]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/YQUI.h
follow the widget state - for reference: you don't
[duncan/yast2-qt4.git] / src / YQUI.h
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:         YQUI.h
14
15   Author:       Stefan Hundhammer <sh@suse.de>
16
17 /-*/
18
19 #ifndef YQUI_h
20 #define YQUI_h
21
22 #include <qapplication.h>
23 #include <Qt/qmap.h>
24 #include <Qt/qtimer.h>
25 #include <vector>
26
27 #include "YSimpleEventHandler.h"
28 #include <YUI.h>
29
30 #define YQWidgetMargin  4
31 #define YQWidgetSpacing 4
32 #define YQButtonBorder  3
33
34 class QCursor;
35 class QFrame;
36 class QStackedWidget;
37 class QY2Settings;
38 class YEvent;
39 class YQOptionalWidgetFactory;
40 class YQPackageSelectorPlugin;
41 class YQWidgetFactory;
42 class YQApplication;
43
44 using std::string;
45 using std::vector;
46
47
48 class YQUI: public QObject, public YUI
49 {
50     Q_OBJECT
51 public:
52
53     /**
54      * Constructor.
55      **/
56     YQUI( int           argc,
57           char **       argv,
58           bool          with_threads,
59           const char *  macro_file );
60
61     /**
62      * Destructor.
63      **/
64     ~YQUI();
65
66     /**
67      * Access the global Qt-UI.
68      **/
69     static YQUI * ui() { return _ui; }
70
71
72 protected:
73     /**
74      * Create the widget factory that provides all the createXY() methods for
75      * standard (mandatory, i.e. non-optional) widgets.
76      *
77      * Reimplemented from YUI.
78      **/
79     virtual YWidgetFactory * createWidgetFactory();
80
81     /**
82      * Create the widget factory that provides all the createXY() methods for
83      * optional ("special") widgets and the corresponding hasXYWidget()
84      * methods.
85      *
86      * Reimplemented from YUI.
87      **/
88     virtual YOptionalWidgetFactory * createOptionalWidgetFactory();
89
90     /*
91      * Create the YApplication object that provides global methods.
92      *
93      * Reimplemented from YUI.
94      **/
95     virtual YApplication * createApplication();
96
97 public:
98
99     /**
100      * Return the global YApplication object as YQApplication.
101      *
102      * This will create the Y(Q)Application upon the first call and return a
103      * pointer to the one and only (singleton) Y(Q)Application upon each
104      * subsequent call.  This may throw exceptions if the Y(Q)Application
105      * cannot be created.
106      **/
107     static YQApplication * yqApp();
108
109     /**
110      * Widget event handlers (slots) call this when an event occured that
111      * should be the answer to a UserInput() / PollInput() (etc.) call.
112      *
113      * The UI assumes ownership of the event object that 'event' points to.
114      * In particular, it takes care to delete that object.
115      *
116      * It is an error to pass 0 for 'event'.
117      **/
118     void sendEvent( YEvent * event );
119
120     /**
121      * Returns 'true' if there is any event pending for the specified widget.
122      **/
123     bool eventPendingFor( YWidget * widget ) const
124         { return _event_handler.eventPendingFor( widget ); }
125
126     /**
127      * Returns the last event that isn't processed yet or 0 if there is none.
128      *
129      * The Qt UI keeps track of only one single (the last one) event.
130      **/
131     YEvent * pendingEvent() const { return _event_handler.pendingEvent(); }
132
133     /**
134      * Returns 'false" if the "--no-wm" was specified on the command line, i.e.
135      * we should assume no window manager is running.
136      **/
137     bool haveWM() const { return _have_wm; }
138
139     /**
140      * Returns 'true' if defaultsize windows should use the full screen.
141      **/
142     bool fullscreen() const { return _fullscreen; }
143
144     /**
145      * Returns 'false' if toplevel (defaultsize) windows should not get window
146      * manager decorations, i.e. "--noborder" was specified on the command
147      * line.
148      **/
149     bool decorateToplevelWindow() const { return _decorate_toplevel_window; }
150
151     /**
152      * Returns 'true' if the UI had a fatal error that requires the application
153      * to abort.
154      **/
155     bool fatalError() const { return _fatal_error; }
156
157     /**
158      * Raise a fatal UI error. It will be delivered when it is safe to do so.
159      * The caller should make sure it can continue for some time until the
160      * error is delivered.
161      **/
162     void raiseFatalError() { _fatal_error = true; }
163
164     /**
165      * Returns size for `opt(`defaultsize) dialogs (in one dimension).
166      **/
167     int defaultSize( YUIDimension dim ) const;
168
169     /**
170      * Make a screen shot in .png format and save it to 'filename'.
171      * Opens a file selection box if 'filename' is empty.
172      **/
173     void makeScreenShot( string filename );
174
175     /**
176      * UI-specific runPkgSeleciton method: Start the package selection.
177      * This implementation does the same as UserInput().
178      *
179      * Reimplemented from YUI.
180      **/
181     YCPValue runPkgSelection( YWidget * packageSelector );
182
183     /**
184      * Toggle macro recording (activated by Ctrl-Shift-Alt-M):
185      * Stop macro recording if it is in progress,
186      * open a file selection box and ask for a macro file name to save to and
187      * start recording if no recording has been in progress.
188      **/
189     void toggleRecordMacro();
190
191     /**
192      * Open file selection box and ask for a macro file to play
193      * (activated by Ctrl-Shift-Alt-P)
194      **/
195     void askPlayMacro();
196
197     /**
198      * Issue an internal error: Open popup with that message and wait.
199      *
200      * Reimplemented from YUI.
201      **/
202     void internalError( const char * msg );
203
204
205     /**
206      * Block WM_CLOSE events for the main window.
207      **/
208     void blockWmClose()         { _wm_close_blocked = true;  }
209
210     /**
211      * Unblock WM_CLOSE events for the main window.
212      **/
213     void unblockWmClose()       { _wm_close_blocked = false; }
214
215     /**
216      * Check if dialogs are to be activated automatically
217      **/
218     bool autoActivateDialogs() const { return _auto_activate_dialogs; }
219
220     /**
221      * Change automatic dialog activation
222      **/
223     void setAutoActivateDialogs( bool activate )
224         { _auto_activate_dialogs = activate; }
225
226     /**
227      * Block (or unblock) events. If events are blocked, any event sent
228      * should be ignored until events are unblocked again.
229      *
230      * Reimplemented from YUI.
231      **/
232     virtual void blockEvents( bool block = true )
233         { _event_handler.blockEvents( block ); }
234
235     /**
236      * Returns 'true' if events are currently blocked.
237      *
238      * Reimplemented from YUI.
239      **/
240     virtual bool eventsBlocked() const
241         { return _event_handler.eventsBlocked(); }
242
243     /**
244      * Returns the current product name
245      * ("SuSE Linux", "SuSE Linux Enterprise Server", "United Linux", etc.)
246      * as QString.
247      **/
248     QString productName() const;
249
250     /**
251      * Beep - activate the system (X11) bell.
252      *
253      * Reimplemented from YUI.
254      **/
255     void beep();
256
257
258 public slots:
259
260     /**
261      * Show hourglass cursor.
262      *
263      * Reimplemented from YUI.
264      **/
265     void busyCursor();
266
267     /**
268      * Show pointer cursor.
269      *
270      * Reimplemented from YUI.
271      **/
272     void normalCursor();
273
274     /**
275      * Open file selection box and let the user Save y2logs to that location.
276      * (Shift-F8)
277      **/
278     void askSaveLogs();
279
280     /**
281      * Open dialog to configure logging.
282      * (Shift-F7)
283      **/
284     void askConfigureLogging();
285
286     /**
287      * Fun stuff (release dependent)
288      **/
289     void easterEgg();
290
291     /**
292      * A mouse click with the wrong mouse button was detected - e.g., a right
293      * click on a push button. The user might be left-handed, but his mouse
294      * might not (yet) be configured for left-handed use - e.g., during
295      * installation. Ask him if he would like his mouse temporarily configured
296      * as a left-handed mouse.
297      *
298      * This status can be queried with UI::GetDisplayInfo() ("LeftHandedMouse").
299      **/
300     void maybeLeftHandedUser();
301
302
303 signals:
304     /**
305      * Emitted upon WM_CLOSE
306      **/
307     void wmClose();
308
309
310 protected:
311
312     /**
313      * Idle around until fd_ycp is readable and handle repaints.
314      * This is only used when a separate ui thread is running.
315      *
316      * Reimplemented from YUI.
317      **/
318     void idleLoop( int fd_ycp );
319
320     /**
321      * Return a representation for the glyph symbol specified in UTF-8 encoding
322      * or an empty string to get a default textual representation.
323      *
324      * Reimplemented from YUI.
325      **/
326     YCPString glyph( const YCPSymbol & glyphSymbol );
327
328     /**
329      * Go into event loop until next user input is available.
330      *
331      * Reimplemented from YUI.
332      **/
333     YEvent * userInput( unsigned long timeout_millisec = 0 );
334
335     /**
336      * Check the event queue for user input. Don't wait.
337      *
338      * Reimplemented from YUI.
339      **/
340     YEvent * pollInput();
341
342     /**
343      * Create a dialog.
344      *
345      * Reimplemented from YUI.
346      **/
347     YDialog * createDialog( YWidgetOpt & opt );
348
349     /**
350      * Show and activate a dialog.
351      *
352      * Reimplemented from YUI.
353      **/
354     void showDialog( YDialog * dialog );
355
356     /**
357      * Decativate and close a dialog. This does not delete the dialog yet.
358      *
359      * Reimplemented from YUI.
360      **/
361     void closeDialog( YDialog * dialog );
362
363     /**
364      * Grab show events and work around QWidgetStack bug.
365      *
366      * Reimplemented from QObject.
367      **/
368     bool eventFilter( QObject * obj, QEvent * ev );
369
370     /**
371      * Make all UI windows usable without a mouse - even predefined Qt dialogs
372      * that don't know the UI's dialogs' activate() magic.
373      *
374      * Reimplemented from QObject.
375      **/
376     bool showEventFilter( QObject * obj, QEvent * ev );
377
378
379 public:
380
381     /**
382      *
383      * Open a directory selection box and prompt the user for an existing directory.
384      * [Reimplemented from YUI]
385      *
386      * 'startDir' is the initial directory that is displayed.
387      *
388      * 'headline' is an explanatory text for the directory selection box.
389      * Graphical UIs may omit that if no window manager is running.
390      *
391      * Returns the selected directory name
392      * or 'nil' (YCPVoid() ) if the user canceled the operation.
393      **/
394     YCPValue askForExistingDirectory ( const YCPString & startDir,
395                                        const YCPString & headline );
396
397     /**
398      * Open a file selection box and prompt the user for an existing file.
399      * [Reimplemented from YUI]
400      *
401      * 'startWith' is the initial directory or file.
402      *
403      * 'filter' is one or more blank-separated file patterns, e.g. "*.png *.jpg"
404      *
405      * 'headline' is an explanatory text for the file selection box.
406      * Graphical UIs may omit that if no window manager is running.
407      *
408      * Returns the selected file name
409      * or 'nil' (YCPVoid() ) if the user canceled the operation.
410      **/
411     YCPValue askForExistingFile ( const YCPString & startWith,
412                                   const YCPString & filter,
413                                   const YCPString & headline );
414
415     /**
416      * Open a file selection box and prompt the user for a file to save data to.
417      * Automatically asks for confirmation if the user selects an existing file.
418      * [Reimplemented from YUI]
419      *
420      * 'startWith' is the initial directory or file.
421      *
422      * 'filter' is one or more blank-separated file patterns, e.g. "*.png *.jpg"
423      *
424      * 'headline' is an explanatory text for the file selection box.
425      * Graphical UIs may omit that if no window manager is running.
426      *
427      * Returns the selected file name
428      * or 'nil' (YCPVoid() ) if the user canceled the operation.
429      **/
430     YCPValue askForSaveFileName ( const YCPString & startWith,
431                                   const YCPString & filter,
432                                   const YCPString & headline );
433
434     /**
435      * Lower-level version that works with QStrings and does not change
436      * the mouse cursor.
437      **/
438     QString askForSaveFileName( const QString & startWith,
439                                 const QString & filter,
440                                 const QString & headline );
441
442     /**
443      * main widget
444      **/
445     QWidget* mainWidget();
446
447     /**
448      * Initialize and set a textdomain for gettext()
449      **/
450     static void setTextdomain( const char * domain );
451
452     /**
453      * Returns a high-contrast color palette suitable for vision impaired users.
454      **/
455     static QPalette visionImpairedPalette();
456
457     /**
458      * Returns the normal color palette
459      **/
460     QPalette normalPalette() const { return _normalPalette; }
461
462     /**
463      * Toggle between the vision impaired and the normal color palette.
464      **/
465     void toggleVisionImpairedPalette();
466
467     /**
468      * Returns 'true' if high-contrast colors for vision impaired users is in use.
469      * This should be queried at other places before using custom colors.
470      **/
471     bool usingVisionImpairedPalette() const { return _usingVisionImpairedPalette; }
472
473     /**
474      * Convert logical layout spacing units into device dependent units.
475      * A default size dialog is assumed to be 80x25 layout spacing units
476      * and 640x480 device dependent spacing units.
477      *
478      * Reimplemented from YUI.
479      **/
480     virtual int deviceUnits( YUIDimension dim, float layout_units );
481
482     /**
483      * Convert device dependent units into logical layout spacing units.
484      * A default size dialog is assumed to be 80x25 layout spacing units
485      * and 640x480 device dependent spacing units.
486      *
487      * Reimplemented from YUI.
488      **/
489     virtual float layoutUnits( YUIDimension dim, int device_units );
490
491     /**
492      * Returns the package selector plugin singleton of this UI or creates it
493      * (including loading the plugin lib) if it does not exist yet.
494      **/
495     YQPackageSelectorPlugin * packageSelectorPlugin();
496
497
498 protected:
499
500     /**
501      * Display capabilities.
502      * [Reimplemented from YUI]
503      * See UI builtin GetDisplayInfo() doc for details.
504      **/
505     int  getDisplayWidth();
506     int  getDisplayHeight();
507     int  getDisplayDepth();
508     long getDisplayColors();
509     int  getDefaultWidth();
510     int  getDefaultHeight();
511     bool textMode()                     { return false; }
512     bool hasImageSupport()              { return true;  }
513     bool hasLocalImageSupport()         { return true;  }
514     bool hasAnimationSupport()          { return true;  }
515     bool hasIconSupport()               { return false; }       // not yet
516     bool hasFullUtf8Support()           { return true;  }
517     bool richTextSupportsTable()        { return true; }
518     bool leftHandedMouse()              { return _leftHandedMouse; }
519
520
521     QMap<QString, int>  screenShotNo;
522     QString             screenShotNameTemplate;
523
524 protected slots:
525
526     /**
527      * Application shutdown
528      **/
529     bool close();
530
531     /**
532      * Timeout during TimeoutUserInput() / WaitForEvent()
533      **/
534     void userInputTimeout();
535
536 protected:
537
538     /**
539      * Handle command line args
540      **/
541     void processCommandLineArgs( int argc, char **argv );
542
543     /**
544      * Calculate size of `opt(`defaultsize) dialogs
545      **/
546     void calcDefaultSize();
547
548   void init_ui();
549
550     //
551     // Data members
552     //
553
554     /**
555      * Assume presence of a window manager
556      **/
557     bool _have_wm;
558
559     /**
560      * Use the entire available screen
561      **/
562     bool _fullscreen;
563
564     /**
565      * Decorate the toplevel window
566      **/
567     bool _decorate_toplevel_window;
568
569     /**
570      * Container for the widget stack. QWidgetStack cannot handle a WFlags
571      * argument, so this needs to be embedded into something else - and a QVBox
572      * at least handles all the sizeHint and resize stuff.
573      **/
574     QFrame * _main_win;
575
576     /**
577      * Stack for the Qt widgets inside the main window.
578      **/
579     QStackedWidget * _widget_stack;
580
581     /**
582      * Stack to keep track of the stacking order of popup dialogs.
583      **/
584     vector<QWidget *> _popup_stack;
585
586     /**
587      * Size for `opt(`defaultsize) dialogs.
588      **/
589     QSize _default_size;
590
591     /**
592      * This flag is set during @ref #userInput in order to tell
593      * @ref #returnNow to call exit_loop, which only may be called
594      * after enter_loop.
595      **/
596     bool _do_exit_loop;
597
598     /**
599      * Event loop object. Required since a YaST2 UI needs to react to commands
600      * from the YCP command stream as well as to X11 / Qt events.
601      **/
602     QEventLoop * _eventLoop;
603
604     /**
605      * Window manager close events blocked?
606      **/
607     bool _wm_close_blocked;
608
609     /**
610      * Force new dialogs to the foreground and grab the keyboard focus?
611      * (Only if running without a window manager)
612      **/
613     bool _auto_activate_dialogs;
614
615     /**
616      * Global reference to the UI
617      **/
618     static YQUI * _ui;
619
620     /**
621      * Indicate a fatal error that requires the UI to terminate
622      **/
623     bool _fatal_error;
624
625     /**
626      * Timer for TimeoutUserInput() / WaitForEvent().
627      **/
628     QTimer _user_input_timer;
629
630     /**
631      * Timer for delayed busy cursor
632      **/
633     QTimer *_busy_cursor_timer;
634
635     /**
636      * The handler for the single pending event this UI keeps track of
637      **/
638     YSimpleEventHandler _event_handler;
639
640     /**
641      * Saved normal palette
642      **/
643     QPalette _normalPalette;
644
645     /**
646      * Flag: currently using special palette for vision impaired users?
647      **/
648     bool _usingVisionImpairedPalette;
649
650     /**
651      * Flag: Does the user want to use a left-handed mouse?
652      **/
653     bool _leftHandedMouse;
654
655     /**
656      * Flag: Was the user already asked if he wants to use a left-handed mouse?
657      **/
658     bool _askedForLeftHandedMouse;
659
660   bool _ui_inited;
661   int _ui_argc;
662   char **_ui_argv;
663 };
664
665 #endif // YQUI_h