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