]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/YQUI.h
5141e0807abfa0cf79eea77a38c227982d8c4c5d
[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      * Create a dialog.
345      *
346      * Reimplemented from YUI.
347      **/
348     YDialog * createDialog( YWidgetOpt & opt );
349
350     /**
351      * Show and activate a dialog.
352      *
353      * Reimplemented from YUI.
354      **/
355     void showDialog( YDialog * dialog );
356
357     /**
358      * Decativate and close a dialog. This does not delete the dialog yet.
359      *
360      * Reimplemented from YUI.
361      **/
362     void closeDialog( YDialog * dialog );
363
364     /**
365      * Grab show events and work around QWidgetStack bug.
366      *
367      * Reimplemented from QObject.
368      **/
369     bool eventFilter( QObject * obj, QEvent * ev );
370
371     /**
372      * Make all UI windows usable without a mouse - even predefined Qt dialogs
373      * that don't know the UI's dialogs' activate() magic.
374      *
375      * Reimplemented from QObject.
376      **/
377     bool showEventFilter( QObject * obj, QEvent * ev );
378
379
380 public:
381
382     /**
383      *
384      * Open a directory selection box and prompt the user for an existing directory.
385      * [Reimplemented from YUI]
386      *
387      * 'startDir' is the initial directory that is displayed.
388      *
389      * 'headline' is an explanatory text for the directory selection box.
390      * Graphical UIs may omit that if no window manager is running.
391      *
392      * Returns the selected directory name
393      * or 'nil' (YCPVoid() ) if the user canceled the operation.
394      **/
395     YCPValue askForExistingDirectory ( const YCPString & startDir,
396                                        const YCPString & headline );
397
398     /**
399      * Open a file selection box and prompt the user for an existing file.
400      * [Reimplemented from YUI]
401      *
402      * 'startWith' is the initial directory or file.
403      *
404      * 'filter' is one or more blank-separated file patterns, e.g. "*.png *.jpg"
405      *
406      * 'headline' is an explanatory text for the file selection box.
407      * Graphical UIs may omit that if no window manager is running.
408      *
409      * Returns the selected file name
410      * or 'nil' (YCPVoid() ) if the user canceled the operation.
411      **/
412     YCPValue askForExistingFile ( const YCPString & startWith,
413                                   const YCPString & filter,
414                                   const YCPString & headline );
415
416     /**
417      * Open a file selection box and prompt the user for a file to save data to.
418      * Automatically asks for confirmation if the user selects an existing file.
419      * [Reimplemented from YUI]
420      *
421      * 'startWith' is the initial directory or file.
422      *
423      * 'filter' is one or more blank-separated file patterns, e.g. "*.png *.jpg"
424      *
425      * 'headline' is an explanatory text for the file selection box.
426      * Graphical UIs may omit that if no window manager is running.
427      *
428      * Returns the selected file name
429      * or 'nil' (YCPVoid() ) if the user canceled the operation.
430      **/
431     YCPValue askForSaveFileName ( const YCPString & startWith,
432                                   const YCPString & filter,
433                                   const YCPString & headline );
434
435     /**
436      * Lower-level version that works with QStrings and does not change
437      * the mouse cursor.
438      **/
439     QString askForSaveFileName( const QString & startWith,
440                                 const QString & filter,
441                                 const QString & headline );
442
443     /**
444      * main widget
445      **/
446     QWidget* mainWidget();
447
448     /**
449      * Initialize and set a textdomain for gettext()
450      **/
451     static void setTextdomain( const char * domain );
452
453     /**
454      * Returns a high-contrast color palette suitable for vision impaired users.
455      **/
456     static QPalette visionImpairedPalette();
457
458     /**
459      * Returns the normal color palette
460      **/
461     QPalette normalPalette() const { return _normalPalette; }
462
463     /**
464      * Toggle between the vision impaired and the normal color palette.
465      **/
466     void toggleVisionImpairedPalette();
467
468     /**
469      * Returns 'true' if high-contrast colors for vision impaired users is in use.
470      * This should be queried at other places before using custom colors.
471      **/
472     bool usingVisionImpairedPalette() const { return _usingVisionImpairedPalette; }
473
474     /**
475      * Convert logical layout spacing units into device dependent units.
476      * A default size dialog is assumed to be 80x25 layout spacing units
477      * and 640x480 device dependent spacing units.
478      *
479      * Reimplemented from YUI.
480      **/
481     virtual int deviceUnits( YUIDimension dim, float layout_units );
482
483     /**
484      * Convert device dependent units into logical layout spacing units.
485      * A default size dialog is assumed to be 80x25 layout spacing units
486      * and 640x480 device dependent spacing units.
487      *
488      * Reimplemented from YUI.
489      **/
490     virtual float layoutUnits( YUIDimension dim, int device_units );
491
492     /**
493      * Returns the package selector plugin singleton of this UI or creates it
494      * (including loading the plugin lib) if it does not exist yet.
495      **/
496     YQPackageSelectorPlugin * packageSelectorPlugin();
497
498
499 protected:
500
501     /**
502      * Display capabilities.
503      * [Reimplemented from YUI]
504      * See UI builtin GetDisplayInfo() doc for details.
505      **/
506     int  getDisplayWidth();
507     int  getDisplayHeight();
508     int  getDisplayDepth();
509     long getDisplayColors();
510     int  getDefaultWidth();
511     int  getDefaultHeight();
512     bool textMode()                     { return false; }
513     bool hasImageSupport()              { return true;  }
514     bool hasLocalImageSupport()         { return true;  }
515     bool hasAnimationSupport()          { return true;  }
516     bool hasIconSupport()               { return false; }       // not yet
517     bool hasFullUtf8Support()           { return true;  }
518     bool richTextSupportsTable()        { return true; }
519     bool leftHandedMouse()              { return _leftHandedMouse; }
520
521
522     QMap<QString, int>  screenShotNo;
523     QString             screenShotNameTemplate;
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 protected:
538
539     /**
540      * Handle command line args
541      **/
542     void processCommandLineArgs( int argc, char **argv );
543
544     /**
545      * Calculate size of `opt(`defaultsize) dialogs
546      **/
547     void calcDefaultSize();
548
549   void init_ui();
550
551     //
552     // Data members
553     //
554
555     /**
556      * Assume presence of a window manager
557      **/
558     bool _have_wm;
559
560     /**
561      * Use the entire available screen
562      **/
563     bool _fullscreen;
564
565     /**
566      * Decorate the toplevel window
567      **/
568     bool _decorate_toplevel_window;
569
570     /**
571      * Container for the widget stack. QWidgetStack cannot handle a WFlags
572      * argument, so this needs to be embedded into something else - and a QVBox
573      * at least handles all the sizeHint and resize stuff.
574      **/
575     QFrame * _main_win;
576
577     /**
578      * Stack for the Qt widgets inside the main window.
579      **/
580     QStackedWidget * _widget_stack;
581
582     /**
583      * Stack to keep track of the stacking order of popup dialogs.
584      **/
585     vector<QWidget *> _popup_stack;
586
587     /**
588      * Size for `opt(`defaultsize) dialogs.
589      **/
590     QSize _default_size;
591
592     /**
593      * This flag is set during @ref #userInput in order to tell
594      * @ref #returnNow to call exit_loop, which only may be called
595      * after enter_loop.
596      **/
597     bool _do_exit_loop;
598
599     /**
600      * Event loop object. Required since a YaST2 UI needs to react to commands
601      * from the YCP command stream as well as to X11 / Qt events.
602      **/
603     QEventLoop * _eventLoop;
604
605     /**
606      * Window manager close events blocked?
607      **/
608     bool _wm_close_blocked;
609
610     /**
611      * Force new dialogs to the foreground and grab the keyboard focus?
612      * (Only if running without a window manager)
613      **/
614     bool _auto_activate_dialogs;
615
616     /**
617      * Global reference to the UI
618      **/
619     static YQUI * _ui;
620
621     /**
622      * Indicate a fatal error that requires the UI to terminate
623      **/
624     bool _fatal_error;
625
626     /**
627      * Timer for TimeoutUserInput() / WaitForEvent().
628      **/
629     QTimer _user_input_timer;
630
631     /**
632      * Timer for delayed busy cursor
633      **/
634     QTimer *_busy_cursor_timer;
635
636     /**
637      * The handler for the single pending event this UI keeps track of
638      **/
639     YSimpleEventHandler _event_handler;
640
641     /**
642      * Saved normal palette
643      **/
644     QPalette _normalPalette;
645
646     /**
647      * Flag: currently using special palette for vision impaired users?
648      **/
649     bool _usingVisionImpairedPalette;
650
651     /**
652      * Flag: Does the user want to use a left-handed mouse?
653      **/
654     bool _leftHandedMouse;
655
656     /**
657      * Flag: Was the user already asked if he wants to use a left-handed mouse?
658      **/
659     bool _askedForLeftHandedMouse;
660
661   bool _ui_inited;
662   int _ui_argc;
663   char **_ui_argv;
664 };
665
666 #endif // YQUI_h