25 #include <sys/param.h> 33 #include <QSocketNotifier> 34 #include <QDesktopWidget> 38 #include <QMessageLogContext> 39 #include <QMessageBox> 41 #include <QInputDialog> 44 #define YUILogComponent "qt-ui" 45 #include <yui/YUILog.h> 46 #include <yui/Libyui_config.h> 50 #include <yui/YEvent.h> 51 #include <yui/YCommandLine.h> 52 #include <yui/YButtonBox.h> 53 #include <yui/YUISymbols.h> 55 #include "QY2Styler.h" 56 #include "YQApplication.h" 58 #include "YQWidgetFactory.h" 59 #include "YQOptionalWidgetFactory.h" 61 #include "YQWizardButton.h" 74 #define BUSY_CURSOR_TIMEOUT 200 // milliseconds 75 #define VERBOSE_EVENT_LOOP 0 79 static void qMessageHandler( QtMsgType type,
const QMessageLogContext &,
const QString & msg );
83 YUI * createUI(
bool withThreads )
89 if ( ui && ! withThreads )
102 , _do_exit_loop( false )
104 yuiDebug() <<
"YQUI constructor start" << std::endl;
105 yuiMilestone() <<
"This is libyui-qt " << VERSION << std::endl;
108 _uiInitialized =
false;
112 screenShotNameTemplate =
"";
115 qInstallMessageHandler( qMessageHandler );
117 yuiDebug() <<
"YQUI constructor finished" << std::endl;
118 if ( topmostConstructor ) {
119 yuiDebug() <<
"YQUI is the top most constructor" << std::endl;
120 topmostConstructorHasFinished();
127 if ( _uiInitialized )
130 _uiInitialized =
true;
131 yuiDebug() <<
"Initializing Qt part" << std::endl;
133 YCommandLine cmdLine;
134 std::string progName;
136 if ( cmdLine.argc() > 0 )
138 progName = cmdLine[0];
139 std::size_t lastSlashPos = progName.find_last_of(
'/' );
141 if ( lastSlashPos != std::string::npos )
142 progName = progName.substr( lastSlashPos+1 );
148 if ( progName ==
"y2base" )
149 cmdLine.replace( 0,
"YaST2" );
152 _ui_argc = cmdLine.argc();
153 char ** argv = cmdLine.argv();
155 yuiDebug() <<
"Creating QApplication" << std::endl;
156 QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
157 new QApplication( _ui_argc, argv );
162 _busyCursorTimer =
new QTimer( _signalReceiver );
163 _busyCursorTimer->setSingleShot(
true );
165 (void) QY2Styler::styler();
167 setButtonOrderFromEnvironment();
171 _do_exit_loop =
false;
179 _main_win =
new QWidget( 0, Qt::Window );
180 _main_win->setFocusPolicy( Qt::StrongFocus );
181 _main_win->setObjectName(
"main_window" );
183 _main_win->resize( _defaultSize );
186 _main_win->move( 0, 0 );
195 if ( progName ==
"y2base" )
196 _applicationTitle = QString(
"YaST2" );
198 _applicationTitle = fromUTF8( progName );
201 int displayArgPos = cmdLine.find(
"-display" );
204 if ( displayArgPos > 0 && displayArgPos+1 < cmdLine.argc() )
205 displayName = cmdLine[ displayArgPos+1 ].c_str();
207 displayName = getenv(
"DISPLAY" );
210 char hostname[ MAXHOSTNAMELEN+1 ];
211 if ( gethostname( hostname,
sizeof( hostname )-1 ) == 0 )
212 hostname[
sizeof( hostname ) -1 ] =
'\0';
217 if ( !displayName.startsWith(
":" ) && strlen( hostname ) > 0 )
219 _applicationTitle += QString(
"@" );
220 _applicationTitle += fromUTF8( hostname );
232 YButtonBoxMargins buttonBoxMargins;
233 buttonBoxMargins.left = 8;
234 buttonBoxMargins.right = 8;
235 buttonBoxMargins.top = 6;
236 buttonBoxMargins.bottom = 6;
238 buttonBoxMargins.spacing = 4;
239 buttonBoxMargins.helpButtonExtraSpacing = 16;
240 YButtonBox::setDefaultMargins( buttonBoxMargins );
244 qApp->setFont(
yqApp()->currentFont() );
248 QObject::connect( _busyCursorTimer, &pclass(_busyCursorTimer)::timeout,
249 _signalReceiver, &pclass(_signalReceiver)::slotBusyCursor );
251 yuiMilestone() <<
"YQUI initialized. Thread ID: 0x" 252 << hex << QThread::currentThreadId () << dec
255 qApp->processEvents();
270 for(
int i=0; i < argc; i++ )
272 QString opt = argv[i];
274 yuiMilestone() <<
"Qt argument: " << argv[i] << std::endl;
278 if ( opt.startsWith(
"--" ) )
281 if ( opt == QString(
"-fullscreen" ) ) _fullscreen =
true;
282 else if ( opt == QString(
"-noborder" ) ) _noborder =
true;
285 else if ( opt == QString(
"-gnome-button-order" ) ) YButtonBox::setLayoutPolicy( YButtonBox::gnomeLayoutPolicy() );
286 else if ( opt == QString(
"-kde-button-order" ) ) YButtonBox::setLayoutPolicy( YButtonBox::kdeLayoutPolicy() );
288 else if ( opt == QString(
"-help" ) )
291 "Command line options for the YaST2 Qt UI:\n" 293 "--nothreads run without additional UI threads\n" 294 "--fullscreen use full screen for `opt(`defaultsize) dialogs\n" 295 "--noborder no window manager border for `opt(`defaultsize) dialogs\n" 296 "--auto-fonts automatically pick fonts, disregard Qt standard settings\n" 297 "--help this help text\n" 299 "--macro <macro-file> play a macro right on startup\n" 301 "-no-wm, -noborder etc. are accepted as well as --no-wm, --noborder\n" 302 "to maintain backwards compatibility.\n" 317 yuiMilestone() <<
"Closing down Qt UI." << std::endl;
328 delete _signalReceiver;
335 yuiMilestone() <<
"Destroying UI thread" << std::endl;
339 if ( YDialog::openDialogsCount() > 0 )
341 yuiError() << YDialog::openDialogsCount() <<
" open dialogs left over" << endl;
342 yuiError() <<
"Topmost dialog:" << endl;
343 YDialog::topmostDialog()->dumpWidgetTree();
346 YDialog::deleteAllDialogs();
357 YUI_CHECK_NEW( factory );
363 YOptionalWidgetFactory *
367 YUI_CHECK_NEW( factory );
374 YQUI::createApplication()
377 YUI_CHECK_NEW( app );
385 QScreen * screen = qApp->primaryScreen();
386 QSize primaryScreenSize = screen->size();
387 QSize availableSize = screen->availableSize();
391 _defaultSize = availableSize;
393 yuiMilestone() <<
"-fullscreen: using " 394 << _defaultSize.width() <<
" x " << _defaultSize.height()
395 <<
"for `opt(`defaultsize)" 404 if ( _defaultSize.width() < 800 ||
405 _defaultSize.height() < 600 )
407 if ( primaryScreenSize.width() >= 1024 && primaryScreenSize.height() >= 768 )
411 _defaultSize.setWidth ( max( (
int) (availableSize.width() * 0.7), 800 ) );
412 _defaultSize.setHeight( max( (
int) (availableSize.height() * 0.7), 600 ) );
416 _defaultSize = availableSize;
421 yuiMilestone() <<
"Forced size (via -geometry): " 422 << _defaultSize.width() <<
" x " << _defaultSize.height()
427 yuiMilestone() <<
"Default size: " 428 << _defaultSize.width() <<
" x " << _defaultSize.height()
437 _received_ycp_command =
false;
438 QSocketNotifier * notifier =
new QSocketNotifier( fd_ycp, QSocketNotifier::Read );
439 QObject::connect( notifier, &pclass(notifier)::activated,
440 _signalReceiver, &pclass(_signalReceiver)::slotReceivedYCPCommand );
442 notifier->setEnabled(
true );
449 #if VERBOSE_EVENT_LOOP 450 yuiDebug() <<
"Entering idle loop" << std::endl;
453 QEventLoop eventLoop( qApp );
455 while ( !_received_ycp_command )
456 eventLoop.processEvents( QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents );
458 #if VERBOSE_EVENT_LOOP 459 yuiDebug() <<
"Leaving idle loop" << std::endl;
468 _received_ycp_command =
true;
476 _eventHandler.sendEvent( event );
486 yuiError() <<
"No dialog" << std::endl;
494 bindtextdomain( domain, YSettings::localeDir().c_str() );
495 bind_textdomain_codeset( domain,
"utf8" );
496 textdomain( domain );
500 extern int _nl_msg_cat_cntr;
512 if ( ++_blockedLevel == 1 )
514 _eventHandler.blockEvents(
true );
518 if ( dialog && dialog->
eventLoop()->isRunning() )
520 yuiWarning() <<
"blocking events in active event loop of " << dialog << std::endl;
527 if ( --_blockedLevel == 0 )
529 _eventHandler.blockEvents(
false );
544 _eventHandler.blockEvents(
false );
550 return _eventHandler.eventsBlocked();
556 qApp->setOverrideCursor( Qt::BusyCursor );
562 if ( _busyCursorTimer->isActive() )
563 _busyCursorTimer->stop();
565 while ( qApp->overrideCursor() )
566 qApp->restoreOverrideCursor();
575 _busyCursorTimer->start( BUSY_CURSOR_TIMEOUT );
581 return dim == YD_HORIZ ? _defaultSize.width() : _defaultSize.height();
593 _eventHandler.deletePendingEventsFor( widget );
599 yuiMilestone() <<
"Closing application" << std::endl;
607 QWidget * parent = 0;
608 YDialog * dialog = YDialog::currentDialog(
false );
611 parent = (QWidget *) dialog->widgetRep();
613 QString
id = QInputDialog::getText( parent,
615 _(
"Enter Widget ID:" )
617 if ( !
id.isEmpty() )
621 YWidget * widget = sendWidgetID( toUTF8(
id ) );
626 yuiMilestone() <<
"Activating " << widget << endl;
630 catch ( YUIWidgetNotFoundException & ex )
633 QMessageBox::warning( parent,
635 _(
"No widget with ID \"%1\"" ).arg(
id ) );
644 YQUISignalReceiver::YQUISignalReceiver()
650 void YQUISignalReceiver::slotBusyCursor()
656 void YQUISignalReceiver::slotReceivedYCPCommand()
664 qMessageHandler( QtMsgType type,
const QMessageLogContext &,
const QString & msg )
669 yuiMilestone() <<
"<libqt-debug> " << msg << std::endl;
672 #if QT_VERSION >= 0x050500 674 yuiMilestone() <<
"<libqt-info> " << msg << std::endl;
679 yuiWarning() <<
"<libqt-warning> " << msg << std::endl;
683 yuiError() <<
"<libqt-critical>" << msg << std::endl;
687 yuiError() <<
"<libqt-fatal> " << msg << std::endl;
692 if ( QString( msg ).contains(
"Fatal IO error", Qt::CaseInsensitive ) &&
693 QString( msg ).contains(
"client killed", Qt::CaseInsensitive ) )
694 yuiError() <<
"Client killed. Possibly caused by X server shutdown or crash." << std::endl;
701 const QString resource =
":/";
703 if ( QIcon::hasThemeIcon( iconName.c_str() ) )
705 yuiDebug() <<
"Trying theme icon from: " << iconName << std::endl;
706 icon = QIcon::fromTheme( iconName.c_str() );
711 yuiDebug() <<
"Trying icon from resource: " << iconName << std::endl;
712 icon = QIcon( resource + iconName.c_str() );
717 yuiDebug() <<
"Trying icon from path: " << iconName << std::endl;
718 icon = QIcon( iconName.c_str() );
722 yuiWarning() <<
"Couldn't load icon: " << iconName << std::endl;
int defaultSize(YUIDimension dim) const
Returns size for opt(defaultsize) dialogs (in one dimension).
void receivedYCPCommand()
Notification that a YCP command has been received on fd_ycp to leave idleLoop()
static YQApplication * yqApp()
Return the global YApplication object as YQApplication.
void forceUnblockEvents()
Force unblocking all events, no matter how many times blockEvents() has This returns 0 if there is no...
void setAutoFonts(bool useAutoFonts)
Set whether or not fonts should automatically be picked.
virtual YOptionalWidgetFactory * createOptionalWidgetFactory()
Create the widget factory that provides all the createXY() methods for optional ("special") widgets a...
void askSendWidgetID()
Open a pop-up dialog to ask the user for a widget ID and then send it with sendWidgetID().
void calcDefaultSize()
Calculate size of opt(defaultsize) dialogs.
QEventLoop * eventLoop()
Access to this dialog's event loop.
QIcon loadIcon(const string &iconName) const
Load an icon.
Helper class that acts as a Qt signal receiver for YQUI.
void sendEvent(YEvent *event)
Widget event handlers (slots) call this when an event occured that should be the answer to a UserInpu...
virtual void idleLoop(int fd_ycp)
Idle around until fd_ycp is readable and handle repaints.
void probeX11Display(const YCommandLine &cmdLine)
Probe the X11 display.
virtual void deleteNotify(YWidget *widget)
Notification that a widget is being deleted.
void busyCursor()
Show mouse cursor indicating busy state.
void processCommandLineArgs(int argc, char **argv)
Handle command line args.
YQUI(bool withThreads, bool topmostConstructor=true)
Constructors.
virtual void uiThreadDestructor()
Destroy whatever needs to be destroyed within the UI thread.
virtual void blockEvents(bool block=true)
Block (or unblock) events.
void timeoutBusyCursor()
Show mouse cursor indicating busy state if the UI is unable to respond to user input for more than a ...
bool close()
Application shutdown.
void normalCursor()
Show normal mouse cursor not indicating busy status.
virtual void initUI()
Post-constructor initialization.
virtual ~YQUI()
Destructor.
void raiseFatalError()
Raise a fatal UI error.
static void setTextdomain(const char *domain)
Initialize and set a textdomain for gettext()
static YQUI * ui()
Access the global Qt-UI.
virtual bool eventsBlocked() const
Returns 'true' if events are currently blocked.
virtual YWidgetFactory * createWidgetFactory()
Create the widget factory that provides all the createXY() methods for standard (mandatory, i.e.