]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/YQUI.h
restart qt4 porting
[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.h>
24 #include <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 QVBox;
36 class QWidgetStack;
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
525 protected slots:
526
527     /**
528      * Application shutdown
529      **/
530     bool close();
531
532     /**
533      * Timeout during TimeoutUserInput() / WaitForEvent()
534      **/
535     void userInputTimeout();
536
537     /**
538      * Sets @ref #leave_idle_loop to true.
539      **/
540     void leaveIdleLoop( int );
541
542
543 protected:
544
545     /**
546      * Handle command line args
547      **/
548     void processCommandLineArgs( int argc, char **argv );
549
550     /**
551      * Calculate size of `opt(`defaultsize) dialogs
552      **/
553     void calcDefaultSize();
554
555
556     //
557     // Data members
558     //
559
560     /**
561      * Assume presence of a window manager
562      **/
563     bool _have_wm;
564
565     /**
566      * Use the entire available screen
567      **/
568     bool _fullscreen;
569
570     /**
571      * Decorate the toplevel window
572      **/
573     bool _decorate_toplevel_window;
574
575     /**
576      * Container for the widget stack. QWidgetStack cannot handle a WFlags
577      * argument, so this needs to be embedded into something else - and a QVBox
578      * at least handles all the sizeHint and resize stuff.
579      **/
580     QVBox * _main_win;
581
582     /**
583      * Stack for the Qt widgets inside the main window.
584      **/
585     QWidgetStack * _widget_stack;
586
587     /**
588      * Stack to keep track of the stacking order of popup dialogs.
589      **/
590     vector<QWidget *> _popup_stack;
591
592     /**
593      * Numeric ID for defaultsize dialogs for the widget stack
594      **/
595     int _main_dialog_id;
596
597     /**
598      * Size for `opt(`defaultsize) dialogs.
599      **/
600     QSize _default_size;
601
602     /**
603      * A flag used during the idle loop. If it is set to true,
604      * the idle loop is left. This happens, if the ycp-ui-communication
605      * pipe to the ui gets readable.
606      **/
607     bool _leave_idle_loop;
608
609     /**
610      * This flag is set during @ref #userInput in order to tell
611      * @ref #returnNow to call exit_loop, which only may be called
612      * after enter_loop.
613      **/
614     bool _do_exit_loop;
615
616     /**
617      * Window manager close events blocked?
618      **/
619     bool _wm_close_blocked;
620
621     /**
622      * Force new dialogs to the foreground and grab the keyboard focus?
623      * (Only if running without a window manager)
624      **/
625     bool _auto_activate_dialogs;
626
627     /**
628      * Global reference to the UI
629      **/
630     static YQUI * _ui;
631
632     /**
633      * Indicate a fatal error that requires the UI to terminate
634      **/
635     bool _fatal_error;
636
637     /**
638      * Timer for TimeoutUserInput() / WaitForEvent().
639      **/
640     QTimer _user_input_timer;
641
642     /**
643      * Timer for delayed busy cursor
644      **/
645     QTimer _busy_cursor_timer;
646
647     /**
648      * The handler for the single pending event this UI keeps track of
649      **/
650     YSimpleEventHandler _event_handler;
651
652     /**
653      * Saved normal palette
654      **/
655     QPalette _normalPalette;
656
657     /**
658      * Flag: currently using special palette for vision impaired users?
659      **/
660     bool _usingVisionImpairedPalette;
661
662     /**
663      * Flag: Does the user want to use a left-handed mouse?
664      **/
665     bool _leftHandedMouse;
666
667     /**
668      * Flag: Was the user already asked if he wants to use a left-handed mouse?
669      **/
670     bool _askedForLeftHandedMouse;
671 };
672
673
674 #endif // YQUI_h