27 #include <sys/param.h> 35 #include <QSocketNotifier> 36 #include <QDesktopWidget> 40 #include <QMessageLogContext> 41 #include <QMessageBox> 43 #include <QInputDialog> 46 #define YUILogComponent "qt-ui" 47 #include <yui/YUILog.h> 48 #include <yui/Libyui_config.h> 52 #include <yui/YEvent.h> 53 #include <yui/YCommandLine.h> 54 #include <yui/YButtonBox.h> 55 #include <yui/YUISymbols.h> 57 #include "QY2Styler.h" 58 #include "YQApplication.h" 60 #include "YQWidgetFactory.h" 61 #include "YQOptionalWidgetFactory.h" 63 #include "YQWizardButton.h" 74 #define BUSY_CURSOR_TIMEOUT 200 // milliseconds 75 #define VERBOSE_EVENT_LOOP 0 81 #define TEXTDOMAIN "qt" 88 static void qMessageHandler( QtMsgType type,
const QMessageLogContext &,
const QString & msg );
92 YUI * createUI(
bool withThreads )
98 if ( ui && ! withThreads )
111 , _do_exit_loop( false )
113 yuiDebug() <<
"YQUI constructor start" << endl;
114 yuiMilestone() <<
"This is libyui-qt " << VERSION << endl;
117 _uiInitialized =
false;
123 qInstallMessageHandler( qMessageHandler );
125 yuiDebug() <<
"YQUI constructor finished" << endl;
126 if ( topmostConstructor ) {
127 yuiDebug() <<
"YQUI is the top most constructor" << endl;
128 topmostConstructorHasFinished();
135 if ( _uiInitialized )
138 _uiInitialized =
true;
139 yuiDebug() <<
"Initializing Qt part" << endl;
141 YCommandLine cmdLine;
144 if ( cmdLine.argc() > 0 )
146 progName = cmdLine[0];
147 std::size_t lastSlashPos = progName.find_last_of(
'/' );
149 if ( lastSlashPos != string::npos )
150 progName = progName.substr( lastSlashPos+1 );
156 if ( progName ==
"y2base" )
157 cmdLine.replace( 0,
"YaST2" );
160 _ui_argc = cmdLine.argc();
161 char ** argv = cmdLine.argv();
163 yuiDebug() <<
"Creating QApplication" << endl;
164 QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
165 new QApplication( _ui_argc, argv );
170 _busyCursorTimer =
new QTimer( _signalReceiver );
171 _busyCursorTimer->setSingleShot(
true );
173 (void) QY2Styler::styler();
175 setButtonOrderFromEnvironment();
179 _do_exit_loop =
false;
187 _main_win =
new QWidget( 0, Qt::Window );
188 _main_win->setFocusPolicy( Qt::StrongFocus );
189 _main_win->setObjectName(
"main_window" );
191 _main_win->resize( _defaultSize );
194 _main_win->move( 0, 0 );
203 if ( progName ==
"y2base" )
204 _applicationTitle = QString(
"YaST2" );
206 _applicationTitle = fromUTF8( progName );
209 int displayArgPos = cmdLine.find(
"-display" );
212 if ( displayArgPos > 0 && displayArgPos+1 < cmdLine.argc() )
213 displayName = cmdLine[ displayArgPos+1 ].c_str();
215 displayName = getenv(
"DISPLAY" );
218 char hostname[ MAXHOSTNAMELEN+1 ];
219 if ( gethostname( hostname,
sizeof( hostname )-1 ) == 0 )
220 hostname[
sizeof( hostname ) -1 ] =
'\0';
225 if ( !displayName.startsWith(
":" ) && strlen( hostname ) > 0 )
227 _applicationTitle += QString(
"@" );
228 _applicationTitle += fromUTF8( hostname );
240 YButtonBoxMargins buttonBoxMargins;
241 buttonBoxMargins.left = 8;
242 buttonBoxMargins.right = 8;
243 buttonBoxMargins.top = 6;
244 buttonBoxMargins.bottom = 6;
246 buttonBoxMargins.spacing = 4;
247 buttonBoxMargins.helpButtonExtraSpacing = 16;
248 YButtonBox::setDefaultMargins( buttonBoxMargins );
252 qApp->setFont(
yqApp()->currentFont() );
256 QObject::connect( _busyCursorTimer, &pclass(_busyCursorTimer)::timeout,
257 _signalReceiver, &pclass(_signalReceiver)::slotBusyCursor );
259 yuiMilestone() <<
"YQUI initialized. Thread ID: 0x" 260 << hex << QThread::currentThreadId () << dec
263 qApp->processEvents();
278 for(
int i=0; i < argc; i++ )
280 QString opt = argv[i];
282 yuiMilestone() <<
"Qt argument: " << argv[i] << endl;
286 if ( opt.startsWith(
"--" ) )
289 if ( opt == QString(
"-fullscreen" ) ) _fullscreen =
true;
290 else if ( opt == QString(
"-noborder" ) ) _noborder =
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() );
296 else if ( opt == QString(
"-help" ) )
299 "Command line options for the YaST2 Qt UI:\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" 307 "--macro <macro-file> play a macro right on startup\n" 309 "-no-wm, -noborder etc. are accepted as well as --no-wm, --noborder\n" 310 "to maintain backwards compatibility.\n" 325 yuiMilestone() <<
"Closing down Qt UI." << endl;
336 delete _signalReceiver;
343 yuiMilestone() <<
"Destroying UI thread" << endl;
347 if ( YDialog::openDialogsCount() > 0 )
349 yuiError() << YDialog::openDialogsCount() <<
" open dialogs left over" << endl;
350 yuiError() <<
"Topmost dialog:" << endl;
351 YDialog::topmostDialog()->dumpWidgetTree();
354 YDialog::deleteAllDialogs();
365 YUI_CHECK_NEW( factory );
371 YOptionalWidgetFactory *
375 YUI_CHECK_NEW( factory );
382 YQUI::createApplication()
385 YUI_CHECK_NEW( app );
393 QScreen * screen = qApp->primaryScreen();
394 QSize primaryScreenSize = screen->size();
395 QSize availableSize = screen->availableSize();
399 _defaultSize = availableSize;
401 yuiMilestone() <<
"-fullscreen: using " 402 << _defaultSize.width() <<
" x " << _defaultSize.height()
403 <<
"for `opt(`defaultsize)" 412 if ( _defaultSize.width() < 800 ||
413 _defaultSize.height() < 600 )
415 if ( primaryScreenSize.width() >= 1024 && primaryScreenSize.height() >= 768 )
419 _defaultSize.setWidth ( std::max( (
int) (availableSize.width() * 0.7), 800 ) );
420 _defaultSize.setHeight( std::max( (
int) (availableSize.height() * 0.7), 600 ) );
424 _defaultSize = availableSize;
429 yuiMilestone() <<
"Forced size (via -geometry): " 430 << _defaultSize.width() <<
" x " << _defaultSize.height()
435 yuiMilestone() <<
"Default size: " 436 << _defaultSize.width() <<
" x " << _defaultSize.height()
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 );
450 notifier->setEnabled(
true );
457 #if VERBOSE_EVENT_LOOP 458 yuiDebug() <<
"Entering idle loop" << endl;
461 QEventLoop eventLoop( qApp );
463 while ( !_received_ycp_command )
464 eventLoop.processEvents( QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents );
466 #if VERBOSE_EVENT_LOOP 467 yuiDebug() <<
"Leaving idle loop" << endl;
476 _received_ycp_command =
true;
484 _eventHandler.sendEvent( event );
494 yuiError() <<
"No dialog" << endl;
502 bindtextdomain( domain, YSettings::localeDir().c_str() );
503 bind_textdomain_codeset( domain,
"utf8" );
504 textdomain( domain );
508 extern int _nl_msg_cat_cntr;
520 if ( ++_blockedLevel == 1 )
522 _eventHandler.blockEvents(
true );
526 if ( dialog && dialog->
eventLoop()->isRunning() )
528 yuiWarning() <<
"blocking events in active event loop of " << dialog << endl;
535 if ( --_blockedLevel == 0 )
537 _eventHandler.blockEvents(
false );
552 _eventHandler.blockEvents(
false );
558 return _eventHandler.eventsBlocked();
564 qApp->setOverrideCursor( Qt::BusyCursor );
570 if ( _busyCursorTimer->isActive() )
571 _busyCursorTimer->stop();
573 while ( qApp->overrideCursor() )
574 qApp->restoreOverrideCursor();
583 _busyCursorTimer->start( BUSY_CURSOR_TIMEOUT );
589 return dim == YD_HORIZ ? _defaultSize.width() : _defaultSize.height();
601 _eventHandler.deletePendingEventsFor( widget );
607 yuiMilestone() <<
"Closing application" << endl;
615 QWidget * parent = 0;
616 YDialog * dialog = YDialog::currentDialog(
false );
621 parent = (QWidget *) dialog->widgetRep();
623 QString
id = QInputDialog::getText( parent,
625 _(
"Enter Widget ID:" )
627 if ( !
id.isEmpty() )
631 YWidget * widget = sendWidgetID( toUTF8(
id ) );
636 yuiMilestone() <<
"Activating " << widget << endl;
640 catch ( YUIWidgetNotFoundException & ex )
643 QMessageBox::warning( parent,
645 _(
"No widget with ID \"%1\"" ).arg(
id ) );
654 YQUISignalReceiver::YQUISignalReceiver()
660 void YQUISignalReceiver::slotBusyCursor()
666 void YQUISignalReceiver::slotReceivedYCPCommand()
674 qMessageHandler( QtMsgType type,
const QMessageLogContext &,
const QString & msg )
679 yuiMilestone() <<
"<libqt-debug> " << msg << endl;
682 #if QT_VERSION >= 0x050500 684 yuiMilestone() <<
"<libqt-info> " << msg << endl;
689 yuiWarning() <<
"<libqt-warning> " << msg << endl;
693 yuiError() <<
"<libqt-critical>" << msg << endl;
697 yuiError() <<
"<libqt-fatal> " << msg << endl;
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;
711 const QString resource =
":/";
713 if ( QIcon::hasThemeIcon( iconName.c_str() ) )
715 yuiDebug() <<
"Trying theme icon from: " << iconName << endl;
716 icon = QIcon::fromTheme( iconName.c_str() );
721 yuiDebug() <<
"Trying icon from resource: " << iconName << endl;
722 icon = QIcon( resource + iconName.c_str() );
727 yuiDebug() <<
"Trying icon from path: " << iconName << endl;
728 icon = QIcon( iconName.c_str() );
732 yuiWarning() <<
"Couldn't load icon: " << iconName << 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.