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
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;
void setAutoFonts(bool useAutoFonts)
Set whether or not fonts should automatically be picked.
QEventLoop * eventLoop()
Access to this dialog's event loop.
Helper class that acts as a Qt signal receiver for YQUI.
virtual void deleteNotify(YWidget *widget)
Notification that a widget is being deleted.
void probeX11Display(const YCommandLine &cmdLine)
Probe the X11 display.
virtual bool eventsBlocked() const
Returns 'true' if events are currently blocked.
void busyCursor()
Show mouse cursor indicating busy state.
virtual void idleLoop(int fd_ycp)
Idle around until fd_ycp is readable and handle repaints.
virtual ~YQUI()
Destructor.
void processCommandLineArgs(int argc, char **argv)
Handle command line args.
YQUI(bool withThreads, bool topmostConstructor=true)
Constructors.
virtual YOptionalWidgetFactory * createOptionalWidgetFactory()
Create the widget factory that provides all the createXY() methods for optional ("special") widgets a...
static YQUI * ui()
Access the global Qt-UI.
void askSendWidgetID()
Open a pop-up dialog to ask the user for a widget ID and then send it with sendWidgetID().
void timeoutBusyCursor()
Show mouse cursor indicating busy state if the UI is unable to respond to user input for more than a ...
void sendEvent(YEvent *event)
Widget event handlers (slots) call this when an event occured that should be the answer to a UserInpu...
static YQApplication * yqApp()
Return the global YApplication object as YQApplication.
virtual void initUI()
Post-constructor initialization.
int defaultSize(YUIDimension dim) const
Returns size for opt(defaultsize) dialogs (in one dimension).
void forceUnblockEvents()
Force unblocking all events, no matter how many times blockEvents() has This returns 0 if there is no...
virtual void blockEvents(bool block=true)
Block (or unblock) events.
bool close()
Application shutdown.
void receivedYCPCommand()
Notification that a YCP command has been received on fd_ycp to leave idleLoop()
void calcDefaultSize()
Calculate size of opt(defaultsize) dialogs.
QIcon loadIcon(const string &iconName) const
Load an icon.
virtual void uiThreadDestructor()
Destroy whatever needs to be destroyed within the UI thread.
void normalCursor()
Show normal mouse cursor not indicating busy status.
static void setTextdomain(const char *domain)
Initialize and set a textdomain for gettext()
void raiseFatalError()
Raise a fatal UI error.
virtual YWidgetFactory * createWidgetFactory()
Create the widget factory that provides all the createXY() methods for standard (mandatory,...