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