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 00271 void KMainWindow::setupToolbarMenuActions() 00272 { 00273 if ( d->toolBarHandler ) 00274 d->toolBarHandler->setupActions(); 00275 } 00276 00277 void KMainWindow::parseGeometry(bool parsewidth) 00278 { 00279 assert ( !kapp->geometryArgument().isNull() ); 00280 assert ( d->care_about_geometry ); 00281 00282 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00283 //#ifndef Q_WS_QWS 00284 // FIXME: (E) Implement something similar for Qt Embedded (or decide we don't need it) 00285 int x, y; 00286 int w, h; 00287 int m = XParseGeometry( kapp->geometryArgument().latin1(), &x, &y, (unsigned int*)&w, (unsigned int*)&h); 00288 if (parsewidth) { 00289 QSize minSize = minimumSize(); 00290 QSize maxSize = maximumSize(); 00291 if ( (m & WidthValue) == 0 ) 00292 w = width(); 00293 if ( (m & HeightValue) == 0 ) 00294 h = height(); 00295 w = QMIN(w,maxSize.width()); 00296 h = QMIN(h,maxSize.height()); 00297 w = QMAX(w,minSize.width()); 00298 h = QMAX(h,minSize.height()); 00299 resize(w, h); 00300 } else { 00301 if ( parsewidth && (m & XValue) == 0 ) 00302 x = geometry().x(); 00303 if ( parsewidth && (m & YValue) == 0 ) 00304 y = geometry().y(); 00305 if ( (m & XNegative) ) 00306 x = KApplication::desktop()->width() + x - w; 00307 if ( (m & YNegative) ) 00308 y = KApplication::desktop()->height() + y - h; 00309 move(x, y); 00310 } 00311 #endif 00312 } 00313 00314 KMainWindow::~KMainWindow() 00315 { 00316 delete d->settingsTimer; 00317 QMenuBar* mb = internalMenuBar(); 00318 delete mb; 00319 delete d->m_interface; 00320 delete d; 00321 memberList->remove( this ); 00322 } 00323 00324 KPopupMenu* KMainWindow::helpMenu( const QString &aboutAppText, bool showWhatsThis ) 00325 { 00326 if( mHelpMenu == 0 ) { 00327 if ( aboutAppText.isEmpty() ) 00328 mHelpMenu = new KHelpMenu( this, instance()->aboutData(), showWhatsThis); 00329 else 00330 mHelpMenu = new KHelpMenu( this, aboutAppText, showWhatsThis ); 00331 00332 if ( mHelpMenu == 0 ) 00333 return 0; 00334 connect( mHelpMenu, SIGNAL( showAboutApplication() ), 00335 this, SLOT( showAboutApplication() ) ); 00336 } 00337 00338 return mHelpMenu->menu(); 00339 } 00340 00341 KPopupMenu* KMainWindow::customHelpMenu( bool showWhatsThis ) 00342 { 00343 if( mHelpMenu == 0 ) { 00344 mHelpMenu = new KHelpMenu( this, QString::null, showWhatsThis ); 00345 connect( mHelpMenu, SIGNAL( showAboutApplication() ), 00346 this, SLOT( showAboutApplication() ) ); 00347 } 00348 00349 return mHelpMenu->menu(); 00350 } 00351 00352 bool KMainWindow::canBeRestored( int number ) 00353 { 00354 if ( !kapp->isRestored() ) 00355 return false; 00356 KConfig *config = kapp->sessionConfig(); 00357 if ( !config ) 00358 return false; 00359 config->setGroup( QString::fromLatin1("Number") ); 00360 int n = config->readNumEntry( QString::fromLatin1("NumberOfWindows") , 1 ); 00361 return number >= 1 && number <= n; 00362 } 00363 00364 const QString KMainWindow::classNameOfToplevel( int number ) 00365 { 00366 if ( !kapp->isRestored() ) 00367 return QString::null; 00368 KConfig *config = kapp->sessionConfig(); 00369 if ( !config ) 00370 return QString::null; 00371 QString s; 00372 s.setNum( number ); 00373 s.prepend( QString::fromLatin1("WindowProperties") ); 00374 config->setGroup( s ); 00375 if ( !config->hasKey( QString::fromLatin1("ClassName") ) ) 00376 return QString::null; 00377 else 00378 return config->readEntry( QString::fromLatin1("ClassName") ); 00379 } 00380 00381 void KMainWindow::show() 00382 { 00383 QMainWindow::show(); 00384 00385 for ( QPtrListIterator<QDockWindow> it( d->hiddenDockWindows ); it.current(); ++it ) 00386 it.current()->show(); 00387 00388 d->hiddenDockWindows.clear(); 00389 } 00390 00391 void KMainWindow::hide() 00392 { 00393 if ( isVisible() ) { 00394 00395 d->hiddenDockWindows.clear(); 00396 00397 QObjectList *list = queryList( "QDockWindow" ); 00398 for( QObjectListIt it( *list ); it.current(); ++it ) { 00399 QDockWindow *dw = (QDockWindow*)it.current(); 00400 if ( dw->isTopLevel() && dw->isVisible() ) { 00401 d->hiddenDockWindows.append( dw ); 00402 dw->hide(); 00403 } 00404 } 00405 delete list; 00406 } 00407 00408 QWidget::hide(); 00409 } 00410 00411 bool KMainWindow::restore( int number, bool show ) 00412 { 00413 if ( !canBeRestored( number ) ) 00414 return false; 00415 KConfig *config = kapp->sessionConfig(); 00416 if ( readPropertiesInternal( config, number ) ){ 00417 if ( show ) 00418 KMainWindow::show(); 00419 return false; 00420 } 00421 return false; 00422 } 00423 00424 KXMLGUIFactory *KMainWindow::guiFactory() 00425 { 00426 if ( !factory_ ) 00427 factory_ = new KXMLGUIFactory( this, this, "guifactory" ); 00428 return factory_; 00429 } 00430 00431 int KMainWindow::configureToolbars() 00432 { 00433 saveMainWindowSettings(KGlobal::config()); 00434 KEditToolbar dlg(actionCollection(), xmlFile(), true, this); 00435 connect(&dlg, SIGNAL(newToolbarConfig()), SLOT(saveNewToolbarConfig())); 00436 return dlg.exec(); 00437 } 00438 00439 void KMainWindow::saveNewToolbarConfig() 00440 { 00441 createGUI(xmlFile()); 00442 applyMainWindowSettings( KGlobal::config() ); 00443 } 00444 00445 void KMainWindow::setupGUI( int options, const QString & xmlfile ) { 00446 if( options & Keys ){ 00447 KStdAction::keyBindings(guiFactory(), 00448 SLOT(configureShortcuts()), actionCollection()); 00449 } 00450 00451 if( (options & StatusBar) && internalStatusBar() ){ 00452 createStandardStatusBarAction(); 00453 } 00454 00455 if( options & ToolBar ){ 00456 setStandardToolBarMenuEnabled( true ); 00457 KStdAction::configureToolbars(this, 00458 SLOT(configureToolbars() ), actionCollection()); 00459 } 00460 00461 if( options & Create ){ 00462 createGUI(xmlfile); 00463 } 00464 00465 if( options & Save ){ 00466 // setupGUI() is typically called in the constructor before show(), 00467 // so the default window size will be incorrect unless the application 00468 // hard coded the size which they should try not to do (i.e. use 00469 // size hints). 00470 if(!isShown()) 00471 adjustSize(); 00472 setAutoSaveSettings(); 00473 } 00474 00475 } 00476 00477 void KMainWindow::createGUI( const QString &xmlfile, bool _conserveMemory ) 00478 { 00479 // disabling the updates prevents unnecessary redraws 00480 setUpdatesEnabled( false ); 00481 00482 // just in case we are rebuilding, let's remove our old client 00483 guiFactory()->removeClient( this ); 00484 00485 // make sure to have an empty GUI 00486 QMenuBar* mb = internalMenuBar(); 00487 if ( mb ) 00488 mb->clear(); 00489 00490 (void)toolBarIterator(); // make sure toolbarList is most-up-to-date 00491 toolbarList.setAutoDelete( true ); 00492 toolbarList.clear(); 00493 toolbarList.setAutoDelete( false ); 00494 00495 // don't build a help menu unless the user ask for it 00496 if (d->showHelpMenu) { 00497 // we always want a help menu 00498 if (helpMenu2 == 0) 00499 helpMenu2 = new KHelpMenu(this, instance()->aboutData(), true, 00500 actionCollection()); 00501 } 00502 00503 // we always want to load in our global standards file 00504 setXMLFile( locate( "config", "ui/ui_standards.rc", instance() ) ); 00505 00506 // now, merge in our local xml file. if this is null, then that 00507 // means that we will be only using the global file 00508 if ( !xmlfile.isNull() ) { 00509 setXMLFile( xmlfile, true ); 00510 } else { 00511 QString auto_file(instance()->instanceName() + "ui.rc"); 00512 setXMLFile( auto_file, true ); 00513 } 00514 00515 // make sure we don't have any state saved already 00516 setXMLGUIBuildDocument( QDomDocument() ); 00517 00518 // do the actual GUI building 00519 guiFactory()->addClient( this ); 00520 00521 // try and get back *some* of our memory 00522 if ( _conserveMemory ) 00523 { 00524 // before freeing the memory allocated by the DOM document we also 00525 // free all memory allocated internally in the KXMLGUIFactory for 00526 // the menubar and the toolbars . This however implies that we 00527 // have to take care of deleting those widgets ourselves. For 00528 // destruction this is no problem, but when rebuilding we have 00529 // to take care of that (and we want to rebuild the GUI when 00530 // using stuff like the toolbar editor ). 00531 // In addition we have to take care of not removing containers 00532 // like popupmenus, defined in the XML document. 00533 // this code should probably go into a separate method in KMainWindow. 00534 // there's just one problem: I'm bad in finding names ;-) , so 00535 // I skipped this ;-) 00536 00537 QDomDocument doc = domDocument(); 00538 00539 for( QDomNode n = doc.documentElement().firstChild(); 00540 !n.isNull(); n = n.nextSibling()) 00541 { 00542 QDomElement e = n.toElement(); 00543 00544 if ( e.tagName().lower() == "toolbar" ) 00545 factory_->resetContainer( e.attribute( "name" ) ); 00546 else if ( e.tagName().lower() == "menubar" ) 00547 factory_->resetContainer( e.tagName(), true ); 00548 } 00549 00550 conserveMemory(); 00551 } 00552 00553 setUpdatesEnabled( true ); 00554 updateGeometry(); 00555 } 00556 00557 void KMainWindow::setHelpMenuEnabled(bool showHelpMenu) 00558 { 00559 d->showHelpMenu = showHelpMenu; 00560 } 00561 00562 bool KMainWindow::isHelpMenuEnabled() 00563 { 00564 return d->showHelpMenu; 00565 } 00566 00567 void KMainWindow::setCaption( const QString &caption ) 00568 { 00569 setPlainCaption( kapp->makeStdCaption(caption) ); 00570 } 00571 00572 void KMainWindow::setCaption( const QString &caption, bool modified ) 00573 { 00574 setPlainCaption( kapp->makeStdCaption(caption, true, modified) ); 00575 } 00576 00577 void KMainWindow::setPlainCaption( const QString &caption ) 00578 { 00579 QMainWindow::setCaption( caption ); 00580 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00581 //#ifndef Q_WS_QWS 00582 NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), 0 ); 00583 info.setName( caption.utf8().data() ); 00584 #endif 00585 } 00586 00587 void KMainWindow::appHelpActivated( void ) 00588 { 00589 if( mHelpMenu == 0 ) { 00590 mHelpMenu = new KHelpMenu( this ); 00591 if ( mHelpMenu == 0 ) 00592 return; 00593 } 00594 mHelpMenu->appHelpActivated(); 00595 } 00596 00597 void KMainWindow::slotStateChanged(const QString &newstate) 00598 { 00599 stateChanged(newstate, KXMLGUIClient::StateNoReverse); 00600 } 00601 00602 /* 00603 * Get rid of this for KDE 4.0 00604 */ 00605 void KMainWindow::slotStateChanged(const QString &newstate, 00606 KXMLGUIClient::ReverseStateChange reverse) 00607 { 00608 stateChanged(newstate, reverse); 00609 } 00610 00611 /* 00612 * Enable this for KDE 4.0 00613 */ 00614 // void KMainWindow::slotStateChanged(const QString &newstate, 00615 // bool reverse) 00616 // { 00617 // stateChanged(newstate, 00618 // reverse ? KXMLGUIClient::StateReverse : KXMLGUIClient::StateNoReverse); 00619 // } 00620 00621 void KMainWindow::closeEvent ( QCloseEvent *e ) 00622 { 00623 // Save settings if auto-save is enabled, and settings have changed 00624 if (d->settingsDirty && d->autoSaveSettings) 00625 saveAutoSaveSettings(); 00626 00627 if (queryClose()) { 00628 e->accept(); 00629 00630 int not_withdrawn = 0; 00631 QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); 00632 for (it.toFirst(); it.current(); ++it){ 00633 if ( !it.current()->isHidden() && it.current()->isTopLevel() && it.current() != this ) 00634 not_withdrawn++; 00635 } 00636 00637 if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted? 00638 if ( queryExit() && !kapp->sessionSaving() && !d->shuttingDown ) { // Yes, Quit app? 00639 // don't call queryExit() twice 00640 disconnect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown())); 00641 d->shuttingDown = true; 00642 kapp->deref(); // ...and quit application. 00643 } else { 00644 // cancel closing, it's stupid to end up with no windows at all.... 00645 e->ignore(); 00646 } 00647 } 00648 } 00649 } 00650 00651 bool KMainWindow::queryExit() 00652 { 00653 return true; 00654 } 00655 00656 bool KMainWindow::queryClose() 00657 { 00658 return true; 00659 } 00660 00661 void KMainWindow::saveGlobalProperties( KConfig* ) 00662 { 00663 } 00664 00665 void KMainWindow::readGlobalProperties( KConfig* ) 00666 { 00667 } 00668 00669 #if defined(KDE_COMPAT) 00670 void KMainWindow::updateRects() 00671 { 00672 } 00673 #endif 00674 00675 void KMainWindow::showAboutApplication() 00676 { 00677 } 00678 00679 void KMainWindow::savePropertiesInternal( KConfig *config, int number ) 00680 { 00681 bool oldASWS = d->autoSaveWindowSize; 00682 d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size 00683 00684 QString s; 00685 s.setNum(number); 00686 s.prepend(QString::fromLatin1("WindowProperties")); 00687 config->setGroup(s); 00688 00689 // store objectName, className, Width and Height for later restoring 00690 // (Only useful for session management) 00691 config->writeEntry(QString::fromLatin1("ObjectName"), name()); 00692 config->writeEntry(QString::fromLatin1("ClassName"), className()); 00693 00694 saveMainWindowSettings(config); // Menubar, statusbar and Toolbar settings. 00695 00696 s.setNum(number); 00697 config->setGroup(s); 00698 saveProperties(config); 00699 00700 d->autoSaveWindowSize = oldASWS; 00701 } 00702 00703 void KMainWindow::saveMainWindowSettings(KConfig *config, const QString &configGroup) 00704 { 00705 kdDebug(200) << "KMainWindow::saveMainWindowSettings " << configGroup << endl; 00706 QString oldGroup; 00707 00708 if (!configGroup.isEmpty()) 00709 { 00710 oldGroup = config->group(); 00711 config->setGroup(configGroup); 00712 } 00713 00714 // Called by session management - or if we want to save the window size anyway 00715 if ( d->autoSaveWindowSize ) 00716 saveWindowSize( config ); 00717 00718 QStatusBar* sb = internalStatusBar(); 00719 if (sb) { 00720 if(!config->hasDefault("StatusBar") && !sb->isHidden() ) 00721 config->revertToDefault("StatusBar"); 00722 else 00723 config->writeEntry("StatusBar", sb->isHidden() ? "Disabled" : "Enabled"); 00724 } 00725 00726 QMenuBar* mb = internalMenuBar(); 00727 if (mb) { 00728 QString MenuBar = QString::fromLatin1("MenuBar"); 00729 if(!config->hasDefault("MenuBar") && !mb->isHidden() ) 00730 config->revertToDefault("MenuBar"); 00731 else 00732 config->writeEntry("MenuBar", mb->isHidden() ? "Disabled" : "Enabled"); 00733 } 00734 00735 int n = 1; // Toolbar counter. toolbars are counted from 1, 00736 KToolBar *toolbar = 0; 00737 QPtrListIterator<KToolBar> it( toolBarIterator() ); 00738 while ( ( toolbar = it.current() ) ) { 00739 ++it; 00740 QString group; 00741 if (!configGroup.isEmpty()) 00742 { 00743 // Give a number to the toolbar, but prefer a name if there is one, 00744 // because there's no real guarantee on the ordering of toolbars 00745 group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name()); 00746 group.prepend(" Toolbar"); 00747 group.prepend(configGroup); 00748 } 00749 toolbar->saveSettings(config, group); 00750 n++; 00751 } 00752 if (!configGroup.isEmpty()) 00753 config->setGroup(oldGroup); 00754 } 00755 00756 void KMainWindow::setStandardToolBarMenuEnabled( bool enable ) 00757 { 00758 if ( enable ) { 00759 if ( d->toolBarHandler ) 00760 return; 00761 00762 d->toolBarHandler = new KDEPrivate::ToolBarHandler( this ); 00763 00764 if ( factory() ) 00765 factory()->addClient( d->toolBarHandler ); 00766 } else { 00767 if ( !d->toolBarHandler ) 00768 return; 00769 00770 if ( factory() ) 00771 factory()->removeClient( d->toolBarHandler ); 00772 00773 delete d->toolBarHandler; 00774 d->toolBarHandler = 0; 00775 } 00776 } 00777 00778 bool KMainWindow::isStandardToolBarMenuEnabled() const 00779 { 00780 return ( d->toolBarHandler != 0 ); 00781 } 00782 00783 void KMainWindow::createStandardStatusBarAction(){ 00784 if(!d->showStatusBarAction){ 00785 d->showStatusBarAction = KStdAction::showStatusbar(this, SLOT(setSettingsDirty()), actionCollection()); 00786 KStatusBar *sb = statusBar(); // Creates statusbar if it doesn't exist already. 00787 connect(d->showStatusBarAction, SIGNAL(toggled(bool)), sb, SLOT(setShown(bool))); 00788 d->showStatusBarAction->setChecked(sb->isHidden()); 00789 } 00790 } 00791 00792 bool KMainWindow::readPropertiesInternal( KConfig *config, int number ) 00793 { 00794 if ( number == 1 ) 00795 readGlobalProperties( config ); 00796 00797 // in order they are in toolbar list 00798 QString s; 00799 s.setNum(number); 00800 s.prepend(QString::fromLatin1("WindowProperties")); 00801 00802 config->setGroup(s); 00803 00804 // restore the object name (window role) 00805 if ( config->hasKey(QString::fromLatin1("ObjectName" )) ) 00806 setName( config->readEntry(QString::fromLatin1("ObjectName")).latin1()); // latin1 is right here 00807 00808 applyMainWindowSettings(config); // Menubar, statusbar and toolbar settings. 00809 00810 s.setNum(number); 00811 config->setGroup(s); 00812 readProperties(config); 00813 return true; 00814 } 00815 00816 void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup) 00817 { 00818 return applyMainWindowSettings(config,configGroup,false); 00819 } 00820 00821 void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup,bool force) 00822 { 00823 kdDebug(200) << "KMainWindow::applyMainWindowSettings" << endl; 00824 if (!configGroup.isEmpty()) 00825 config->setGroup(configGroup); 00826 00827 restoreWindowSize(config); 00828 00829 QStatusBar* sb = internalStatusBar(); 00830 if (sb) { 00831 QString entry = config->readEntry("StatusBar", "Enabled"); 00832 if ( entry == "Disabled" ) 00833 sb->hide(); 00834 else 00835 sb->show(); 00836 if(d->showStatusBarAction) 00837 d->showStatusBarAction->setChecked(!sb->isHidden()); 00838 } 00839 00840 QMenuBar* mb = internalMenuBar(); 00841 if (mb) { 00842 QString entry = config->readEntry ("MenuBar", "Enabled"); 00843 if ( entry == "Disabled" ) 00844 mb->hide(); 00845 else 00846 mb->show(); 00847 } 00848 00849 int n = 1; // Toolbar counter. toolbars are counted from 1, 00850 KToolBar *toolbar; 00851 QPtrListIterator<KToolBar> it( toolBarIterator() ); // must use own iterator 00852 00853 for ( ; it.current(); ++it) { 00854 toolbar= it.current(); 00855 QString group; 00856 if (!configGroup.isEmpty()) 00857 { 00858 // Give a number to the toolbar, but prefer a name if there is one, 00859 // because there's no real guarantee on the ordering of toolbars 00860 group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name()); 00861 group.prepend(" Toolbar"); 00862 group.prepend(configGroup); 00863 } 00864 toolbar->applySettings(config, group, force); 00865 n++; 00866 } 00867 00868 finalizeGUI( true ); 00869 } 00870 00871 void KMainWindow::finalizeGUI( bool force ) 00872 { 00873 //kdDebug(200) << "KMainWindow::finalizeGUI force=" << force << endl; 00874 // The whole reason for this is that moveToolBar relies on the indexes 00875 // of the other toolbars, so in theory it should be called only once per 00876 // toolbar, but in increasing order of indexes. 00877 // Since we can't do that immediately, we move them, and _then_ 00878 // we call positionYourself again for each of them, but this time 00879 // the toolbariterator should give them in the proper order. 00880 // Both the XMLGUI and applySettings call this, hence "force" for the latter. 00881 QPtrListIterator<KToolBar> it( toolBarIterator() ); 00882 for ( ; it.current() ; ++ it ) 00883 it.current()->positionYourself( force ); 00884 00885 d->settingsDirty = false; 00886 } 00887 00888 void KMainWindow::saveWindowSize( KConfig * config ) const 00889 { 00890 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00891 int scnum = QApplication::desktop()->screenNumber(parentWidget()); 00892 QRect desk = QApplication::desktop()->screenGeometry(scnum); 00893 // save maximalization as desktop size + 1 in that direction 00894 KWin::WindowInfo info = KWin::windowInfo( winId(), NET::WMState ); 00895 int w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width(); 00896 int h = info.state() & NET::MaxVert ? desk.height() + 1 : height(); 00897 QRect size( desk.width(), w, desk.height(), h ); 00898 #else 00899 int w = 500; 00900 int h = 500; 00901 QRect desk( 100, 100, 200, 200 ); // fixme 00902 QRect size( 100, 100, 200, 200 ); // fixme 00903 #endif 00904 bool defaultSize = (size == d->defaultWindowSize); 00905 QString widthString = QString::fromLatin1("Width %1").arg(desk.width()); 00906 QString heightString = QString::fromLatin1("Height %1").arg(desk.height()); 00907 if (!config->hasDefault(widthString) && defaultSize) 00908 config->revertToDefault(widthString); 00909 else 00910 config->writeEntry(widthString, w ); 00911 00912 if (!config->hasDefault(heightString) && defaultSize) 00913 config->revertToDefault(heightString); 00914 else 00915 config->writeEntry(heightString, h ); 00916 } 00917 00918 void KMainWindow::restoreWindowSize( KConfig * config ) 00919 { 00920 if (d->care_about_geometry) { 00921 parseGeometry(true); 00922 } else { 00923 // restore the size 00924 int scnum = QApplication::desktop()->screenNumber(parentWidget()); 00925 QRect desk = QApplication::desktop()->screenGeometry(scnum); 00926 if ( d->defaultWindowSize.isNull() ) // only once 00927 d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); // store default values 00928 QSize size( config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ), 00929 config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) ); 00930 if (size.isEmpty()) { 00931 // try the KDE 2.0 way 00932 size = QSize( config->readNumEntry( QString::fromLatin1("Width"), 0 ), 00933 config->readNumEntry( QString::fromLatin1("Height"), 0 ) ); 00934 if (!size.isEmpty()) { 00935 // make sure the other resolutions don't get old settings 00936 config->writeEntry( QString::fromLatin1("Width"), 0 ); 00937 config->writeEntry( QString::fromLatin1("Height"), 0 ); 00938 } 00939 } 00940 if ( !size.isEmpty() ) { 00941 int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 ) 00942 | ( size.height() > desk.height() ? NET::MaxVert : 0 ); 00943 if(( state & NET::Max ) == NET::Max ) 00944 ; // no resize 00945 else if(( state & NET::MaxHoriz ) == NET::MaxHoriz ) 00946 resize( width(), size.height()); 00947 else if(( state & NET::MaxVert ) == NET::MaxVert ) 00948 resize( size.width(), height()); 00949 else 00950 resize( size ); 00951 // QWidget::showMaximized() is both insufficient and broken 00952 KWin::setState( winId(), state ); 00953 } 00954 } 00955 } 00956 00957 bool KMainWindow::initialGeometrySet() const 00958 { 00959 return d->care_about_geometry; 00960 } 00961 00962 void KMainWindow::ignoreInitialGeometry() 00963 { 00964 d->care_about_geometry = false; 00965 } 00966 00967 void KMainWindow::setSettingsDirty() 00968 { 00969 //kdDebug(200) << "KMainWindow::setSettingsDirty" << endl; 00970 d->settingsDirty = true; 00971 if ( d->autoSaveSettings ) 00972 { 00973 // Use a timer to save "immediately" user-wise, but not too immediately 00974 // (to compress calls and save only once, in case of multiple changes) 00975 if ( !d->settingsTimer ) 00976 { 00977 d->settingsTimer = new QTimer( this ); 00978 connect( d->settingsTimer, SIGNAL( timeout() ), SLOT( saveAutoSaveSettings() ) ); 00979 } 00980 d->settingsTimer->start( 500, true ); 00981 } 00982 } 00983 00984 bool KMainWindow::settingsDirty() const 00985 { 00986 return d->settingsDirty; 00987 } 00988 00989 QString KMainWindow::settingsGroup() const 00990 { 00991 return d->autoSaveGroup; 00992 } 00993 00994 void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize ) 00995 { 00996 d->autoSaveSettings = true; 00997 d->autoSaveGroup = groupName; 00998 d->autoSaveWindowSize = saveWindowSize; 00999 // Get notified when the user moves a toolbar around 01000 connect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ), 01001 this, SLOT( setSettingsDirty() ) ); 01002 01003 // Now read the previously saved settings 01004 applyMainWindowSettings( KGlobal::config(), groupName ); 01005 } 01006 01007 void KMainWindow::resetAutoSaveSettings() 01008 { 01009 d->autoSaveSettings = false; 01010 if ( d->settingsTimer ) 01011 d->settingsTimer->stop(); 01012 } 01013 01014 bool KMainWindow::autoSaveSettings() const 01015 { 01016 return d->autoSaveSettings; 01017 } 01018 01019 QString KMainWindow::autoSaveGroup() const 01020 { 01021 return d->autoSaveGroup; 01022 } 01023 01024 void KMainWindow::saveAutoSaveSettings() 01025 { 01026 Q_ASSERT( d->autoSaveSettings ); 01027 //kdDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings" << endl; 01028 saveMainWindowSettings( KGlobal::config(), d->autoSaveGroup ); 01029 KGlobal::config()->sync(); 01030 d->settingsDirty = false; 01031 if ( d->settingsTimer ) 01032 d->settingsTimer->stop(); 01033 } 01034 01035 void KMainWindow::resizeEvent( QResizeEvent * ) 01036 { 01037 if ( d->autoSaveWindowSize ) 01038 setSettingsDirty(); 01039 } 01040 01041 bool KMainWindow::hasMenuBar() 01042 { 01043 return (internalMenuBar()); 01044 } 01045 01046 KMenuBar *KMainWindow::menuBar() 01047 { 01048 KMenuBar * mb = internalMenuBar(); 01049 if ( !mb ) { 01050 mb = new KMenuBar( this ); 01051 // trigger a re-layout and trigger a call to the private 01052 // setMenuBar method. 01053 QMainWindow::menuBar(); 01054 } 01055 return mb; 01056 } 01057 01058 KStatusBar *KMainWindow::statusBar() 01059 { 01060 KStatusBar * sb = internalStatusBar(); 01061 if ( !sb ) { 01062 sb = new KStatusBar( this ); 01063 // trigger a re-layout and trigger a call to the private 01064 // setStatusBar method. 01065 QMainWindow::statusBar(); 01066 } 01067 return sb; 01068 } 01069 01070 void KMainWindow::shuttingDown() 01071 { 01072 // Needed for Qt <= 3.0.3 at least to prevent reentrancy 01073 // when queryExit() shows a dialog. Check before removing! 01074 static bool reentrancy_protection = false; 01075 if (!reentrancy_protection) 01076 { 01077 reentrancy_protection = true; 01078 // call the virtual queryExit 01079 queryExit(); 01080 reentrancy_protection = false; 01081 } 01082 01083 } 01084 01085 KMenuBar *KMainWindow::internalMenuBar() 01086 { 01087 QObjectList *l = queryList( "KMenuBar", 0, false, false ); 01088 if ( !l || !l->first() ) { 01089 delete l; 01090 return 0; 01091 } 01092 01093 KMenuBar *m = (KMenuBar*)l->first(); 01094 delete l; 01095 return m; 01096 } 01097 01098 KStatusBar *KMainWindow::internalStatusBar() 01099 { 01100 QObjectList *l = queryList( "KStatusBar", 0, false, false ); 01101 if ( !l || !l->first() ) { 01102 delete l; 01103 return 0; 01104 } 01105 01106 KStatusBar *s = (KStatusBar*)l->first(); 01107 delete l; 01108 return s; 01109 } 01110 01111 void KMainWindow::childEvent( QChildEvent* e) 01112 { 01113 QMainWindow::childEvent( e ); 01114 } 01115 01116 KToolBar *KMainWindow::toolBar( const char * name ) 01117 { 01118 if (!name) 01119 name = "mainToolBar"; 01120 KToolBar *tb = (KToolBar*)child( name, "KToolBar" ); 01121 if ( tb ) 01122 return tb; 01123 bool honor_mode = (name == "mainToolBar"); 01124 01125 if ( builderClient() ) 01126 return new KToolBar(this, name, honor_mode); // XMLGUI constructor 01127 else 01128 return new KToolBar(this, DockTop, false, name, honor_mode ); // non-XMLGUI 01129 } 01130 01131 QPtrListIterator<KToolBar> KMainWindow::toolBarIterator() 01132 { 01133 toolbarList.clear(); 01134 QPtrList<QToolBar> lst; 01135 for ( int i = (int)QMainWindow::DockUnmanaged; i <= (int)DockMinimized; ++i ) { 01136 lst = toolBars( (ToolBarDock)i ); 01137 for ( QToolBar *tb = lst.first(); tb; tb = lst.next() ) { 01138 if ( !tb->inherits( "KToolBar" ) ) 01139 continue; 01140 toolbarList.append( (KToolBar*)tb ); 01141 } 01142 } 01143 return QPtrListIterator<KToolBar>( toolbarList ); 01144 } 01145 01146 KAccel * KMainWindow::accel() 01147 { 01148 if ( !d->kaccel ) 01149 d->kaccel = new KAccel( this, "kmw-kaccel" ); 01150 return d->kaccel; 01151 } 01152 01153 void KMainWindow::paintEvent( QPaintEvent * pe ) 01154 { 01155 QMainWindow::paintEvent(pe); //Upcall to handle SH_MainWindow_SpaceBelowMenuBar rendering 01156 } 01157 01158 QSize KMainWindow::sizeForCentralWidgetSize(QSize size) 01159 { 01160 KToolBar *tb = (KToolBar*)child( "mainToolBar", "KToolBar" ); 01161 if (tb && !tb->isHidden()) { 01162 switch( tb->barPos() ) 01163 { 01164 case KToolBar::Top: 01165 case KToolBar::Bottom: 01166 size += QSize(0, tb->sizeHint().height()); 01167 break; 01168 01169 case KToolBar::Left: 01170 case KToolBar::Right: 01171 size += QSize(toolBar()->sizeHint().width(), 0); 01172 break; 01173 01174 case KToolBar::Flat: 01175 size += QSize(0, 3+kapp->style().pixelMetric( QStyle::PM_DockWindowHandleExtent )); 01176 break; 01177 01178 default: 01179 break; 01180 } 01181 } 01182 KMenuBar *mb = internalMenuBar(); 01183 if (mb && !mb->isHidden()) { 01184 size += QSize(0,mb->heightForWidth(size.width())); 01185 if (style().styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, this)) 01186 size += QSize( 0, dockWindowsMovable() ? 1 : 2); 01187 } 01188 QStatusBar *sb = internalStatusBar(); 01189 if( sb && !sb->isHidden() ) 01190 size += QSize(0, sb->sizeHint().height()); 01191 01192 return size; 01193 } 01194 01195 // why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI; 01196 // DF: because they compile KDE much faster :) 01197 void KMainWindow::finalizeGUI( KXMLGUIClient *client ) 01198 { KXMLGUIBuilder::finalizeGUI( client ); } 01199 01200 void KMainWindow::virtual_hook( int id, void* data ) 01201 { KXMLGUIBuilder::virtual_hook( id, data ); 01202 KXMLGUIClient::virtual_hook( id, data ); } 01203 01204 01205 01206 #include "kmainwindow.moc" 01207
KDE Logo
This file is part of the documentation for kdeui Library Version 3.3.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Oct 17 11:27:30 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003