kdeui Library API Documentation

kmainwindow.cpp

00001 /* This file is part of the KDE libraries 00002 Copyright 00003 (C) 2000 Reginald Stadlbauer (reggie@kde.org) 00004 (C) 1997 Stephan Kulow (coolo@kde.org) 00005 (C) 1997-2000 Sven Radej (radej@kde.org) 00006 (C) 1997-2000 Matthias Ettrich (ettrich@kde.org) 00007 (C) 1999 Chris Schlaeger (cs@kde.org) 00008 (C) 2002 Joseph Wenninger (jowenn@kde.org) 00009 00010 This library is free software; you can redistribute it and/or 00011 modify it under the terms of the GNU Library General Public 00012 License version 2 as published by the Free Software Foundation. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Library General Public License for more details. 00018 00019 You should have received a copy of the GNU Library General Public License 00020 along with this library; see the file COPYING.LIB. If not, write to 00021 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00022 Boston, MA 02111-1307, USA. 00023 */ 00024 #include "config.h" 00025 00026 #include "kmainwindow.h" 00027 #include "kmainwindowiface.h" 00028 #include "ktoolbarhandler.h" 00029 #include <qsessionmanager.h> 00030 #include <qobjectlist.h> 00031 #include <qstyle.h> 00032 #include <qlayout.h> 00033 #include <qwidgetlist.h> 00034 #include <qtimer.h> 00035 00036 #include <kaccel.h> 00037 #include <kaction.h> 00038 #include <kapplication.h> 00039 #include <kconfig.h> 00040 #include <kdebug.h> 00041 #include <khelpmenu.h> 00042 #include <kmenubar.h> 00043 #include <kstatusbar.h> 00044 #include <kwin.h> 00045 #include <kedittoolbar.h> 00046 #include <kmainwindow.h> 00047 00048 #include <klocale.h> 00049 #include <kstandarddirs.h> 00050 #include <kstaticdeleter.h> 00051 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00052 #include <netwm.h> 00053 #endif 00054 00055 #include <stdlib.h> 00056 #include <ctype.h> 00057 #include <assert.h> 00058 00059 class KMainWindowPrivate { 00060 public: 00061 bool showHelpMenu:1; 00062 00063 bool autoSaveSettings:1; 00064 bool settingsDirty:1; 00065 bool autoSaveWindowSize:1; 00066 bool care_about_geometry:1; 00067 bool shuttingDown:1; 00068 QString autoSaveGroup; 00069 KAccel * kaccel; 00070 KMainWindowInterface *m_interface; 00071 KDEPrivate::ToolBarHandler *toolBarHandler; 00072 QTimer* settingsTimer; 00073 KToggleAction *showStatusBarAction; 00074 QRect defaultWindowSize; 00075 QPtrList<QDockWindow> hiddenDockWindows; 00076 }; 00077 00078 QPtrList<KMainWindow>* KMainWindow::memberList = 0L; 00079 static bool no_query_exit = false; 00080 static KMWSessionManaged* ksm = 0; 00081 static KStaticDeleter<KMWSessionManaged> ksmd; 00082 00083 class KMWSessionManaged : public KSessionManaged 00084 { 00085 public: 00086 KMWSessionManaged() 00087 { 00088 }; 00089 ~KMWSessionManaged() 00090 { 00091 } 00092 bool saveState( QSessionManager& ) 00093 { 00094 KConfig* config = KApplication::kApplication()->sessionConfig(); 00095 if ( KMainWindow::memberList->first() ){ 00096 // According to Jochen Wilhelmy <digisnap@cs.tu-berlin.de>, this 00097 // hook is useful for better document orientation 00098 KMainWindow::memberList->first()->saveGlobalProperties(config); 00099 } 00100 00101 QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); 00102 int n = 0; 00103 for (it.toFirst(); it.current(); ++it){ 00104 n++; 00105 it.current()->savePropertiesInternal(config, n); 00106 } 00107 config->setGroup(QString::fromLatin1("Number")); 00108 config->writeEntry(QString::fromLatin1("NumberOfWindows"), n ); 00109 return true; 00110 } 00111 00112 bool commitData( QSessionManager& sm ) 00113 { 00114 // not really a fast method but the only compatible one 00115 if ( sm.allowsInteraction() ) { 00116 bool canceled = false; 00117 QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); 00118 ::no_query_exit = true; 00119 for (it.toFirst(); it.current() && !canceled;){ 00120 KMainWindow *window = *it; 00121 ++it; // Update now, the current window might get deleted 00122 if ( !window->testWState( Qt::WState_ForceHide ) ) { 00123 QCloseEvent e; 00124 QApplication::sendEvent( window, &e ); 00125 canceled = !e.isAccepted(); 00126 /* Don't even think_about deleting widgets with 00127 Qt::WDestructiveClose flag set at this point. We 00128 are faking a close event, but we are *not*_ 00129 closing the window. The purpose of the faked 00130 close event is to prepare the application so it 00131 can safely be quit without the user losing data 00132 (possibly showing a message box "do you want to 00133 save this or that?"). It is possible that the 00134 session manager quits the application later 00135 (emitting QApplication::aboutToQuit() when this 00136 happens), but it is also possible that the user 00137 cancels the shutdown, so the application will 00138 continue to run. 00139 */ 00140 } 00141 } 00142 ::no_query_exit = false; 00143 if (canceled) 00144 return false; 00145 00146 KMainWindow* last = 0; 00147 for (it.toFirst(); it.current() && !canceled; ++it){ 00148 KMainWindow *window = *it; 00149 if ( !window->testWState( Qt::WState_ForceHide ) ) { 00150 last = window; 00151 } 00152 } 00153 if ( last ) 00154 return last->queryExit(); 00155 // else 00156 return true; 00157 } 00158 00159 // the user wants it, the user gets it 00160 return true; 00161 } 00162 }; 00163 00164 static bool being_first = true; 00165 00166 KMainWindow::KMainWindow( QWidget* parent, const char *name, WFlags f ) 00167 : QMainWindow( parent, name, f ), KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 ) 00168 { 00169 initKMainWindow(name, 0); 00170 } 00171 00172 KMainWindow::KMainWindow( int cflags, QWidget* parent, const char *name, WFlags f ) 00173 : QMainWindow( parent, name, f ), KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 ) 00174 { 00175 initKMainWindow(name, cflags); 00176 } 00177 00178 void KMainWindow::initKMainWindow(const char *name, int cflags) 00179 { 00180 setDockMenuEnabled( false ); 00181 mHelpMenu = 0; 00182 kapp->setTopWidget( this ); 00183 actionCollection()->setWidget( this ); 00184 connect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown())); 00185 if( !memberList ) 00186 memberList = new QPtrList<KMainWindow>; 00187 00188 if ( !ksm ) 00189 ksm = ksmd.setObject(ksm, new KMWSessionManaged()); 00190 // set a unique object name. Required by session management. 00191 QCString objname; 00192 QCString s; 00193 int unusedNumber; 00194 if ( !name ) 00195 { // no name given 00196 objname = kapp->instanceName() + "-mainwindow#"; 00197 s = objname + '1'; // start adding number immediately 00198 unusedNumber = 1; 00199 } 00200 else if( name[ strlen( name ) - 1 ] == '#' ) 00201 { // trailing # - always add a number 00202 objname = name; 00203 s = objname + '1'; // start adding number immediately 00204 unusedNumber = 1; 00205 } 00206 else 00207 { 00208 objname = name; 00209 s = objname; 00210 unusedNumber = 0; // add numbers only when needed 00211 } 00212 for(;;) { 00213 QWidgetList* list = kapp->topLevelWidgets(); 00214 QWidgetListIt it( *list ); 00215 bool found = false; 00216 for( QWidget* w = it.current(); 00217 w != NULL; 00218 ++it, w = it.current()) 00219 if( w != this && w->name() == s ) 00220 { 00221 found = true; 00222 break; 00223 } 00224 delete list; 00225 if( !found ) 00226 break; 00227 s.setNum( ++unusedNumber ); 00228 s = objname + s; 00229 } 00230 setName( s ); 00231 00232 memberList->append( this ); 00233 00234 d = new KMainWindowPrivate; 00235 d->showHelpMenu = true; 00236 d->settingsDirty = false; 00237 d->autoSaveSettings = false; 00238 d->autoSaveWindowSize = true; // for compatibility 00239 d->kaccel = actionCollection()->kaccel(); 00240 d->toolBarHandler = 0; 00241 d->settingsTimer = 0; 00242 d->showStatusBarAction = NULL; 00243 d->shuttingDown = false; 00244 if ((d->care_about_geometry = being_first)) { 00245 being_first = false; 00246 if ( kapp->geometryArgument().isNull() ) // if there is no geometry, it doesn't mater 00247 d->care_about_geometry = false; 00248 else 00249 parseGeometry(false); 00250 } 00251 00252 setCaption( kapp->caption() ); 00253 if ( cflags & NoDCOPObject) 00254 d->m_interface = 0; 00255 else 00256 d->m_interface = new KMainWindowInterface(this); 00257 00258 if (!kapp->authorize("movable_toolbars")) 00259 setDockWindowsMovable(false); 00260 } 00261 00262 KAction *KMainWindow::toolBarMenuAction() 00263 { 00264 if ( !d->toolBarHandler ) 00265 return 0; 00266 00267 return d->toolBarHandler->toolBarMenuAction(); 00268 } 00269 00270 void KMainWindow::parseGeometry(bool parsewidth) 00271 { 00272 assert ( !kapp->geometryArgument().isNull() ); 00273 assert ( d->care_about_geometry ); 00274 00275 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00276 //#ifndef Q_WS_QWS 00277 // FIXME: (E) Implement something similar for Qt Embedded (or decide we don't need it) 00278 int x, y; 00279 int w, h; 00280 int m = XParseGeometry( kapp->geometryArgument().latin1(), &x, &y, (unsigned int*)&w, (unsigned int*)&h); 00281 if (parsewidth) { 00282 QSize minSize = minimumSize(); 00283 QSize maxSize = maximumSize(); 00284 if ( (m & WidthValue) == 0 ) 00285 w = width(); 00286 if ( (m & HeightValue) == 0 ) 00287 h = height(); 00288 w = QMIN(w,maxSize.width()); 00289 h = QMIN(h,maxSize.height()); 00290 w = QMAX(w,minSize.width()); 00291 h = QMAX(h,minSize.height()); 00292 resize(w, h); 00293 } else { 00294 if ( parsewidth && (m & XValue) == 0 ) 00295 x = geometry().x(); 00296 if ( parsewidth && (m & YValue) == 0 ) 00297 y = geometry().y(); 00298 if ( (m & XNegative) ) 00299 x = KApplication::desktop()->width() + x - w; 00300 if ( (m & YNegative) ) 00301 y = KApplication::desktop()->height() + y - h; 00302 move(x, y); 00303 } 00304 #endif 00305 } 00306 00307 KMainWindow::~KMainWindow() 00308 { 00309 delete d->settingsTimer; 00310 QMenuBar* mb = internalMenuBar(); 00311 delete mb; 00312 delete d->m_interface; 00313 delete d; 00314 memberList->remove( this ); 00315 } 00316 00317 KPopupMenu* KMainWindow::helpMenu( const QString &aboutAppText, bool showWhatsThis ) 00318 { 00319 if( mHelpMenu == 0 ) { 00320 if ( aboutAppText.isEmpty() ) 00321 mHelpMenu = new KHelpMenu( this, instance()->aboutData(), showWhatsThis); 00322 else 00323 mHelpMenu = new KHelpMenu( this, aboutAppText, showWhatsThis ); 00324 00325 if ( mHelpMenu == 0 ) 00326 return 0; 00327 connect( mHelpMenu, SIGNAL( showAboutApplication() ), 00328 this, SLOT( showAboutApplication() ) ); 00329 } 00330 00331 return mHelpMenu->menu(); 00332 } 00333 00334 KPopupMenu* KMainWindow::customHelpMenu( bool showWhatsThis ) 00335 { 00336 if( mHelpMenu == 0 ) { 00337 mHelpMenu = new KHelpMenu( this, QString::null, showWhatsThis ); 00338 connect( mHelpMenu, SIGNAL( showAboutApplication() ), 00339 this, SLOT( showAboutApplication() ) ); 00340 } 00341 00342 return mHelpMenu->menu(); 00343 } 00344 00345 bool KMainWindow::canBeRestored( int number ) 00346 { 00347 if ( !kapp->isRestored() ) 00348 return false; 00349 KConfig *config = kapp->sessionConfig(); 00350 if ( !config ) 00351 return false; 00352 config->setGroup( QString::fromLatin1("Number") ); 00353 int n = config->readNumEntry( QString::fromLatin1("NumberOfWindows") , 1 ); 00354 return number >= 1 && number <= n; 00355 } 00356 00357 const QString KMainWindow::classNameOfToplevel( int number ) 00358 { 00359 if ( !kapp->isRestored() ) 00360 return QString::null; 00361 KConfig *config = kapp->sessionConfig(); 00362 if ( !config ) 00363 return QString::null; 00364 QString s; 00365 s.setNum( number ); 00366 s.prepend( QString::fromLatin1("WindowProperties") ); 00367 config->setGroup( s ); 00368 if ( !config->hasKey( QString::fromLatin1("ClassName") ) ) 00369 return QString::null; 00370 else 00371 return config->readEntry( QString::fromLatin1("ClassName") ); 00372 } 00373 00374 void KMainWindow::show() 00375 { 00376 QMainWindow::show(); 00377 00378 for ( QPtrListIterator<QDockWindow> it( d->hiddenDockWindows ); it.current(); ++it ) 00379 it.current()->show(); 00380 00381 d->hiddenDockWindows.clear(); 00382 } 00383 00384 void KMainWindow::hide() 00385 { 00386 if ( isVisible() ) { 00387 00388 d->hiddenDockWindows.clear(); 00389 00390 QObjectList *list = queryList( "QDockWindow" ); 00391 for( QObjectListIt it( *list ); it.current(); ++it ) { 00392 QDockWindow *dw = (QDockWindow*)it.current(); 00393 if ( dw->isTopLevel() && dw->isVisible() ) { 00394 d->hiddenDockWindows.append( dw ); 00395 dw->hide(); 00396 } 00397 } 00398 delete list; 00399 } 00400 00401 QWidget::hide(); 00402 } 00403 00404 bool KMainWindow::restore( int number, bool show ) 00405 { 00406 if ( !canBeRestored( number ) ) 00407 return false; 00408 KConfig *config = kapp->sessionConfig(); 00409 if ( readPropertiesInternal( config, number ) ){ 00410 if ( show ) 00411 KMainWindow::show(); 00412 return false; 00413 } 00414 return false; 00415 } 00416 00417 KXMLGUIFactory *KMainWindow::guiFactory() 00418 { 00419 if ( !factory_ ) 00420 factory_ = new KXMLGUIFactory( this, this, "guifactory" ); 00421 return factory_; 00422 } 00423 00424 int KMainWindow::configureToolbars() 00425 { 00426 saveMainWindowSettings(KGlobal::config()); 00427 KEditToolbar dlg(actionCollection(), xmlFile(), true, this); 00428 connect(&dlg, SIGNAL(newToolbarConfig()), SLOT(saveNewToolbarConfig())); 00429 return dlg.exec(); 00430 } 00431 00432 void KMainWindow::saveNewToolbarConfig() 00433 { 00434 createGUI(xmlFile()); 00435 applyMainWindowSettings( KGlobal::config() ); 00436 } 00437 00438 void KMainWindow::setupGUI( int options, const QString & xmlfile ) { 00439 if( options & Keys ){ 00440 KStdAction::keyBindings(guiFactory(), 00441 SLOT(configureShortcuts()), actionCollection()); 00442 } 00443 00444 if( (options & StatusBar) && internalStatusBar() ){ 00445 createStandardStatusBarAction(); 00446 } 00447 00448 if( options & ToolBar ){ 00449 setStandardToolBarMenuEnabled( true ); 00450 KStdAction::configureToolbars(this, 00451 SLOT(configureToolbars() ), actionCollection()); 00452 } 00453 00454 if( options & Create ){ 00455 createGUI(xmlfile); 00456 } 00457 00458 if( options & Save ){ 00459 // setupGUI() is typically called in the constructor before show(), 00460 // so the default window size will be incorrect unless the application 00461 // hard coded the size which they should try not to do (i.e. use 00462 // size hints). 00463 if(!isShown()) 00464 adjustSize(); 00465 setAutoSaveSettings(); 00466 } 00467 00468 } 00469 00470 void KMainWindow::createGUI( const QString &xmlfile, bool _conserveMemory ) 00471 { 00472 // disabling the updates prevents unnecessary redraws 00473 setUpdatesEnabled( false ); 00474 00475 // just in case we are rebuilding, let's remove our old client 00476 guiFactory()->removeClient( this ); 00477 00478 // make sure to have an empty GUI 00479 QMenuBar* mb = internalMenuBar(); 00480 if ( mb ) 00481 mb->clear(); 00482 00483 (void)toolBarIterator(); // make sure toolbarList is most-up-to-date 00484 toolbarList.setAutoDelete( true ); 00485 toolbarList.clear(); 00486 toolbarList.setAutoDelete( false ); 00487 00488 // don't build a help menu unless the user ask for it 00489 if (d->showHelpMenu) { 00490 // we always want a help menu 00491 if (helpMenu2 == 0) 00492 helpMenu2 = new KHelpMenu(this, instance()->aboutData(), true, 00493 actionCollection()); 00494 } 00495 00496 // we always want to load in our global standards file 00497 setXMLFile( locate( "config", "ui/ui_standards.rc", instance() ) ); 00498 00499 // now, merge in our local xml file. if this is null, then that 00500 // means that we will be only using the global file 00501 if ( !xmlfile.isNull() ) { 00502 setXMLFile( xmlfile, true ); 00503 } else { 00504 QString auto_file(instance()->instanceName() + "ui.rc"); 00505 setXMLFile( auto_file, true ); 00506 } 00507 00508 // make sure we don't have any state saved already 00509 setXMLGUIBuildDocument( QDomDocument() ); 00510 00511 // do the actual GUI building 00512 guiFactory()->addClient( this ); 00513 00514 // try and get back *some* of our memory 00515 if ( _conserveMemory ) 00516 { 00517 // before freeing the memory allocated by the DOM document we also 00518 // free all memory allocated internally in the KXMLGUIFactory for 00519 // the menubar and the toolbars . This however implies that we 00520 // have to take care of deleting those widgets ourselves. For 00521 // destruction this is no problem, but when rebuilding we have 00522 // to take care of that (and we want to rebuild the GUI when 00523 // using stuff like the toolbar editor ). 00524 // In addition we have to take care of not removing containers 00525 // like popupmenus, defined in the XML document. 00526 // this code should probably go into a separate method in KMainWindow. 00527 // there's just one problem: I'm bad in finding names ;-) , so 00528 // I skipped this ;-) 00529 00530 QDomDocument doc = domDocument(); 00531 00532 for( QDomNode n = doc.documentElement().firstChild(); 00533 !n.isNull(); n = n.nextSibling()) 00534 { 00535 QDomElement e = n.toElement(); 00536 00537 if ( e.tagName().lower() == "toolbar" ) 00538 factory_->resetContainer( e.attribute( "name" ) ); 00539 else if ( e.tagName().lower() == "menubar" ) 00540 factory_->resetContainer( e.tagName(), true ); 00541 } 00542 00543 conserveMemory(); 00544 } 00545 00546 setUpdatesEnabled( true ); 00547 updateGeometry(); 00548 } 00549 00550 void KMainWindow::setHelpMenuEnabled(bool showHelpMenu) 00551 { 00552 d->showHelpMenu = showHelpMenu; 00553 } 00554 00555 bool KMainWindow::isHelpMenuEnabled() 00556 { 00557 return d->showHelpMenu; 00558 } 00559 00560 void KMainWindow::setCaption( const QString &caption ) 00561 { 00562 setPlainCaption( kapp->makeStdCaption(caption) ); 00563 } 00564 00565 void KMainWindow::setCaption( const QString &caption, bool modified ) 00566 { 00567 setPlainCaption( kapp->makeStdCaption(caption, true, modified) ); 00568 } 00569 00570 void KMainWindow::setPlainCaption( const QString &caption ) 00571 { 00572 QMainWindow::setCaption( caption ); 00573 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00574 //#ifndef Q_WS_QWS 00575 NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), 0 ); 00576 info.setName( caption.utf8().data() ); 00577 #endif 00578 } 00579 00580 void KMainWindow::appHelpActivated( void ) 00581 { 00582 if( mHelpMenu == 0 ) { 00583 mHelpMenu = new KHelpMenu( this ); 00584 if ( mHelpMenu == 0 ) 00585 return; 00586 } 00587 mHelpMenu->appHelpActivated(); 00588 } 00589 00590 void KMainWindow::slotStateChanged(const QString &newstate) 00591 { 00592 stateChanged(newstate, KXMLGUIClient::StateNoReverse); 00593 } 00594 00595 /* 00596 * Get rid of this for KDE 4.0 00597 */ 00598 void KMainWindow::slotStateChanged(const QString &newstate, 00599 KXMLGUIClient::ReverseStateChange reverse) 00600 { 00601 stateChanged(newstate, reverse); 00602 } 00603 00604 /* 00605 * Enable this for KDE 4.0 00606 */ 00607 // void KMainWindow::slotStateChanged(const QString &newstate, 00608 // bool reverse) 00609 // { 00610 // stateChanged(newstate, 00611 // reverse ? KXMLGUIClient::StateReverse : KXMLGUIClient::StateNoReverse); 00612 // } 00613 00614 void KMainWindow::closeEvent ( QCloseEvent *e ) 00615 { 00616 // Save settings if auto-save is enabled, and settings have changed 00617 if (d->settingsDirty && d->autoSaveSettings) 00618 saveAutoSaveSettings(); 00619 00620 if (queryClose()) { 00621 e->accept(); 00622 00623 int not_withdrawn = 0; 00624 QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); 00625 for (it.toFirst(); it.current(); ++it){ 00626 if ( !it.current()->isHidden() && it.current()->isTopLevel() && it.current() != this ) 00627 not_withdrawn++; 00628 } 00629 00630 if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted? 00631 if ( queryExit() && !kapp->sessionSaving() && !d->shuttingDown ) { // Yes, Quit app? 00632 // don't call queryExit() twice 00633 disconnect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown())); 00634 d->shuttingDown = true; 00635 kapp->deref(); // ...and quit application. 00636 } else { 00637 // cancel closing, it's stupid to end up with no windows at all.... 00638 e->ignore(); 00639 } 00640 } 00641 } 00642 } 00643 00644 bool KMainWindow::queryExit() 00645 { 00646 return true; 00647 } 00648 00649 bool KMainWindow::queryClose() 00650 { 00651 return true; 00652 } 00653 00654 void KMainWindow::saveGlobalProperties( KConfig* ) 00655 { 00656 } 00657 00658 void KMainWindow::readGlobalProperties( KConfig* ) 00659 { 00660 } 00661 00662 #if defined(KDE_COMPAT) 00663 void KMainWindow::updateRects() 00664 { 00665 } 00666 #endif 00667 00668 void KMainWindow::showAboutApplication() 00669 { 00670 } 00671 00672 void KMainWindow::savePropertiesInternal( KConfig *config, int number ) 00673 { 00674 bool oldASWS = d->autoSaveWindowSize; 00675 d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size 00676 00677 QString s; 00678 s.setNum(number); 00679 s.prepend(QString::fromLatin1("WindowProperties")); 00680 config->setGroup(s); 00681 00682 // store objectName, className, Width and Height for later restoring 00683 // (Only useful for session management) 00684 config->writeEntry(QString::fromLatin1("ObjectName"), name()); 00685 config->writeEntry(QString::fromLatin1("ClassName"), className()); 00686 00687 saveMainWindowSettings(config); // Menubar, statusbar and Toolbar settings. 00688 00689 s.setNum(number); 00690 config->setGroup(s); 00691 saveProperties(config); 00692 00693 d->autoSaveWindowSize = oldASWS; 00694 } 00695 00696 void KMainWindow::saveMainWindowSettings(KConfig *config, const QString &configGroup) 00697 { 00698 kdDebug(200) << "KMainWindow::saveMainWindowSettings " << configGroup << endl; 00699 QString oldGroup; 00700 00701 if (!configGroup.isEmpty()) 00702 { 00703 oldGroup = config->group(); 00704 config->setGroup(configGroup); 00705 } 00706 00707 // Called by session management - or if we want to save the window size anyway 00708 if ( d->autoSaveWindowSize ) 00709 saveWindowSize( config ); 00710 00711 QStatusBar* sb = internalStatusBar(); 00712 if (sb) { 00713 if(!config->hasDefault("StatusBar") && !sb->isHidden() ) 00714 config->revertToDefault("StatusBar"); 00715 else 00716 config->writeEntry("StatusBar", sb->isHidden() ? "Disabled" : "Enabled"); 00717 } 00718 00719 QMenuBar* mb = internalMenuBar(); 00720 if (mb) { 00721 QString MenuBar = QString::fromLatin1("MenuBar"); 00722 if(!config->hasDefault("MenuBar") && !mb->isHidden() ) 00723 config->revertToDefault("MenuBar"); 00724 else 00725 config->writeEntry("MenuBar", mb->isHidden() ? "Disabled" : "Enabled"); 00726 } 00727 00728 int n = 1; // Toolbar counter. toolbars are counted from 1, 00729 KToolBar *toolbar = 0; 00730 QPtrListIterator<KToolBar> it( toolBarIterator() ); 00731 while ( ( toolbar = it.current() ) ) { 00732 ++it; 00733 QString group; 00734 if (!configGroup.isEmpty()) 00735 { 00736 // Give a number to the toolbar, but prefer a name if there is one, 00737 // because there's no real guarantee on the ordering of toolbars 00738 group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name()); 00739 group.prepend(" Toolbar"); 00740 group.prepend(configGroup); 00741 } 00742 toolbar->saveSettings(config, group); 00743 n++; 00744 } 00745 if (!configGroup.isEmpty()) 00746 config->setGroup(oldGroup); 00747 } 00748 00749 void KMainWindow::setStandardToolBarMenuEnabled( bool enable ) 00750 { 00751 if ( enable ) { 00752 if ( d->toolBarHandler ) 00753 return; 00754 00755 d->toolBarHandler = new KDEPrivate::ToolBarHandler( this ); 00756 00757 if ( factory() ) 00758 factory()->addClient( d->toolBarHandler ); 00759 } else { 00760 if ( !d->toolBarHandler ) 00761 return; 00762 00763 if ( factory() ) 00764 factory()->removeClient( d->toolBarHandler ); 00765 00766 delete d->toolBarHandler; 00767 d->toolBarHandler = 0; 00768 } 00769 } 00770 00771 bool KMainWindow::isStandardToolBarMenuEnabled() const 00772 { 00773 return ( d->toolBarHandler != 0 ); 00774 } 00775 00776 void KMainWindow::createStandardStatusBarAction(){ 00777 if(!d->showStatusBarAction){ 00778 d->showStatusBarAction = KStdAction::showStatusbar(this, SLOT(setSettingsDirty()), actionCollection()); 00779 KStatusBar *sb = statusBar(); // Creates statusbar if it doesn't exist already. 00780 connect(d->showStatusBarAction, SIGNAL(toggled(bool)), sb, SLOT(setShown(bool))); 00781 d->showStatusBarAction->setChecked(sb->isHidden()); 00782 } 00783 } 00784 00785 bool KMainWindow::readPropertiesInternal( KConfig *config, int number ) 00786 { 00787 if ( number == 1 ) 00788 readGlobalProperties( config ); 00789 00790 // in order they are in toolbar list 00791 QString s; 00792 s.setNum(number); 00793 s.prepend(QString::fromLatin1("WindowProperties")); 00794 00795 config->setGroup(s); 00796 00797 // restore the object name (window role) 00798 if ( config->hasKey(QString::fromLatin1("ObjectName" )) ) 00799 setName( config->readEntry(QString::fromLatin1("ObjectName")).latin1()); // latin1 is right here 00800 00801 applyMainWindowSettings(config); // Menubar, statusbar and toolbar settings. 00802 00803 s.setNum(number); 00804 config->setGroup(s); 00805 readProperties(config); 00806 return true; 00807 } 00808 00809 void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup) 00810 { 00811 return applyMainWindowSettings(config,configGroup,false); 00812 } 00813 00814 void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup,bool force) 00815 { 00816 kdDebug(200) << "KMainWindow::applyMainWindowSettings" << endl; 00817 if (!configGroup.isEmpty()) 00818 config->setGroup(configGroup); 00819 00820 restoreWindowSize(config); 00821 00822 QStatusBar* sb = internalStatusBar(); 00823 if (sb) { 00824 QString entry = config->readEntry("StatusBar", "Enabled"); 00825 if ( entry == "Disabled" ) 00826 sb->hide(); 00827 else 00828 sb->show(); 00829 if(d->showStatusBarAction) 00830 d->showStatusBarAction->setChecked(!sb->isHidden()); 00831 } 00832 00833 QMenuBar* mb = internalMenuBar(); 00834 if (mb) { 00835 QString entry = config->readEntry ("MenuBar", "Enabled"); 00836 if ( entry == "Disabled" ) 00837 mb->hide(); 00838 else 00839 mb->show(); 00840 } 00841 00842 int n = 1; // Toolbar counter. toolbars are counted from 1, 00843 KToolBar *toolbar; 00844 QPtrListIterator<KToolBar> it( toolBarIterator() ); // must use own iterator 00845 00846 for ( ; it.current(); ++it) { 00847 toolbar= it.current(); 00848 QString group; 00849 if (!configGroup.isEmpty()) 00850 { 00851 // Give a number to the toolbar, but prefer a name if there is one, 00852 // because there's no real guarantee on the ordering of toolbars 00853 group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name()); 00854 group.prepend(" Toolbar"); 00855 group.prepend(configGroup); 00856 } 00857 toolbar->applySettings(config, group, force); 00858 n++; 00859 } 00860 00861 finalizeGUI( true ); 00862 } 00863 00864 void KMainWindow::finalizeGUI( bool force ) 00865 { 00866 //kdDebug(200) << "KMainWindow::finalizeGUI force=" << force << endl; 00867 // The whole reason for this is that moveToolBar relies on the indexes 00868 // of the other toolbars, so in theory it should be called only once per 00869 // toolbar, but in increasing order of indexes. 00870 // Since we can't do that immediately, we move them, and _then_ 00871 // we call positionYourself again for each of them, but this time 00872 // the toolbariterator should give them in the proper order. 00873 // Both the XMLGUI and applySettings call this, hence "force" for the latter. 00874 QPtrListIterator<KToolBar> it( toolBarIterator() ); 00875 for ( ; it.current() ; ++ it ) 00876 it.current()->positionYourself( force ); 00877 00878 d->settingsDirty = false; 00879 } 00880 00881 void KMainWindow::saveWindowSize( KConfig * config ) const 00882 { 00883 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00884 int scnum = QApplication::desktop()->screenNumber(parentWidget()); 00885 QRect desk = QApplication::desktop()->screenGeometry(scnum); 00886 // save maximalization as desktop size + 1 in that direction 00887 KWin::WindowInfo info = KWin::windowInfo( winId(), NET::WMState ); 00888 int w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width(); 00889 int h = info.state() & NET::MaxVert ? desk.height() + 1 : height(); 00890 QRect size( desk.width(), w, desk.height(), h ); 00891 #else 00892 int w = 500; 00893 int h = 500; 00894 QRect desk( 100, 100, 200, 200 ); // fixme 00895 QRect size( 100, 100, 200, 200 ); // fixme 00896 #endif 00897 bool defaultSize = (size == d->defaultWindowSize); 00898 QString widthString = QString::fromLatin1("Width %1").arg(desk.width()); 00899 QString heightString = QString::fromLatin1("Height %1").arg(desk.height()); 00900 if (!config->hasDefault(widthString) && defaultSize) 00901 config->revertToDefault(widthString); 00902 else 00903 config->writeEntry(widthString, w ); 00904 00905 if (!config->hasDefault(heightString) && defaultSize) 00906 config->revertToDefault(heightString); 00907 else 00908 config->writeEntry(heightString, h ); 00909 } 00910 00911 void KMainWindow::restoreWindowSize( KConfig * config ) 00912 { 00913 if (d->care_about_geometry) { 00914 parseGeometry(true); 00915 } else { 00916 // restore the size 00917 int scnum = QApplication::desktop()->screenNumber(parentWidget()); 00918 QRect desk = QApplication::desktop()->screenGeometry(scnum); 00919 if ( d->defaultWindowSize.isNull() ) // only once 00920 d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); // store default values 00921 QSize size( config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ), 00922 config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) ); 00923 if (size.isEmpty()) { 00924 // try the KDE 2.0 way 00925 size = QSize( config->readNumEntry( QString::fromLatin1("Width"), 0 ), 00926 config->readNumEntry( QString::fromLatin1("Height"), 0 ) ); 00927 if (!size.isEmpty()) { 00928 // make sure the other resolutions don't get old settings 00929 config->writeEntry( QString::fromLatin1("Width"), 0 ); 00930 config->writeEntry( QString::fromLatin1("Height"), 0 ); 00931 } 00932 } 00933 if ( !size.isEmpty() ) { 00934 int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 ) 00935 | ( size.height() > desk.height() ? NET::MaxVert : 0 ); 00936 if(( state & NET::Max ) == NET::Max ) 00937 ; // no resize 00938 else if(( state & NET::MaxHoriz ) == NET::MaxHoriz ) 00939 resize( width(), size.height()); 00940 else if(( state & NET::MaxVert ) == NET::MaxVert ) 00941 resize( size.width(), height()); 00942 else 00943 resize( size ); 00944 // QWidget::showMaximized() is both insufficient and broken 00945 KWin::setState( winId(), state ); 00946 } 00947 } 00948 } 00949 00950 bool KMainWindow::initialGeometrySet() const 00951 { 00952 return d->care_about_geometry; 00953 } 00954 00955 void KMainWindow::ignoreInitialGeometry() 00956 { 00957 d->care_about_geometry = false; 00958 } 00959 00960 void KMainWindow::setSettingsDirty() 00961 { 00962 //kdDebug(200) << "KMainWindow::setSettingsDirty" << endl; 00963 d->settingsDirty = true; 00964 if ( d->autoSaveSettings ) 00965 { 00966 // Use a timer to save "immediately" user-wise, but not too immediately 00967 // (to compress calls and save only once, in case of multiple changes) 00968 if ( !d->settingsTimer ) 00969 { 00970 d->settingsTimer = new QTimer( this ); 00971 connect( d->settingsTimer, SIGNAL( timeout() ), SLOT( saveAutoSaveSettings() ) ); 00972 } 00973 d->settingsTimer->start( 500, true ); 00974 } 00975 } 00976 00977 bool KMainWindow::settingsDirty() const 00978 { 00979 return d->settingsDirty; 00980 } 00981 00982 QString KMainWindow::settingsGroup() const 00983 { 00984 return d->autoSaveGroup; 00985 } 00986 00987 void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize ) 00988 { 00989 d->autoSaveSettings = true; 00990 d->autoSaveGroup = groupName; 00991 d->autoSaveWindowSize = saveWindowSize; 00992 // Get notified when the user moves a toolbar around 00993 connect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ), 00994 this, SLOT( setSettingsDirty() ) ); 00995 00996 // Now read the previously saved settings 00997 applyMainWindowSettings( KGlobal::config(), groupName ); 00998 } 00999 01000 void KMainWindow::resetAutoSaveSettings() 01001 { 01002 d->autoSaveSettings = false; 01003 if ( d->settingsTimer ) 01004 d->settingsTimer->stop(); 01005 } 01006 01007 bool KMainWindow::autoSaveSettings() const 01008 { 01009 return d->autoSaveSettings; 01010 } 01011 01012 QString KMainWindow::autoSaveGroup() const 01013 { 01014 return d->autoSaveGroup; 01015 } 01016 01017 void KMainWindow::saveAutoSaveSettings() 01018 { 01019 Q_ASSERT( d->autoSaveSettings ); 01020 //kdDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings" << endl; 01021 saveMainWindowSettings( KGlobal::config(), d->autoSaveGroup ); 01022 KGlobal::config()->sync(); 01023 d->settingsDirty = false; 01024 if ( d->settingsTimer ) 01025 d->settingsTimer->stop(); 01026 } 01027 01028 void KMainWindow::resizeEvent( QResizeEvent * ) 01029 { 01030 if ( d->autoSaveWindowSize ) 01031 setSettingsDirty(); 01032 } 01033 01034 bool KMainWindow::hasMenuBar() 01035 { 01036 return (internalMenuBar()); 01037 } 01038 01039 KMenuBar *KMainWindow::menuBar() 01040 { 01041 KMenuBar * mb = internalMenuBar(); 01042 if ( !mb ) { 01043 mb = new KMenuBar( this ); 01044 // trigger a re-layout and trigger a call to the private 01045 // setMenuBar method. 01046 QMainWindow::menuBar(); 01047 } 01048 return mb; 01049 } 01050 01051 KStatusBar *KMainWindow::statusBar() 01052 { 01053 KStatusBar * sb = internalStatusBar(); 01054 if ( !sb ) { 01055 sb = new KStatusBar( this ); 01056 // trigger a re-layout and trigger a call to the private 01057 // setStatusBar method. 01058 QMainWindow::statusBar(); 01059 } 01060 return sb; 01061 } 01062 01063 void KMainWindow::shuttingDown() 01064 { 01065 // Needed for Qt <= 3.0.3 at least to prevent reentrancy 01066 // when queryExit() shows a dialog. Check before removing! 01067 static bool reentrancy_protection = false; 01068 if (!reentrancy_protection) 01069 { 01070 reentrancy_protection = true; 01071 // call the virtual queryExit 01072 queryExit(); 01073 reentrancy_protection = false; 01074 } 01075 01076 } 01077 01078 KMenuBar *KMainWindow::internalMenuBar() 01079 { 01080 QObjectList *l = queryList( "KMenuBar", 0, false, false ); 01081 if ( !l || !l->first() ) { 01082 delete l; 01083 return 0; 01084 } 01085 01086 KMenuBar *m = (KMenuBar*)l->first(); 01087 delete l; 01088 return m; 01089 } 01090 01091 KStatusBar *KMainWindow::internalStatusBar() 01092 { 01093 QObjectList *l = queryList( "KStatusBar", 0, false, false ); 01094 if ( !l || !l->first() ) { 01095 delete l; 01096 return 0; 01097 } 01098 01099 KStatusBar *s = (KStatusBar*)l->first(); 01100 delete l; 01101 return s; 01102 } 01103 01104 void KMainWindow::childEvent( QChildEvent* e) 01105 { 01106 QMainWindow::childEvent( e ); 01107 } 01108 01109 KToolBar *KMainWindow::toolBar( const char * name ) 01110 { 01111 if (!name) 01112 name = "mainToolBar"; 01113 KToolBar *tb = (KToolBar*)child( name, "KToolBar" ); 01114 if ( tb ) 01115 return tb; 01116 bool honor_mode = (name == "mainToolBar"); 01117 01118 if ( builderClient() ) 01119 return new KToolBar(this, name, honor_mode); // XMLGUI constructor 01120 else 01121 return new KToolBar(this, DockTop, false, name, honor_mode ); // non-XMLGUI 01122 } 01123 01124 QPtrListIterator<KToolBar> KMainWindow::toolBarIterator() 01125 { 01126 toolbarList.clear(); 01127 QPtrList<QToolBar> lst; 01128 for ( int i = (int)QMainWindow::DockUnmanaged; i <= (int)DockMinimized; ++i ) { 01129 lst = toolBars( (ToolBarDock)i ); 01130 for ( QToolBar *tb = lst.first(); tb; tb = lst.next() ) { 01131 if ( !tb->inherits( "KToolBar" ) ) 01132 continue; 01133 toolbarList.append( (KToolBar*)tb ); 01134 } 01135 } 01136 return QPtrListIterator<KToolBar>( toolbarList ); 01137 } 01138 01139 KAccel * KMainWindow::accel() 01140 { 01141 if ( !d->kaccel ) 01142 d->kaccel = new KAccel( this, "kmw-kaccel" ); 01143 return d->kaccel; 01144 } 01145 01146 void KMainWindow::paintEvent( QPaintEvent * pe ) 01147 { 01148 QMainWindow::paintEvent(pe); //Upcall to handle SH_MainWindow_SpaceBelowMenuBar rendering 01149 } 01150 01151 QSize KMainWindow::sizeForCentralWidgetSize(QSize size) 01152 { 01153 KToolBar *tb = (KToolBar*)child( "mainToolBar", "KToolBar" ); 01154 if (tb && !tb->isHidden()) { 01155 switch( tb->barPos() ) 01156 { 01157 case KToolBar::Top: 01158 case KToolBar::Bottom: 01159 size += QSize(0, tb->sizeHint().height()); 01160 break; 01161 01162 case KToolBar::Left: 01163 case KToolBar::Right: 01164 size += QSize(toolBar()->sizeHint().width(), 0); 01165 break; 01166 01167 case KToolBar::Flat: 01168 size += QSize(0, 3+kapp->style().pixelMetric( QStyle::PM_DockWindowHandleExtent )); 01169 break; 01170 01171 default: 01172 break; 01173 } 01174 } 01175 KMenuBar *mb = internalMenuBar(); 01176 if (mb && !mb->isHidden()) { 01177 size += QSize(0,mb->heightForWidth(size.width())); 01178 if (style().styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, this)) 01179 size += QSize( 0, dockWindowsMovable() ? 1 : 2); 01180 } 01181 QStatusBar *sb = internalStatusBar(); 01182 if( sb && !sb->isHidden() ) 01183 size += QSize(0, sb->sizeHint().height()); 01184 01185 return size; 01186 } 01187 01188 // why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI; 01189 // DF: because they compile KDE much faster :) 01190 void KMainWindow::finalizeGUI( KXMLGUIClient *client ) 01191 { KXMLGUIBuilder::finalizeGUI( client ); } 01192 01193 void KMainWindow::virtual_hook( int id, void* data ) 01194 { KXMLGUIBuilder::virtual_hook( id, data ); 01195 KXMLGUIClient::virtual_hook( id, data ); } 01196 01197 01198 01199 #include "kmainwindow.moc" 01200
KDE Logo
This file is part of the documentation for kdeui Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Sep 29 09:43:28 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003