25 #include <rpc/types.h>
33 #include <QSocketNotifier>
34 #include <QDesktopWidget>
38 #include <QMessageLogContext>
41 #define YUILogComponent "qt-ui"
42 #include <yui/YUILog.h>
43 #include <yui/Libyui_config.h>
47 #include <yui/YEvent.h>
48 #include <yui/YCommandLine.h>
49 #include <yui/YButtonBox.h>
50 #include <yui/YUISymbols.h>
52 #include "QY2Styler.h"
53 #include "YQApplication.h"
55 #include "YQWidgetFactory.h"
56 #include "YQOptionalWidgetFactory.h"
69 #define BUSY_CURSOR_TIMEOUT 200 // milliseconds
70 #define VERBOSE_EVENT_LOOP 0
74 static void qMessageHandler( QtMsgType type,
const QMessageLogContext &,
const QString & msg );
78 YUI * createUI(
bool withThreads )
84 if ( ui && ! withThreads )
97 , _do_exit_loop( false )
99 yuiDebug() <<
"YQUI constructor start" << std::endl;
100 yuiMilestone() <<
"This is libyui-qt " << VERSION << std::endl;
103 _uiInitialized =
false;
106 _usingVisionImpairedPalette =
false;
108 screenShotNameTemplate =
"";
111 qInstallMessageHandler( qMessageHandler );
113 yuiDebug() <<
"YQUI constructor finished" << std::endl;
115 topmostConstructorHasFinished();
121 if ( _uiInitialized )
124 _uiInitialized =
true;
125 yuiDebug() <<
"Initializing Qt part" << std::endl;
127 YCommandLine cmdLine;
128 std::string progName;
130 if ( cmdLine.argc() > 0 )
132 progName = cmdLine[0];
133 std::size_t lastSlashPos = progName.find_last_of(
'/' );
135 if ( lastSlashPos != std::string::npos )
136 progName = progName.substr( lastSlashPos+1 );
142 if ( progName ==
"y2base" )
143 cmdLine.replace( 0,
"YaST2" );
146 _ui_argc = cmdLine.argc();
147 char ** argv = cmdLine.argv();
152 yuiDebug() <<
"Creating QApplication" << std::endl;
153 new QApplication( _ui_argc, argv );
158 _busyCursorTimer =
new QTimer( _signalReceiver );
159 _busyCursorTimer->setSingleShot(
true );
161 _normalPalette = qApp->palette();
162 (void) QY2Styler::styler();
164 setButtonOrderFromEnvironment();
168 _do_exit_loop =
false;
176 _main_win =
new QWidget( 0, Qt::Window );
177 _main_win->setFocusPolicy( Qt::StrongFocus );
178 _main_win->setObjectName(
"main_window" );
180 _main_win->resize( _defaultSize );
183 _main_win->move( 0, 0 );
192 if ( progName ==
"y2base" )
193 _applicationTitle = QString(
"YaST2" );
195 _applicationTitle = fromUTF8( progName );
198 int displayArgPos = cmdLine.find(
"-display" );
201 if ( displayArgPos > 0 && displayArgPos+1 < cmdLine.argc() )
202 displayName = cmdLine[ displayArgPos+1 ].c_str();
204 displayName = getenv(
"DISPLAY" );
207 char hostname[ MAXHOSTNAMELEN+1 ];
208 if ( gethostname( hostname,
sizeof( hostname )-1 ) == 0 )
209 hostname[
sizeof( hostname ) -1 ] =
'\0';
214 if ( !displayName.startsWith(
":" ) && strlen( hostname ) > 0 )
216 _applicationTitle += QString(
"@" );
217 _applicationTitle += fromUTF8( hostname );
229 YButtonBoxMargins buttonBoxMargins;
230 buttonBoxMargins.left = 8;
231 buttonBoxMargins.right = 8;
232 buttonBoxMargins.top = 6;
233 buttonBoxMargins.bottom = 6;
235 buttonBoxMargins.spacing = 4;
236 buttonBoxMargins.helpButtonExtraSpacing = 16;
237 YButtonBox::setDefaultMargins( buttonBoxMargins );
259 QString qt_lib_name = QString( QTLIBDIR
"/libQtGui.so.%1" ).arg( QT_VERSION >> 16 );;
260 void * qt_lib = dlopen( qt_lib_name.toUtf8().constData(), RTLD_LAZY | RTLD_GLOBAL );
262 yuiMilestone() <<
"Forcing " << qt_lib_name.toUtf8().constData() <<
" open successful" << std::endl;
264 yuiError() <<
"Forcing " << qt_lib_name.toUtf8().constData() <<
" open failed" << std::endl;
268 qApp->setFont(
yqApp()->currentFont() );
272 QObject::connect( _busyCursorTimer, &pclass(_busyCursorTimer)::timeout,
273 _signalReceiver, &pclass(_signalReceiver)::slotBusyCursor );
275 yuiMilestone() <<
"YQUI initialized. Thread ID: 0x"
276 << hex << QThread::currentThreadId () << dec
279 qApp->processEvents();
294 for(
int i=0; i < argc; i++ )
296 QString opt = argv[i];
298 yuiMilestone() <<
"Qt argument: " << argv[i] << std::endl;
302 if ( opt.startsWith(
"--" ) )
305 if ( opt == QString(
"-fullscreen" ) ) _fullscreen =
true;
306 else if ( opt == QString(
"-noborder" ) ) _noborder =
true;
309 else if ( opt == QString(
"-gnome-button-order" ) ) YButtonBox::setLayoutPolicy( YButtonBox::gnomeLayoutPolicy() );
310 else if ( opt == QString(
"-kde-button-order" ) ) YButtonBox::setLayoutPolicy( YButtonBox::kdeLayoutPolicy() );
312 else if ( opt == QString(
"-help" ) )
315 "Command line options for the YaST2 Qt UI:\n"
317 "--nothreads run without additional UI threads\n"
318 "--fullscreen use full screen for `opt(`defaultsize) dialogs\n"
319 "--noborder no window manager border for `opt(`defaultsize) dialogs\n"
320 "--auto-fonts automatically pick fonts, disregard Qt standard settings\n"
321 "--help this help text\n"
323 "--macro <macro-file> play a macro right on startup\n"
325 "-no-wm, -noborder etc. are accepted as well as --no-wm, --noborder\n"
326 "to maintain backwards compatibility.\n"
342 yuiDebug() <<
"Closing down Qt UI." << std::endl;
353 delete _signalReceiver;
371 YUI_CHECK_NEW( factory );
378 YOptionalWidgetFactory *
382 YUI_CHECK_NEW( factory );
389 YQUI::createApplication()
392 YUI_CHECK_NEW( app );
400 QSize primaryScreenSize = qApp->desktop()->screenGeometry( qApp->desktop()->primaryScreen() ).size();
401 QSize availableSize = qApp->desktop()->availableGeometry( qApp->desktop()->primaryScreen() ).size();
405 _defaultSize = availableSize;
407 yuiMilestone() <<
"-fullscreen: using "
408 << _defaultSize.width() <<
" x " << _defaultSize.height()
409 <<
"for `opt(`defaultsize)"
418 if ( _defaultSize.width() < 800 ||
419 _defaultSize.height() < 600 )
421 if ( primaryScreenSize.width() >= 1024 && primaryScreenSize.height() >= 768 )
425 _defaultSize.setWidth ( max( (
int) (availableSize.width() * 0.7), 800 ) );
426 _defaultSize.setHeight( max( (
int) (availableSize.height() * 0.7), 600 ) );
430 _defaultSize = availableSize;
435 yuiMilestone() <<
"Forced size (via -geometry): "
436 << _defaultSize.width() <<
" x " << _defaultSize.height()
441 yuiMilestone() <<
"Default size: "
442 << _defaultSize.width() <<
" x " << _defaultSize.height()
451 _received_ycp_command =
false;
452 QSocketNotifier * notifier =
new QSocketNotifier( fd_ycp, QSocketNotifier::Read );
453 QObject::connect( notifier, &pclass(notifier)::activated,
454 _signalReceiver, &pclass(_signalReceiver)::slotReceivedYCPCommand );
456 notifier->setEnabled(
true );
463 #if VERBOSE_EVENT_LOOP
464 yuiDebug() <<
"Entering idle loop" << std::endl;
467 QEventLoop eventLoop( qApp );
469 while ( !_received_ycp_command )
470 eventLoop.processEvents( QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents );
472 #if VERBOSE_EVENT_LOOP
473 yuiDebug() <<
"Leaving idle loop" << std::endl;
482 _received_ycp_command =
true;
490 _eventHandler.sendEvent( event );
500 yuiError() <<
"No dialog" << std::endl;
508 bindtextdomain( domain, YSettings::localeDir().c_str() );
509 bind_textdomain_codeset( domain,
"utf8" );
510 textdomain( domain );
514 extern int _nl_msg_cat_cntr;
526 if ( ++_blockedLevel == 1 )
528 _eventHandler.blockEvents(
true );
532 if ( dialog && dialog->
eventLoop()->isRunning() )
534 yuiWarning() <<
"blocking events in active event loop of " << dialog << std::endl;
541 if ( --_blockedLevel == 0 )
543 _eventHandler.blockEvents(
false );
558 _eventHandler.blockEvents(
false );
564 return _eventHandler.eventsBlocked();
570 qApp->setOverrideCursor( Qt::BusyCursor );
576 if ( _busyCursorTimer->isActive() )
577 _busyCursorTimer->stop();
579 while ( qApp->overrideCursor() )
580 qApp->restoreOverrideCursor();
589 _busyCursorTimer->start( BUSY_CURSOR_TIMEOUT );
595 return dim == YD_HORIZ ? _defaultSize.width() : _defaultSize.height();
601 int displayArgPos = cmdLine.find(
"-display" );
602 std::string displayNameStr;
604 if ( displayArgPos > 0 && displayArgPos+1 < cmdLine.argc() )
606 displayNameStr = cmdLine[ displayArgPos+1 ];
607 yuiMilestone() <<
"Using X11 display \"" << displayNameStr <<
"\"" << std::endl;
610 const char * displayName = ( displayNameStr.empty() ? 0 : displayNameStr.c_str() );
611 Display * display = XOpenDisplay( displayName );
615 yuiDebug() <<
"Probing X11 display successful" << std::endl;
616 XCloseDisplay( display );
620 string msg =
"Can't open display " + displayNameStr;
621 YUI_THROW( YUIException( msg ) );
628 _eventHandler.deletePendingEventsFor( widget );
634 if ( _usingVisionImpairedPalette )
638 _usingVisionImpairedPalette =
false;
644 _usingVisionImpairedPalette =
true;
652 const QColor dark ( 0x20, 0x20, 0x20 );
656 pal.setColor( QPalette::Active, QPalette::Background, Qt::black );
657 pal.setColor( QPalette::Active, QPalette::Foreground, Qt::cyan );
658 pal.setColor( QPalette::Active, QPalette::Text, Qt::cyan );
659 pal.setColor( QPalette::Active, QPalette::Base, dark );
660 pal.setColor( QPalette::Active, QPalette::Button, dark );
661 pal.setColor( QPalette::Active, QPalette::ButtonText, Qt::green );
662 pal.setColor( QPalette::Active, QPalette::Highlight, Qt::yellow );
663 pal.setColor( QPalette::Active, QPalette::HighlightedText, Qt::black );
666 pal.setColor( QPalette::Inactive, QPalette::Background, Qt::black );
667 pal.setColor( QPalette::Inactive, QPalette::Foreground, Qt::cyan );
668 pal.setColor( QPalette::Inactive, QPalette::Text, Qt::cyan );
669 pal.setColor( QPalette::Inactive, QPalette::Base, dark );
670 pal.setColor( QPalette::Inactive, QPalette::Button, dark );
671 pal.setColor( QPalette::Inactive, QPalette::ButtonText, Qt::green );
674 pal.setColor( QPalette::Disabled, QPalette::Background, Qt::black );
675 pal.setColor( QPalette::Disabled, QPalette::Foreground, Qt::gray );
676 pal.setColor( QPalette::Disabled, QPalette::Text, Qt::gray );
677 pal.setColor( QPalette::Disabled, QPalette::Base, dark );
678 pal.setColor( QPalette::Disabled, QPalette::Button, dark );
679 pal.setColor( QPalette::Disabled, QPalette::ButtonText, Qt::gray );
688 yuiMilestone() <<
"Closing application" << std::endl;
696 YQUISignalReceiver::YQUISignalReceiver()
702 void YQUISignalReceiver::slotBusyCursor()
708 void YQUISignalReceiver::slotReceivedYCPCommand()
716 qMessageHandler( QtMsgType type,
const QMessageLogContext &,
const QString & msg )
721 yuiMilestone() <<
"<libqt-debug> " << msg << std::endl;
725 yuiWarning() <<
"<libqt-warning> " << msg << std::endl;
729 yuiError() <<
"<libqt-critical>" << msg << std::endl;
733 yuiError() <<
"<libqt-fatal> " << msg << std::endl;
738 if ( QString( msg ).contains(
"Fatal IO error", Qt::CaseInsensitive ) &&
739 QString( msg ).contains(
"client killed", Qt::CaseInsensitive ) )
740 yuiError() <<
"Client killed. Possibly caused by X server shutdown or crash." << std::endl;
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...
int defaultSize(YUIDimension dim) const
Returns size for opt(defaultsize) dialogs (in one dimension).
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 calcDefaultSize()
Calculate size of opt(defaultsize) dialogs.
QEventLoop * eventLoop()
Access to this dialog's event loop.
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...
YQUI(bool withThreads)
Constructor.
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 bool eventsBlocked() const
Returns 'true' if events are currently blocked.
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.
static QPalette visionImpairedPalette()
Returns a high-contrast color palette suitable for vision impaired users.
virtual void uiThreadDestructor()
Destroy whatever needs to be destroyed within the UI thread.
QPalette normalPalette() const
Returns the normal color palette.
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.
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()
void toggleVisionImpairedPalette()
Toggle between the vision impaired and the normal color palette.
static YQUI * ui()
Access the global Qt-UI.
virtual YWidgetFactory * createWidgetFactory()
Create the widget factory that provides all the createXY() methods for standard (mandatory, i.e.