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