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