libyui-qt  2.53.0
YQUI.cc
1 /*
2  Copyright (C) 2000-2012 Novell, Inc
3  This library is free software; you can redistribute it and/or modify
4  it under the terms of the GNU Lesser General Public License as
5  published by the Free Software Foundation; either version 2.1 of the
6  License, or (at your option) version 3.0 of the License. This library
7  is distributed in the hope that it will be useful, but WITHOUT ANY
8  WARRANTY; without even the implied warranty of MERCHANTABILITY or
9  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10  License for more details. You should have received a copy of the GNU
11  Lesser General Public License along with this library; if not, write
12  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
13  Floor, Boston, MA 02110-1301 USA
14 */
15 
16 
17 /*-/
18 
19  File: YQUI.cc
20 
21  Author: Stefan Hundhammer <sh@suse.de>
22 
23  Textdomain "qt"
24 
25 /-*/
26 
27 #include <sys/param.h> // MAXHOSTNAMELEN
28 #include <dlfcn.h>
29 #include <libintl.h>
30 #include <algorithm>
31 #include <stdio.h>
32 
33 #include <QWidget>
34 #include <QThread>
35 #include <QSocketNotifier>
36 #include <QDesktopWidget>
37 #include <QEvent>
38 #include <QCursor>
39 #include <QLocale>
40 #include <QMessageLogContext>
41 #include <QMessageBox>
42 #include <QScreen>
43 #include <QInputDialog>
44 
45 
46 #define YUILogComponent "qt-ui"
47 #include <yui/YUILog.h>
48 #include <yui/Libyui_config.h>
49 
50 #include "YQUI.h"
51 
52 #include <yui/YEvent.h>
53 #include <yui/YCommandLine.h>
54 #include <yui/YButtonBox.h>
55 #include <yui/YUISymbols.h>
56 
57 #include "QY2Styler.h"
58 #include "YQApplication.h"
59 #include "YQDialog.h"
60 #include "YQWidgetFactory.h"
61 #include "YQOptionalWidgetFactory.h"
62 
63 #include "YQWizardButton.h"
64 
65 #include "YQi18n.h"
66 #include "utf8.h"
67 
68 // Include low-level X headers AFTER Qt headers:
69 // X.h pollutes the global namespace (!!!) with pretty useless #defines
70 // like "Above", "Below" etc. that clash with some Qt headers.
71 #include <X11/Xlib.h>
72 
73 
74 #define BUSY_CURSOR_TIMEOUT 200 // milliseconds
75 #define VERBOSE_EVENT_LOOP 0
76 
77 #ifdef TEXTDOMAIN
78 # undef TEXTDOMAIN
79 #endif
80 
81 #define TEXTDOMAIN "qt"
82 
83 
84 using std::string;
85 
86 
87 
88 static void qMessageHandler( QtMsgType type, const QMessageLogContext &, const QString & msg );
89 YQUI * YQUI::_ui = 0;
90 
91 
92 YUI * createUI( bool withThreads )
93 {
94  if ( ! YQUI::ui() )
95  {
96  YQUI * ui = new YQUI( withThreads );
97 
98  if ( ui && ! withThreads )
99  ui->initUI();
100  }
101 
102  return YQUI::ui();
103 }
104 
105 
106 YQUI::YQUI( bool withThreads, bool topmostConstructor )
107  : YUI( withThreads )
108 #if 0
109  , _main_win( NULL )
110 #endif
111  , _do_exit_loop( false )
112 {
113  yuiDebug() << "YQUI constructor start" << endl;
114  yuiMilestone() << "This is libyui-qt " << VERSION << endl;
115 
116  _ui = this;
117  _uiInitialized = false;
118  _fatalError = false;
119  _fullscreen = false;
120  _noborder = false;
121  _blockedLevel = 0;
122 
123  qInstallMessageHandler( qMessageHandler );
124 
125  yuiDebug() << "YQUI constructor finished" << endl;
126  if ( topmostConstructor ) {
127  yuiDebug() << "YQUI is the top most constructor" << endl;
128  topmostConstructorHasFinished();
129  }
130 }
131 
132 
134 {
135  if ( _uiInitialized )
136  return;
137 
138  _uiInitialized = true;
139  yuiDebug() << "Initializing Qt part" << endl;
140 
141  YCommandLine cmdLine; // Retrieve command line args from /proc/<pid>/cmdline
142  string progName;
143 
144  if ( cmdLine.argc() > 0 )
145  {
146  progName = cmdLine[0];
147  std::size_t lastSlashPos = progName.find_last_of( '/' );
148 
149  if ( lastSlashPos != string::npos )
150  progName = progName.substr( lastSlashPos+1 );
151 
152  // Qt will display argv[0] as the window manager title.
153  // For YaST2, display "YaST2" instead of "y2base".
154  // For other applications, leave argv[0] alone.
155 
156  if ( progName == "y2base" )
157  cmdLine.replace( 0, "YaST2" );
158  }
159 
160  _ui_argc = cmdLine.argc();
161  char ** argv = cmdLine.argv();
162 
163  yuiDebug() << "Creating QApplication" << endl;
164  QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
165  new QApplication( _ui_argc, argv );
166  Q_CHECK_PTR( qApp );
167  // Qt keeps track to a global QApplication in qApp.
168 
169  _signalReceiver = new YQUISignalReceiver();
170  _busyCursorTimer = new QTimer( _signalReceiver );
171  _busyCursorTimer->setSingleShot( true );
172 
173  (void) QY2Styler::styler(); // Make sure QY2Styler singleton is created
174 
175  setButtonOrderFromEnvironment();
176  processCommandLineArgs( _ui_argc, argv );
177  calcDefaultSize();
178 
179  _do_exit_loop = false;
180 
181 #if 0
182  // Create main window for `opt(`defaultsize) dialogs.
183  //
184  // We have to use something else than QWidgetStack since QWidgetStack
185  // doesn't accept a WFlags arg which we badly need here.
186 
187  _main_win = new QWidget( 0, Qt::Window ); // parent, wflags
188  _main_win->setFocusPolicy( Qt::StrongFocus );
189  _main_win->setObjectName( "main_window" );
190 
191  _main_win->resize( _defaultSize );
192 
193  if ( _fullscreen )
194  _main_win->move( 0, 0 );
195 #endif
196 
197 
198  //
199  // Set application title (used by YQDialog and YQWizard)
200  //
201 
202  // for YaST2, display "YaST2" instead of "y2base"
203  if ( progName == "y2base" )
204  _applicationTitle = QString( "YaST2" );
205  else
206  _applicationTitle = fromUTF8( progName );
207 
208  // read x11 display from commandline or environment variable
209  int displayArgPos = cmdLine.find( "-display" );
210  QString displayName;
211 
212  if ( displayArgPos > 0 && displayArgPos+1 < cmdLine.argc() )
213  displayName = cmdLine[ displayArgPos+1 ].c_str();
214  else
215  displayName = getenv( "DISPLAY" );
216 
217  // identify hostname
218  char hostname[ MAXHOSTNAMELEN+1 ];
219  if ( gethostname( hostname, sizeof( hostname )-1 ) == 0 )
220  hostname[ sizeof( hostname ) -1 ] = '\0'; // make sure it's terminated
221  else
222  hostname[0] = '\0';
223 
224  // add hostname to the window title if it's not a local display
225  if ( !displayName.startsWith( ":" ) && strlen( hostname ) > 0 )
226  {
227  _applicationTitle += QString( "@" );
228  _applicationTitle += fromUTF8( hostname );
229  }
230 
231 
232 #if 0
233  // Hide the main window for now. The first call to UI::OpenDialog() on an
234  // `opt(`defaultSize) dialog will trigger a dialog->open() call that shows
235  // the main window - there is nothing to display yet.
236 
237  _main_win->hide();
238 #endif
239 
240  YButtonBoxMargins buttonBoxMargins;
241  buttonBoxMargins.left = 8;
242  buttonBoxMargins.right = 8;
243  buttonBoxMargins.top = 6;
244  buttonBoxMargins.bottom = 6;
245 
246  buttonBoxMargins.spacing = 4;
247  buttonBoxMargins.helpButtonExtraSpacing = 16;
248  YButtonBox::setDefaultMargins( buttonBoxMargins );
249 
250  // Init other stuff
251 
252  qApp->setFont( yqApp()->currentFont() );
253  busyCursor();
254 
255 
256  QObject::connect( _busyCursorTimer, &pclass(_busyCursorTimer)::timeout,
257  _signalReceiver, &pclass(_signalReceiver)::slotBusyCursor );
258 
259  yuiMilestone() << "YQUI initialized. Thread ID: 0x"
260  << hex << QThread::currentThreadId () << dec
261  << endl;
262 
263  qApp->processEvents();
264 }
265 
266 
269 {
270  return static_cast<YQApplication *>( app() );
271 }
272 
273 
274 void YQUI::processCommandLineArgs( int argc, char **argv )
275 {
276  if ( argv )
277  {
278  for( int i=0; i < argc; i++ )
279  {
280  QString opt = argv[i];
281 
282  yuiMilestone() << "Qt argument: " << argv[i] << endl;
283 
284  // Normalize command line option - accept "--xy" as well as "-xy"
285 
286  if ( opt.startsWith( "--" ) )
287  opt.remove(0, 1);
288 
289  if ( opt == QString( "-fullscreen" ) ) _fullscreen = true;
290  else if ( opt == QString( "-noborder" ) ) _noborder = true;
291  else if ( opt == QString( "-auto-font" ) ) yqApp()->setAutoFonts( true );
292  else if ( opt == QString( "-auto-fonts" ) ) yqApp()->setAutoFonts( true );
293  else if ( opt == QString( "-gnome-button-order" ) ) YButtonBox::setLayoutPolicy( YButtonBox::gnomeLayoutPolicy() );
294  else if ( opt == QString( "-kde-button-order" ) ) YButtonBox::setLayoutPolicy( YButtonBox::kdeLayoutPolicy() );
295  // --macro is handled by YUI_component
296  else if ( opt == QString( "-help" ) )
297  {
298  fprintf( stderr,
299  "Command line options for the YaST2 Qt UI:\n"
300  "\n"
301  "--nothreads run without additional UI threads\n"
302  "--fullscreen use full screen for `opt(`defaultsize) dialogs\n"
303  "--noborder no window manager border for `opt(`defaultsize) dialogs\n"
304  "--auto-fonts automatically pick fonts, disregard Qt standard settings\n"
305  "--help this help text\n"
306  "\n"
307  "--macro <macro-file> play a macro right on startup\n"
308  "\n"
309  "-no-wm, -noborder etc. are accepted as well as --no-wm, --noborder\n"
310  "to maintain backwards compatibility.\n"
311  "\n"
312  );
313 
314  raiseFatalError();
315  }
316  }
317  }
318 
319  // Qt handles command line option "-reverse" for Arabic / Hebrew
320 }
321 
322 
324 {
325  yuiMilestone() <<"Closing down Qt UI." << endl;
326 
327  // Intentionally NOT calling dlclose() to libqt-mt
328  // (see constructor for explanation)
329 
330  if ( qApp ) // might already be reset to 0 internally from Qt
331  {
332  qApp->exit();
333  qApp->deleteLater();
334  }
335 
336  delete _signalReceiver;
337 }
338 
339 
340 void
342 {
343  yuiMilestone() <<"Destroying UI thread" << endl;
344 
345  if ( qApp ) // might already be reset to 0 internally from Qt
346  {
347  if ( YDialog::openDialogsCount() > 0 )
348  {
349  yuiError() << YDialog::openDialogsCount() << " open dialogs left over" << endl;
350  yuiError() << "Topmost dialog:" << endl;
351  YDialog::topmostDialog()->dumpWidgetTree();
352  }
353 
354  YDialog::deleteAllDialogs();
355  qApp->exit();
356  qApp->deleteLater();
357  }
358 }
359 
360 
361 YWidgetFactory *
363 {
364  YQWidgetFactory * factory = new YQWidgetFactory();
365  YUI_CHECK_NEW( factory );
366 
367  return factory;
368 }
369 
370 
371 YOptionalWidgetFactory *
373 {
375  YUI_CHECK_NEW( factory );
376 
377  return factory;
378 }
379 
380 
381 YApplication *
382 YQUI::createApplication()
383 {
384  YQApplication * app = new YQApplication();
385  YUI_CHECK_NEW( app );
386 
387  return app;
388 }
389 
390 
392 {
393  QScreen * screen = qApp->primaryScreen();
394  QSize primaryScreenSize = screen->size();
395  QSize availableSize = screen->availableSize();
396 
397  if ( _fullscreen )
398  {
399  _defaultSize = availableSize;
400 
401  yuiMilestone() << "-fullscreen: using "
402  << _defaultSize.width() << " x " << _defaultSize.height()
403  << "for `opt(`defaultsize)"
404  << endl;
405  }
406  else
407  {
408  // Get _defaultSize via -geometry command line option (if set)
409 
410  // Set min defaultsize or figure one out if -geometry was not used
411 
412  if ( _defaultSize.width() < 800 ||
413  _defaultSize.height() < 600 )
414  {
415  if ( primaryScreenSize.width() >= 1024 && primaryScreenSize.height() >= 768 )
416  {
417  // Scale down to 70% of screen size
418 
419  _defaultSize.setWidth ( std::max( (int) (availableSize.width() * 0.7), 800 ) );
420  _defaultSize.setHeight( std::max( (int) (availableSize.height() * 0.7), 600 ) );
421  }
422  else
423  {
424  _defaultSize = availableSize;
425  }
426  }
427  else
428  {
429  yuiMilestone() << "Forced size (via -geometry): "
430  << _defaultSize.width() << " x " << _defaultSize.height()
431  << endl;
432  }
433  }
434 
435  yuiMilestone() << "Default size: "
436  << _defaultSize.width() << " x " << _defaultSize.height()
437  << endl;
438 }
439 
440 
441 void YQUI::idleLoop( int fd_ycp )
442 {
443  initUI();
444 
445  _received_ycp_command = false;
446  QSocketNotifier * notifier = new QSocketNotifier( fd_ycp, QSocketNotifier::Read );
447  QObject::connect( notifier, &pclass(notifier)::activated,
448  _signalReceiver, &pclass(_signalReceiver)::slotReceivedYCPCommand );
449 
450  notifier->setEnabled( true );
451 
452 
453  //
454  // Process Qt events until fd_ycp is readable
455  //
456 
457 #if VERBOSE_EVENT_LOOP
458  yuiDebug() << "Entering idle loop" << endl;
459 #endif
460 
461  QEventLoop eventLoop( qApp );
462 
463  while ( !_received_ycp_command )
464  eventLoop.processEvents( QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents );
465 
466 #if VERBOSE_EVENT_LOOP
467  yuiDebug() << "Leaving idle loop" << endl;
468 #endif
469 
470  delete notifier;
471 }
472 
473 
475 {
476  _received_ycp_command = true;
477 }
478 
479 
480 void YQUI::sendEvent( YEvent * event )
481 {
482  if ( event )
483  {
484  _eventHandler.sendEvent( event );
485  YQDialog * dialog = (YQDialog *) YDialog::currentDialog( false ); // don't throw
486 
487  if ( dialog )
488  {
489  if ( dialog->eventLoop()->isRunning() )
490  dialog->eventLoop()->exit( 0 );
491  }
492  else
493  {
494  yuiError() << "No dialog" << endl;
495  }
496  }
497 }
498 
499 
500 void YQUI::setTextdomain( const char * domain )
501 {
502  bindtextdomain( domain, YSettings::localeDir().c_str() );
503  bind_textdomain_codeset( domain, "utf8" );
504  textdomain( domain );
505 
506  // Make change known.
507  {
508  extern int _nl_msg_cat_cntr;
509  ++_nl_msg_cat_cntr;
510  }
511 }
512 
513 
514 void YQUI::blockEvents( bool block )
515 {
516  initUI();
517 
518  if ( block )
519  {
520  if ( ++_blockedLevel == 1 )
521  {
522  _eventHandler.blockEvents( true );
523 
524  YQDialog * dialog = (YQDialog *) YDialog::currentDialog( false ); // don't throw
525 
526  if ( dialog && dialog->eventLoop()->isRunning() )
527  {
528  yuiWarning() << "blocking events in active event loop of " << dialog << endl;
529  dialog->eventLoop()->exit();
530  }
531  }
532  }
533  else
534  {
535  if ( --_blockedLevel == 0 )
536  {
537  _eventHandler.blockEvents( false );
538 
539  YQDialog * dialog = (YQDialog *) YDialog::currentDialog( false ); // don't throw
540 
541  if ( dialog )
542  dialog->eventLoop()->wakeUp();
543  }
544  }
545 }
546 
547 
549 {
550  initUI();
551  _blockedLevel = 0;
552  _eventHandler.blockEvents( false );
553 }
554 
555 
557 {
558  return _eventHandler.eventsBlocked();
559 }
560 
561 
563 {
564  qApp->setOverrideCursor( Qt::BusyCursor );
565 }
566 
567 
569 {
570  if ( _busyCursorTimer->isActive() )
571  _busyCursorTimer->stop();
572 
573  while ( qApp->overrideCursor() )
574  qApp->restoreOverrideCursor();
575 }
576 
577 
579 {
580  // Display a busy cursor, but only if there is no other activity within
581  // BUSY_CURSOR_TIMEOUT milliseconds: Avoid cursor flicker.
582 
583  _busyCursorTimer->start( BUSY_CURSOR_TIMEOUT ); // single shot
584 }
585 
586 
587 int YQUI::defaultSize(YUIDimension dim) const
588 {
589  return dim == YD_HORIZ ? _defaultSize.width() : _defaultSize.height();
590 }
591 
592 
593 void YQUI::probeX11Display( const YCommandLine & cmdLine )
594 {
595  // obsolete, see https://bugzilla.suse.com/show_bug.cgi?id=1072411
596 }
597 
598 
599 void YQUI::deleteNotify( YWidget * widget )
600 {
601  _eventHandler.deletePendingEventsFor( widget );
602 }
603 
604 
606 {
607  yuiMilestone() << "Closing application" << endl;
608  sendEvent( new YCancelEvent() );
609  return true;
610 }
611 
612 
614 {
615  QWidget * parent = 0;
616  YDialog * dialog = YDialog::currentDialog( false ); // doThrow
617 
618  YQUI::setTextdomain( TEXTDOMAIN );
619 
620  if ( dialog )
621  parent = (QWidget *) dialog->widgetRep();
622 
623  QString id = QInputDialog::getText( parent,
624  _( "Widget ID" ), // dialog title
625  _( "Enter Widget ID:" ) // label
626  );
627  if ( ! id.isEmpty() )
628  {
629  try
630  {
631  YWidget * widget = sendWidgetID( toUTF8( id ) );
632  YQGenericButton * yqButton = dynamic_cast<YQGenericButton *>( widget );
633 
634  if ( yqButton )
635  {
636  yuiMilestone() << "Activating " << widget << endl;
637  yqButton->activate();
638  }
639  }
640  catch ( YUIWidgetNotFoundException & ex )
641  {
642  YUI_CAUGHT( ex );
643  QMessageBox::warning( parent,
644  _( "Error" ), // title
645  _( "No widget with ID \"%1\"" ).arg( id ) );
646  }
647  }
648 }
649 
650 
651 
652 
653 
654 YQUISignalReceiver::YQUISignalReceiver()
655  : QObject()
656 {
657 }
658 
659 
660 void YQUISignalReceiver::slotBusyCursor()
661 {
662  YQUI::ui()->busyCursor();
663 }
664 
665 
666 void YQUISignalReceiver::slotReceivedYCPCommand()
667 {
669 }
670 
671 
672 
673 static void
674 qMessageHandler( QtMsgType type, const QMessageLogContext &, const QString & msg )
675 {
676  switch (type)
677  {
678  case QtDebugMsg:
679  yuiMilestone() << "<libqt-debug> " << msg << endl;
680  break;
681 
682 #if QT_VERSION >= 0x050500
683  case QtInfoMsg:
684  yuiMilestone() << "<libqt-info> " << msg << endl;
685  break;
686 #endif
687 
688  case QtWarningMsg:
689  yuiWarning() << "<libqt-warning> " << msg << endl;
690  break;
691 
692  case QtCriticalMsg:
693  yuiError() << "<libqt-critical>" << msg << endl;
694  break;
695 
696  case QtFatalMsg:
697  yuiError() << "<libqt-fatal> " << msg << endl;
698  abort();
699  exit(1); // Qt does the same
700  }
701 
702  if ( QString( msg ).contains( "Fatal IO error", Qt::CaseInsensitive ) &&
703  QString( msg ).contains( "client killed", Qt::CaseInsensitive ) )
704  yuiError() << "Client killed. Possibly caused by X server shutdown or crash." << endl;
705 }
706 
707 
708 QIcon YQUI::loadIcon( const string & iconName ) const
709 {
710  QIcon icon;
711  const QString resource = ":/";
712 
713  if ( QIcon::hasThemeIcon( iconName.c_str() ) )
714  {
715  yuiDebug() << "Trying theme icon from: " << iconName << endl;
716  icon = QIcon::fromTheme( iconName.c_str() );
717  }
718 
719  if ( icon.isNull() )
720  {
721  yuiDebug() << "Trying icon from resource: " << iconName << endl;
722  icon = QIcon( resource + iconName.c_str() );
723  }
724 
725  if ( icon.isNull() )
726  {
727  yuiDebug() << "Trying icon from path: " << iconName << endl;
728  icon = QIcon( iconName.c_str() );
729  }
730 
731  if ( icon.isNull() )
732  yuiWarning() << "Couldn't load icon: " << iconName << endl;
733 
734  return icon;
735 }
void setAutoFonts(bool useAutoFonts)
Set whether or not fonts should automatically be picked.
QEventLoop * eventLoop()
Access to this dialog's event loop.
Definition: YQDialog.h:201
Abstract base class for push button and similar widgets - all that can become a YQDialog's "default b...
void activate()
Activate (animated) this button.
Widget factory for optional ("special") widgets.
Helper class that acts as a Qt signal receiver for YQUI.
Definition: YQUI.h:396
Definition: YQUI.h:63
virtual void deleteNotify(YWidget *widget)
Notification that a widget is being deleted.
Definition: YQUI.cc:599
void probeX11Display(const YCommandLine &cmdLine)
Probe the X11 display.
Definition: YQUI.cc:593
virtual bool eventsBlocked() const
Returns 'true' if events are currently blocked.
Definition: YQUI.cc:556
void busyCursor()
Show mouse cursor indicating busy state.
Definition: YQUI.cc:562
virtual void idleLoop(int fd_ycp)
Idle around until fd_ycp is readable and handle repaints.
Definition: YQUI.cc:441
virtual ~YQUI()
Destructor.
Definition: YQUI.cc:323
void processCommandLineArgs(int argc, char **argv)
Handle command line args.
Definition: YQUI.cc:274
YQUI(bool withThreads, bool topmostConstructor=true)
Constructors.
Definition: YQUI.cc:106
virtual YOptionalWidgetFactory * createOptionalWidgetFactory()
Create the widget factory that provides all the createXY() methods for optional ("special") widgets a...
Definition: YQUI.cc:372
static YQUI * ui()
Access the global Qt-UI.
Definition: YQUI.h:83
void askSendWidgetID()
Open a pop-up dialog to ask the user for a widget ID and then send it with sendWidgetID().
Definition: YQUI.cc:613
void timeoutBusyCursor()
Show mouse cursor indicating busy state if the UI is unable to respond to user input for more than a ...
Definition: YQUI.cc:578
void sendEvent(YEvent *event)
Widget event handlers (slots) call this when an event occured that should be the answer to a UserInpu...
Definition: YQUI.cc:480
static YQApplication * yqApp()
Return the global YApplication object as YQApplication.
Definition: YQUI.cc:268
virtual void initUI()
Post-constructor initialization.
Definition: YQUI.cc:133
int defaultSize(YUIDimension dim) const
Returns size for opt(defaultsize) dialogs (in one dimension).
Definition: YQUI.cc:587
void forceUnblockEvents()
Force unblocking all events, no matter how many times blockEvents() has This returns 0 if there is no...
Definition: YQUI.cc:548
virtual void blockEvents(bool block=true)
Block (or unblock) events.
Definition: YQUI.cc:514
bool close()
Application shutdown.
Definition: YQUI.cc:605
void receivedYCPCommand()
Notification that a YCP command has been received on fd_ycp to leave idleLoop()
Definition: YQUI.cc:474
void calcDefaultSize()
Calculate size of opt(defaultsize) dialogs.
Definition: YQUI.cc:391
QIcon loadIcon(const string &iconName) const
Load an icon.
Definition: YQUI.cc:708
virtual void uiThreadDestructor()
Destroy whatever needs to be destroyed within the UI thread.
Definition: YQUI.cc:341
void normalCursor()
Show normal mouse cursor not indicating busy status.
Definition: YQUI.cc:568
static void setTextdomain(const char *domain)
Initialize and set a textdomain for gettext()
Definition: YQUI.cc:500
void raiseFatalError()
Raise a fatal UI error.
Definition: YQUI.h:187
virtual YWidgetFactory * createWidgetFactory()
Create the widget factory that provides all the createXY() methods for standard (mandatory,...
Definition: YQUI.cc:362
Concrete widget factory for mandatory widgets.