1 /*---------------------------------------------------------------------\
3 | __ __ ____ _____ ____ |
4 | \ \ / /_ _/ ___|_ _|___ \ |
5 | \ V / _` \___ \ | | __) | |
6 | | | (_| |___) || | / __/ |
7 | |_|\__,_|____/ |_| |_____| |
11 \----------------------------------------------------------------------/
15 Author: Stefan Hundhammer <sh@suse.de>
22 #include <qapplication.h>
28 #include "YSimpleEventHandler.h"
31 #define YQWidgetMargin 4
32 #define YQWidgetSpacing 4
33 #define YQButtonBorder 3
41 class YQOptionalWidgetFactory;
42 class YQPackageSelectorPlugin;
43 class YQWidgetFactory;
50 class YQUI: public QObject, public YUI
61 const char * macro_file );
69 * Access the global Qt-UI.
71 static YQUI * ui() { return _ui; }
76 * Create the widget factory that provides all the createXY() methods for
77 * standard (mandatory, i.e. non-optional) widgets.
79 * Reimplemented from YUI.
81 virtual YWidgetFactory * createWidgetFactory();
84 * Create the widget factory that provides all the createXY() methods for
85 * optional ("special") widgets and the corresponding hasXYWidget()
88 * Reimplemented from YUI.
90 virtual YOptionalWidgetFactory * createOptionalWidgetFactory();
93 * Create the YApplication object that provides global methods.
95 * Reimplemented from YUI.
97 virtual YApplication * createApplication();
102 * Return the global YApplication object as YQApplication.
104 * This will create the Y(Q)Application upon the first call and return a
105 * pointer to the one and only (singleton) Y(Q)Application upon each
106 * subsequent call. This may throw exceptions if the Y(Q)Application
109 static YQApplication * yqApp();
112 * Widget event handlers (slots) call this when an event occured that
113 * should be the answer to a UserInput() / PollInput() (etc.) call.
115 * The UI assumes ownership of the event object that 'event' points to.
116 * In particular, it takes care to delete that object.
118 * It is an error to pass 0 for 'event'.
120 void sendEvent( YEvent * event );
123 * Returns 'true' if there is any event pending for the specified widget.
125 bool eventPendingFor( YWidget * widget ) const
126 { return _event_handler.eventPendingFor( widget ); }
129 * Returns the last event that isn't processed yet or 0 if there is none.
131 * The Qt UI keeps track of only one single (the last one) event.
133 YEvent * pendingEvent() const { return _event_handler.pendingEvent(); }
136 * Returns 'false" if the "--no-wm" was specified on the command line, i.e.
137 * we should assume no window manager is running.
139 bool haveWM() const { return _have_wm; }
142 * Returns 'true' if defaultsize windows should use the full screen.
144 bool fullscreen() const { return _fullscreen; }
147 * Returns 'false' if toplevel (defaultsize) windows should not get window
148 * manager decorations, i.e. "--noborder" was specified on the command
151 bool decorateToplevelWindow() const { return _decorate_toplevel_window; }
154 * Returns 'true' if the UI had a fatal error that requires the application
157 bool fatalError() const { return _fatal_error; }
160 * Raise a fatal UI error. It will be delivered when it is safe to do so.
161 * The caller should make sure it can continue for some time until the
162 * error is delivered.
164 void raiseFatalError() { _fatal_error = true; }
167 * Returns size for `opt(`defaultsize) dialogs (in one dimension).
169 int defaultSize( YUIDimension dim ) const;
172 * Make a screen shot in .png format and save it to 'filename'.
173 * Opens a file selection box if 'filename' is empty.
175 void makeScreenShot( string filename );
178 * UI-specific runPkgSeleciton method: Start the package selection.
179 * This implementation does the same as UserInput().
181 * Reimplemented from YUI.
183 YCPValue runPkgSelection( YWidget * packageSelector );
186 * Toggle macro recording (activated by Ctrl-Shift-Alt-M):
187 * Stop macro recording if it is in progress,
188 * open a file selection box and ask for a macro file name to save to and
189 * start recording if no recording has been in progress.
191 void toggleRecordMacro();
194 * Open file selection box and ask for a macro file to play
195 * (activated by Ctrl-Shift-Alt-P)
200 * Issue an internal error: Open popup with that message and wait.
202 * Reimplemented from YUI.
204 void internalError( const char * msg );
208 * Block WM_CLOSE events for the main window.
210 void blockWmClose() { _wm_close_blocked = true; }
213 * Unblock WM_CLOSE events for the main window.
215 void unblockWmClose() { _wm_close_blocked = false; }
218 * Check if dialogs are to be activated automatically
220 bool autoActivateDialogs() const { return _auto_activate_dialogs; }
223 * Change automatic dialog activation
225 void setAutoActivateDialogs( bool activate )
226 { _auto_activate_dialogs = activate; }
229 * Block (or unblock) events. If events are blocked, any event sent
230 * should be ignored until events are unblocked again.
232 * Reimplemented from YUI.
234 virtual void blockEvents( bool block = true );
237 * Returns 'true' if events are currently blocked.
239 * Reimplemented from YUI.
241 virtual bool eventsBlocked() const;
244 * Returns the current product name
245 * ("SuSE Linux", "SuSE Linux Enterprise Server", "United Linux", etc.)
248 QString productName() const;
251 * Beep - activate the system (X11) bell.
253 * Reimplemented from YUI.
261 * Show hourglass cursor.
263 * Reimplemented from YUI.
268 * Show pointer cursor.
270 * Reimplemented from YUI.
275 * Open file selection box and let the user Save y2logs to that location.
281 * Open dialog to configure logging.
284 void askConfigureLogging();
287 * Fun stuff (release dependent)
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.
298 * This status can be queried with UI::GetDisplayInfo() ("LeftHandedMouse").
300 void maybeLeftHandedUser();
305 * Emitted upon WM_CLOSE
313 * Idle around until fd_ycp is readable and handle repaints.
314 * This is only used when a separate ui thread is running.
316 * Reimplemented from YUI.
318 void idleLoop( int fd_ycp );
321 * Return a representation for the glyph symbol specified in UTF-8 encoding
322 * or an empty string to get a default textual representation.
324 * Reimplemented from YUI.
326 YCPString glyph( const YCPSymbol & glyphSymbol );
329 * Go into event loop until next user input is available.
331 * Reimplemented from YUI.
333 YEvent * userInput( unsigned long timeout_millisec = 0 );
336 * Check the event queue for user input. Don't wait.
338 * Reimplemented from YUI.
340 YEvent * pollInput();
343 * Show and activate a dialog.
345 * Reimplemented from YUI.
347 void showDialog( YDialog * dialog );
350 * Decativate and close a dialog. This does not delete the dialog yet.
352 * Reimplemented from YUI.
354 void closeDialog( YDialog * dialog );
357 * Grab show events and work around QWidgetStack bug.
359 * Reimplemented from QObject.
361 bool eventFilter( QObject * obj, QEvent * ev );
364 * Make all UI windows usable without a mouse - even predefined Qt dialogs
365 * that don't know the UI's dialogs' activate() magic.
367 * Reimplemented from QObject.
369 bool showEventFilter( QObject * obj, QEvent * ev );
376 * Open a directory selection box and prompt the user for an existing directory.
377 * [Reimplemented from YUI]
379 * 'startDir' is the initial directory that is displayed.
381 * 'headline' is an explanatory text for the directory selection box.
382 * Graphical UIs may omit that if no window manager is running.
384 * Returns the selected directory name
385 * or 'nil' (YCPVoid() ) if the user canceled the operation.
387 YCPValue askForExistingDirectory ( const YCPString & startDir,
388 const YCPString & headline );
391 * Open a file selection box and prompt the user for an existing file.
392 * [Reimplemented from YUI]
394 * 'startWith' is the initial directory or file.
396 * 'filter' is one or more blank-separated file patterns, e.g. "*.png *.jpg"
398 * 'headline' is an explanatory text for the file selection box.
399 * Graphical UIs may omit that if no window manager is running.
401 * Returns the selected file name
402 * or 'nil' (YCPVoid() ) if the user canceled the operation.
404 YCPValue askForExistingFile ( const YCPString & startWith,
405 const YCPString & filter,
406 const YCPString & headline );
409 * Open a file selection box and prompt the user for a file to save data to.
410 * Automatically asks for confirmation if the user selects an existing file.
411 * [Reimplemented from YUI]
413 * 'startWith' is the initial directory or file.
415 * 'filter' is one or more blank-separated file patterns, e.g. "*.png *.jpg"
417 * 'headline' is an explanatory text for the file selection box.
418 * Graphical UIs may omit that if no window manager is running.
420 * Returns the selected file name
421 * or 'nil' (YCPVoid() ) if the user canceled the operation.
423 YCPValue askForSaveFileName ( const YCPString & startWith,
424 const YCPString & filter,
425 const YCPString & headline );
428 * Lower-level version that works with QStrings and does not change
431 QString askForSaveFileName( const QString & startWith,
432 const QString & filter,
433 const QString & headline );
438 QWidget* mainWidget();
441 * Initialize and set a textdomain for gettext()
443 static void setTextdomain( const char * domain );
446 * Returns a high-contrast color palette suitable for vision impaired users.
448 static QPalette visionImpairedPalette();
451 * Returns the normal color palette
453 QPalette normalPalette() const { return _normalPalette; }
456 * Toggle between the vision impaired and the normal color palette.
458 void toggleVisionImpairedPalette();
461 * Returns 'true' if high-contrast colors for vision impaired users is in use.
462 * This should be queried at other places before using custom colors.
464 bool usingVisionImpairedPalette() const { return _usingVisionImpairedPalette; }
467 * Convert logical layout spacing units into device dependent units.
468 * A default size dialog is assumed to be 80x25 layout spacing units
469 * and 640x480 device dependent spacing units.
471 * Reimplemented from YUI.
473 virtual int deviceUnits( YUIDimension dim, float layout_units );
476 * Convert device dependent units into logical layout spacing units.
477 * A default size dialog is assumed to be 80x25 layout spacing units
478 * and 640x480 device dependent spacing units.
480 * Reimplemented from YUI.
482 virtual float layoutUnits( YUIDimension dim, int device_units );
485 * Returns the package selector plugin singleton of this UI or creates it
486 * (including loading the plugin lib) if it does not exist yet.
488 YQPackageSelectorPlugin * packageSelectorPlugin();
494 * Display capabilities.
495 * [Reimplemented from YUI]
496 * See UI builtin GetDisplayInfo() doc for details.
498 int getDisplayWidth();
499 int getDisplayHeight();
500 int getDisplayDepth();
501 long getDisplayColors();
502 int getDefaultWidth();
503 int getDefaultHeight();
504 bool textMode() { return false; }
505 bool hasImageSupport() { return true; }
506 bool hasLocalImageSupport() { return true; }
507 bool hasAnimationSupport() { return true; }
508 bool hasIconSupport() { return false; } // not yet
509 bool hasFullUtf8Support() { return true; }
510 bool richTextSupportsTable() { return true; }
511 bool leftHandedMouse() { return _leftHandedMouse; }
514 QMap<QString, int> screenShotNo;
515 QString screenShotNameTemplate;
520 * Application shutdown
525 * Timeout during TimeoutUserInput() / WaitForEvent()
527 void userInputTimeout();
532 * Handle command line args
534 void processCommandLineArgs( int argc, char **argv );
537 * Calculate size of `opt(`defaultsize) dialogs
539 void calcDefaultSize();
548 * Assume presence of a window manager
553 * Use the entire available screen
558 * Decorate the toplevel window
560 bool _decorate_toplevel_window;
563 * Container for the widget stack. QWidgetStack cannot handle a WFlags
564 * argument, so this needs to be embedded into something else - and a QVBox
565 * at least handles all the sizeHint and resize stuff.
570 * Stack for the Qt widgets inside the main window.
572 QStackedWidget * _widget_stack;
575 * Stack to keep track of the stacking order of popup dialogs.
577 vector<QWidget *> _popup_stack;
580 * Size for `opt(`defaultsize) dialogs.
585 * This flag is set during @ref #userInput in order to tell
586 * @ref #returnNow to call exit_loop, which only may be called
592 * Event loop object. Required since a YaST2 UI needs to react to commands
593 * from the YCP command stream as well as to X11 / Qt events.
595 QEventLoop * _eventLoop;
598 * Window manager close events blocked?
600 bool _wm_close_blocked;
603 * Force new dialogs to the foreground and grab the keyboard focus?
604 * (Only if running without a window manager)
606 bool _auto_activate_dialogs;
609 * Global reference to the UI
614 * Indicate a fatal error that requires the UI to terminate
619 * Timer for TimeoutUserInput() / WaitForEvent().
621 QTimer _user_input_timer;
624 * Timer for delayed busy cursor
626 QTimer *_busy_cursor_timer;
629 * The handler for the single pending event this UI keeps track of
631 YSimpleEventHandler _event_handler;
636 * Saved normal palette
638 QPalette _normalPalette;
641 * Flag: currently using special palette for vision impaired users?
643 bool _usingVisionImpairedPalette;
646 * Flag: Does the user want to use a left-handed mouse?
648 bool _leftHandedMouse;
651 * Flag: Was the user already asked if he wants to use a left-handed mouse?
653 bool _askedForLeftHandedMouse;
660 * Reads the style sheet, parses some comments and passes it to qapp