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