]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/YQDialog.cc
clicking packages work! so the package selector is now
[duncan/yast2-qt4.git] / src / YQDialog.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:         YQDialog.cc
14
15   Author:       Stefan Hundhammer <sh@suse.de>
16
17   Textdomain    "packages-qt"
18
19 /-*/
20
21
22 #define y2log_component "qt-ui"
23 #include <ycp/y2log.h>
24 #include <qpushbutton.h>
25 #include <qmessagebox.h>
26 #include <QDesktopWidget>
27 #include <QDebug>
28
29 #include "YQUI.h"
30 #include "YQi18n.h"
31 #include "YEvent.h"
32 #include "YQDialog.h"
33 #include "YQGenericButton.h"
34 #include "YQWizardButton.h"
35 #include "YQWizard.h"
36 #include "YQMainWinDock.h"
37
38 // Include low-level X headers AFTER Qt headers:
39 // X.h pollutes the global namespace (!!!) with pretty useless #defines
40 // like "Above", "Below" etc. that clash with some Qt headers.
41 #include <X11/Xlib.h>
42
43 #define YQMainDialogWFlags      Qt::Widget
44
45 #define YQPopupDialogWFlags     Qt::Dialog
46
47
48 YQDialog::YQDialog( YDialogType         dialogType,
49                     YDialogColorMode    colorMode )
50     : QWidget( chooseParent( dialogType ),
51                dialogType == YMainDialog ? YQMainDialogWFlags : YQPopupDialogWFlags )
52     , YDialog( dialogType, colorMode )
53 {
54     setWidgetRep( this );
55
56     _userResized        = false;
57     _focusButton        = 0;
58     _defaultButton      = 0;
59
60     setWindowTitle( "YaST2" );
61     setFocusPolicy( Qt::StrongFocus );
62
63     if ( colorMode != YDialogNormalColor )
64     {
65         QColor normalBackground     ( 0, 128, 0 );
66         QColor inputFieldBackground ( 0xbb,  0xff, 0xbb );
67         QColor text = Qt::white;
68
69         if ( colorMode == YDialogInfoColor )
70         {
71             normalBackground = QColor ( 238, 232, 170 ); // PaleGoldenrod
72         }
73
74         QPalette warnPalette( normalBackground );
75         warnPalette.setColor( QPalette::Text, text );
76         warnPalette.setColor( QPalette::Base, inputFieldBackground );
77         setPalette( warnPalette );
78     }
79
80     if ( dialogType == YMainDialog &&
81          QWidget::parent() != YQMainWinDock::mainWinDock() )
82     {
83         setWindowFlags( YQPopupDialogWFlags );
84     }
85
86     if ( QWidget::parent() == YQMainWinDock::mainWinDock() )
87     {
88         YQMainWinDock::mainWinDock()->add( this );
89     }
90 }
91
92
93 YQDialog::~YQDialog()
94 {
95     if ( dialogType() == YMainDialog )
96     {
97         YQMainWinDock::mainWinDock()->remove( this );
98     }
99     if ( _defaultButton )
100        _defaultButton->forgetDialog();
101     if ( _focusButton )
102        _focusButton->forgetDialog();
103 }
104
105
106 QWidget *
107 YQDialog::chooseParent( YDialogType dialogType )
108 {
109     QWidget * parent = 0;
110
111     if ( dialogType == YMainDialog &&
112          YQMainWinDock::mainWinDock()->couldDock() )
113     {
114         y2debug( "Adding dialog to mainWinDock" );
115         parent = YQMainWinDock::mainWinDock();
116     }
117
118     return parent;
119 }
120
121
122 int
123 YQDialog::preferredWidth()
124 {
125     int preferredWidth;
126
127     if ( dialogType() == YMainDialog )
128     {
129         if ( userResized() )
130             preferredWidth = _userSize.width();
131         else
132             preferredWidth = YQUI::ui()->defaultSize( YD_HORIZ );
133     }
134     else
135     {
136         preferredWidth = YDialog::preferredWidth();
137     }
138
139     int screenWidth = qApp->desktop()->width();
140
141     if ( preferredWidth > screenWidth )
142     {
143         y2warning( "Limiting dialog width to screen width (%d) instead of %d - check the layout!",
144                    screenWidth, preferredWidth );
145     }
146
147     return preferredWidth;
148 }
149
150
151 int
152 YQDialog::preferredHeight()
153 {
154     int preferredHeight;
155
156     if ( dialogType() == YMainDialog )
157     {
158         if ( userResized() )
159             preferredHeight = _userSize.height();
160         else
161             preferredHeight = YQUI::ui()->defaultSize( YD_VERT );
162     }
163     else
164     {
165         preferredHeight = YDialog::preferredHeight();
166     }
167
168     int screenHeight = qApp->desktop()->height();
169
170     if ( preferredHeight > screenHeight )
171     {
172         y2warning( "Limiting dialog height to screen height (%d) instead of %d - check the layout!",
173                    screenHeight, preferredHeight );
174     }
175
176     return preferredHeight;
177 }
178
179
180 void
181 YQDialog::setEnabled( bool enabled )
182 {
183     QWidget::setEnabled( enabled );
184     YDialog::setEnabled( enabled );
185 }
186
187
188 void
189 YQDialog::setSize( int newWidth, int newHeight )
190 {
191     // y2debug( "Resizing dialog to %d x %d", newWidth, newHeight );
192
193     if ( newWidth > qApp->desktop()->width() )
194         newWidth = qApp->desktop()->width();
195
196     if ( newHeight > qApp->desktop()->height() )
197         newHeight = qApp->desktop()->height();
198
199     if ( hasChildren() )
200     {
201         ( ( QWidget* )firstChild()->widgetRep() )->show();
202         firstChild()->setSize( newWidth, newHeight );
203     }
204
205     resize( newWidth, newHeight );
206 }
207
208
209 void
210 YQDialog::activate( bool active )
211 {
212     if ( active )
213     {
214         ensureOnlyOneDefaultButton();
215     }
216 }
217
218
219 void
220 YQDialog::resizeEvent( QResizeEvent * event )
221 {
222     if ( event )
223     {
224         // y2debug( "Resize event: %d x %d", event->size().width(), event->size().height() );
225         setSize ( event->size().width(), event->size().height() );
226         _userSize = event->size();
227
228         if ( QWidget::parent() )
229             _userResized = true;
230     }
231 }
232
233
234 YQGenericButton *
235 YQDialog::findDefaultButton()
236 {
237     if ( _defaultButton )
238         return _defaultButton;
239
240     _defaultButton = findDefaultButton( childrenBegin(), childrenEnd() );
241
242     YDialog::setDefaultButton( 0 ); // prevent complaints about multiple default buttons
243     YDialog::setDefaultButton( _defaultButton );
244
245     return _defaultButton;
246 }
247
248
249 YQGenericButton *
250 YQDialog::findDefaultButton( YWidgetListConstIterator begin,
251                              YWidgetListConstIterator end ) const
252
253 {
254     for ( YWidgetListConstIterator it = begin; it != end; ++it )
255     {
256         YWidget * widget = *it;
257
258         //
259         // Check this widget
260         //
261
262         YQGenericButton * button = dynamic_cast<YQGenericButton *> (widget);
263
264         if ( button && button->isDefaultButton() )
265         {
266             return button;
267         }
268
269
270         //
271         // Recurse over the children of this widget
272         //
273
274         if ( widget->hasChildren() )
275         {
276             button = findDefaultButton( widget->childrenBegin(),
277                                         widget->childrenEnd() );
278             if ( button )
279                 return button;
280         }
281     }
282
283     return 0;
284 }
285
286
287 YQWizard *
288 YQDialog::ensureOnlyOneDefaultButton( YWidgetListConstIterator begin,
289                                       YWidgetListConstIterator end )
290 {
291     YQGenericButton * def  = _focusButton ? _focusButton : _defaultButton;
292     YQWizard * wizard = 0;
293
294     for ( YWidgetListConstIterator it = begin; it != end; ++it )
295     {
296         YQGenericButton * button       = dynamic_cast<YQGenericButton *> (*it);
297         YQWizardButton  * wizardButton = dynamic_cast<YQWizardButton * > (*it);
298
299         if ( ! wizard )
300             wizard = dynamic_cast<YQWizard *> (*it);
301
302         if ( wizardButton )
303         {
304             wizardButton->showAsDefault( false );
305         }
306         else if ( button )
307         {
308             if ( button->isDefaultButton() )
309             {
310                 if ( _defaultButton && button != _defaultButton )
311                 {
312                     y2error( "Too many default buttons: [%s]",
313                              qPrintable(button->text()) );
314                     y2error( "Using old default button: [%s]",
315                              qPrintable(_defaultButton->text()) );
316                 }
317                 else
318                 {
319                     _defaultButton = button;
320                 }
321             }
322
323             if ( button->isShownAsDefault() && button != def )
324                 button->showAsDefault( false );
325         }
326
327         if ( (*it)->hasChildren() )
328         {
329             YQWizard * wiz = ensureOnlyOneDefaultButton( (*it)->childrenBegin(),
330                                                          (*it)->childrenEnd() );
331             if ( wiz )
332                 wizard = wiz;
333         }
334     }
335
336     return wizard;
337 }
338
339
340 void
341 YQDialog::ensureOnlyOneDefaultButton()
342 {
343     _defaultButton = 0;
344     YQWizard * wizard = ensureOnlyOneDefaultButton( childrenBegin(), childrenEnd() );
345
346     if ( ! _defaultButton && wizard )
347     {
348         _defaultButton = wizardDefaultButton( wizard );
349     }
350
351     if ( _defaultButton )
352     {
353         YDialog::setDefaultButton( 0 ); // prevent complaints about multiple default buttons
354         YDialog::setDefaultButton( _defaultButton );
355     }
356
357
358     YQGenericButton * def  = _focusButton ? _focusButton : _defaultButton;
359
360     if ( def )
361         def->showAsDefault();
362 }
363
364
365 YQWizard *
366 YQDialog::findWizard() const
367 {
368     return findWizard( childrenBegin(), childrenEnd() );
369 }
370
371
372 YQWizard *
373 YQDialog::findWizard( YWidgetListConstIterator begin,
374                       YWidgetListConstIterator end ) const
375 {
376     for ( YWidgetListConstIterator it = begin; it != end; ++it )
377     {
378         YWidget * widget = *it;
379         YQWizard * wizard = dynamic_cast<YQWizard *> (widget);
380
381         if ( wizard )
382             return wizard;
383
384         if ( widget->hasChildren() )
385         {
386             wizard = findWizard( widget->childrenBegin(),
387                                  widget->childrenEnd() );
388             if ( wizard )
389                 return wizard;
390         }
391     }
392
393     return 0;
394 }
395
396
397 YQGenericButton *
398 YQDialog::wizardDefaultButton( YQWizard * wizard ) const
399 {
400     YQGenericButton * def = 0;
401
402     if ( ! wizard )
403         wizard = findWizard();
404
405     if ( wizard )
406     {
407         // Pick one of the wizard buttons
408
409         if ( wizard->direction() == YQWizard::Backward )
410         {
411             if ( wizard->backButton()
412                  && wizard->backButton()->isShown()
413                  && wizard->backButton()->isEnabled() )
414             {
415                 def = wizard->backButton();
416             }
417         }
418
419         if ( ! def )
420         {
421             if ( wizard->nextButton()
422                  && wizard->nextButton()->isShown()
423                  && wizard->nextButton()->isEnabled() )
424             {
425                 def = wizard->nextButton();
426             }
427         }
428     }
429
430     return def;
431 }
432
433
434 void
435 YQDialog::setDefaultButton( YPushButton * newDefaultButton )
436 {
437     if ( _defaultButton   &&
438          newDefaultButton &&
439          newDefaultButton != _defaultButton )
440     {
441         if ( dynamic_cast<YQWizardButton *>( _defaultButton ) )
442         {
443             // Let app defined default buttons override wizard buttons
444             _defaultButton->setDefaultButton( false );
445         }
446         else
447         {
448             y2error( "Too many `opt(`default) PushButtons: [%s]",
449                      newDefaultButton->label().c_str() );
450             newDefaultButton->setDefaultButton( false );
451             return;
452         }
453     }
454
455     _defaultButton = dynamic_cast<YQGenericButton*>(newDefaultButton);
456
457     if ( _defaultButton )
458     {
459         _defaultButton->setDefaultButton( true );
460         y2debug( "New default button: [%s]", qPrintable(_defaultButton->text()) );
461
462         if ( _defaultButton && ! _focusButton )
463             _defaultButton->showAsDefault( true );
464     }
465
466
467     YDialog::setDefaultButton( 0 ); // prevent complaints about multiple default buttons
468     YDialog::setDefaultButton( _defaultButton );
469 }
470
471
472 bool
473 YQDialog::activateDefaultButton( bool warn )
474 {
475     // Try the focus button first, if there is any.
476
477     if ( _focusButton              &&
478          _focusButton->isEnabled() &&
479          _focusButton->isShownAsDefault() )
480     {
481         y2debug( "Activating focus button: [%s]", qPrintable(_focusButton->text()) );
482         _focusButton->activate();
483         return true;
484     }
485
486
487     // No focus button - try the default button, if there is any.
488
489     _defaultButton = findDefaultButton();
490
491     if ( _defaultButton                 &&
492          _defaultButton->isEnabled()    &&
493          _defaultButton->isShownAsDefault() )
494     {
495         y2debug( "Activating default button: [%s]", qPrintable(_defaultButton->text()) );
496         _defaultButton->activate();
497         return true;
498     }
499     else
500     {
501         if ( warn )
502         {
503             y2warning( "No default button in this dialog - ignoring [Return]" );
504         }
505     }
506
507     return false;
508 }
509
510
511 void
512 YQDialog::losingFocus( YQGenericButton * button )
513 {
514     if ( button == _focusButton )
515     {
516         if ( _focusButton && _focusButton != _defaultButton )
517             _focusButton->showAsDefault( false );
518
519         _focusButton = 0;
520     }
521
522     if ( ! _focusButton && _defaultButton )
523         _defaultButton->showAsDefault( true );
524 }
525
526
527 void
528 YQDialog::gettingFocus( YQGenericButton * button )
529 {
530     if ( _focusButton && _focusButton != button )
531         _focusButton->showAsDefault( false );
532
533     if ( _defaultButton && _defaultButton != button )
534         _defaultButton->showAsDefault( false );
535
536     _focusButton = button;
537
538     if ( _focusButton )
539         _focusButton->showAsDefault( true );
540 }
541
542
543 void
544 YQDialog::keyPressEvent( QKeyEvent * event )
545 {
546     if ( event )
547     {
548         if ( event->key() == Qt::Key_Print )
549         {
550             YQUI::ui()->makeScreenShot( "" );
551             return;
552         }
553         else if ( event->key()   == Qt::Key_F4 &&       // Shift-F4: toggle colors for vision impaired users
554                   event->modifiers() & Qt::ShiftModifier )
555         {
556             YQUI::ui()->toggleVisionImpairedPalette();
557
558             if ( YQUI::ui()->usingVisionImpairedPalette() )
559             {
560                 y2milestone( "Switched to vision impaired palette" );
561                 QMessageBox::information( 0,                                            // parent
562                                           _("Color switching"),                         // caption
563                                           _( "Switching to color palette for vision impaired users -\n"
564                                              "press Shift-F4 again to switch back to normal colors."   ), // text
565                                           QMessageBox::Ok | QMessageBox::Default,       // button0
566                                           QMessageBox::NoButton,                        // button1
567                                           QMessageBox::NoButton );                      // button2
568             }
569             return;
570         }
571         else if ( event->key()   == Qt::Key_F7 &&       // Shift-F7: toggle y2debug logging
572                   event->modifiers() == Qt::ShiftModifier )
573         {
574             YQUI::ui()->askConfigureLogging();
575             return;
576         }
577         else if ( event->key()   == Qt::Key_F8 &&       // Shift-F8: save y2logs
578                   event->modifiers() & Qt::ShiftModifier )
579         {
580             YQUI::ui()->askSaveLogs();
581             return;
582         }
583         else if ( event->modifiers() & Qt::NoModifier )                 // No Ctrl / Alt / Shift etc. pressed
584         {
585             if ( event->key() == Qt::Key_Return ||
586                  event->key() == Qt::Key_Enter    )
587             {
588                 ( void ) activateDefaultButton();
589                 return;
590             }
591         }
592         else if ( event->modifiers() & ( Qt::ControlModifier | Qt::ShiftModifier | Qt::AltModifier ) )
593         {
594             // Qt-UI special keys - all with Ctrl-Shift-Alt
595
596             y2milestone( "Caught YaST2 magic key combination" );
597
598             if ( event->key() == Qt::Key_M )
599             {
600                 YQUI::ui()->toggleRecordMacro();
601                 return;
602             }
603             else if ( event->key() == Qt::Key_P )
604             {
605                 YQUI::ui()->askPlayMacro();
606                 return;
607             }
608             else if ( event->key() == Qt::Key_D )
609             {
610                 YQUI::ui()->sendEvent( new YDebugEvent() );
611                 return;
612             }
613             else if ( event->key() == Qt::Key_X )
614             {
615                 y2milestone( "Starting xterm" );
616                 system( "/usr/bin/xterm &" );
617                 return;
618             }
619         }
620     }
621
622     QWidget::keyPressEvent( event );
623 }
624
625
626 void
627 YQDialog::closeEvent( QCloseEvent * event )
628 {
629     // The window manager "close window" button (and WM menu, e.g. Alt-F4) will be
630     // handled just like the user had clicked on the `id`( `cancel ) button in
631     // that dialog. It's up to the YCP application to handle this (if desired).
632
633     y2milestone( "Caught window manager close event - returning with YCancelEvent" );
634     event->ignore();
635     YQUI::ui()->sendEvent( new YCancelEvent() );
636 }
637
638
639 void
640 YQDialog::focusInEvent( QFocusEvent * event )
641 {
642
643     // The dialog itself doesn't need or want the keyboard focus, but obviously
644     // (since Qt 2.3?) it needs QFocusPolicy::StrongFocus for the default
645     // button mechanism to work. So let's accept the focus and give it to some
646     // child widget.
647
648     if ( event->reason() == Qt::TabFocusReason )
649     {
650         focusNextPrevChild( true );
651     }
652     else
653     {
654         if ( _defaultButton )
655             _defaultButton->setKeyboardFocus();
656         else
657             focusNextPrevChild( true );
658     }
659 }
660
661
662 void
663 YQDialog::center( QWidget * dialog, QWidget * parent )
664 {
665     if ( ! dialog || ! parent )
666         return;
667
668     qDebug() << "center" << parent->rect() << dialog->rect();
669
670     QPoint pos( ( parent->width()  - dialog->width()  ) / 2,
671                 ( parent->height() - dialog->height() ) / 2 );
672
673     pos += parent->mapToGlobal( QPoint( 0, 0 ) );
674     pos = dialog->mapToParent( dialog->mapFromGlobal( pos ) );
675     qDebug() << pos;
676     dialog->move( pos );
677 }
678
679
680
681 #include "YQDialog.moc"