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 "kwhatsthismanager_p.h" 00030 #include <qsessionmanager.h> 00031 #include <qobjectlist.h> 00032 #include <qstyle.h> 00033 #include <qlayout.h> 00034 #include <qwidgetlist.h> 00035 #include <qtimer.h> 00036 00037 #include <kaccel.h> 00038 #include <kaction.h> 00039 #include <kapplication.h> 00040 #include <kconfig.h> 00041 #include <kdebug.h> 00042 #include <khelpmenu.h> 00043 #include <kmenubar.h> 00044 #include <kstatusbar.h> 00045 #include <kwin.h> 00046 #include <kedittoolbar.h> 00047 #include <kmainwindow.h> 00048 00049 #include <klocale.h> 00050 #include <kstandarddirs.h> 00051 #include <kstaticdeleter.h> 00052 #if defined Q_WS_X11 00053 #include <netwm.h> 00054 #endif 00055 00056 #include <stdlib.h> 00057 #include <ctype.h> 00058 #include <assert.h> 00059 00060 class KMainWindowPrivate { 00061 public: 00062 bool showHelpMenu:1; 00063 00064 bool autoSaveSettings:1; 00065 bool settingsDirty:1; 00066 bool autoSaveWindowSize:1; 00067 bool care_about_geometry:1; 00068 bool shuttingDown:1; 00069 QString autoSaveGroup; 00070 KAccel * kaccel; 00071 KMainWindowInterface *m_interface; 00072 KDEPrivate::ToolBarHandler *toolBarHandler; 00073 QTimer* settingsTimer; 00074 KToggleAction *showStatusBarAction; 00075 QRect defaultWindowSize; 00076 QPtrList<QDockWindow> hiddenDockWindows; 00077 }; 00078 00079 QPtrList<KMainWindow>* KMainWindow::memberList = 0L; 00080 static bool no_query_exit = false; 00081 static KMWSessionManaged* ksm = 0; 00082 static KStaticDeleter<KMWSessionManaged> ksmd; 00083 00084 class KMWSessionManaged : public KSessionManaged 00085 { 00086 public: 00087 KMWSessionManaged() 00088 { 00089 }; 00090 ~KMWSessionManaged() 00091 { 00092 } 00093 bool saveState( QSessionManager& ) 00094 { 00095 KConfig* config = KApplication::kApplication()->sessionConfig(); 00096 if ( KMainWindow::memberList->first() ){ 00097 // According to Jochen Wilhelmy <digisnap@cs.tu-berlin.de>, this 00098 // hook is useful for better document orientation 00099 KMainWindow::memberList->first()->saveGlobalProperties(config); 00100 } 00101 00102 QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); 00103 int n = 0; 00104 for (it.toFirst(); it.current(); ++it){ 00105 n++; 00106 it.current()->savePropertiesInternal(config, n); 00107 } 00108 config->setGroup(QString::fromLatin1("Number")); 00109 config->writeEntry(QString::fromLatin1("NumberOfWindows"), n ); 00110 return true; 00111 } 00112 00113 bool commitData( QSessionManager& sm ) 00114 { 00115 // not really a fast method but the only compatible one 00116 if ( sm.allowsInteraction() ) { 00117 bool canceled = false; 00118 QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); 00119 ::no_query_exit = true; 00120 for (it.toFirst(); it.current() && !canceled;){ 00121 KMainWindow *window = *it; 00122 ++it; // Update now, the current window might get deleted 00123 if ( !window->testWState( Qt::WState_ForceHide ) ) { 00124 QCloseEvent e; 00125 QApplication::sendEvent( window, &e ); 00126 canceled = !e.isAccepted(); 00127 /* Don't even think_about deleting widgets with 00128 Qt::WDestructiveClose flag set at this point. We 00129 are faking a close event, but we are *not*_ 00130 closing the window. The purpose of the faked 00131 close event is to prepare the application so it 00132 can safely be quit without the user losing data 00133 (possibly showing a message box "do you want to 00134 save this or that?"). It is possible that the 00135 session manager quits the application later 00136 (emitting QApplication::aboutToQuit() when this 00137 happens), but it is also possible that the user 00138 cancels the shutdown, so the application will 00139 continue to run. 00140 */ 00141 } 00142 } 00143 ::no_query_exit = false; 00144 if (canceled) 00145 return false; 00146 00147 KMainWindow* last = 0; 00148 for (it.toFirst(); it.current() && !canceled; ++it){ 00149 KMainWindow *window = *it; 00150 if ( !window->testWState( Qt::WState_ForceHide ) ) { 00151 last = window; 00152 } 00153 } 00154 if ( last ) 00155 return last->queryExit(); 00156 // else 00157 return true; 00158 } 00159 00160 // the user wants it, the user gets it 00161 return true; 00162 } 00163 }; 00164 00165 static bool being_first = true; 00166 00167 KMainWindow::KMainWindow( QWidget* parent, const char *name, WFlags f ) 00168 : QMainWindow( parent, name, f ), KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 ) 00169 { 00170 initKMainWindow(name, 0); 00171 } 00172 00173 KMainWindow::KMainWindow( int cflags, QWidget* parent, const char *name, WFlags f ) 00174 : QMainWindow( parent, name, f ), KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 ) 00175 { 00176 initKMainWindow(name, cflags); 00177 } 00178 00179 void KMainWindow::initKMainWindow(const char *name, int cflags) 00180 { 00181 KWhatsThisManager::init (); 00182 setDockMenuEnabled( false ); 00183 mHelpMenu = 0; 00184 kapp->setTopWidget( this ); 00185 actionCollection()->setWidget( this ); 00186 connect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown())); 00187 if( !memberList ) 00188 memberList = new QPtrList<KMainWindow>; 00189 00190 if ( !ksm ) 00191 ksm = ksmd.setObject(ksm, new KMWSessionManaged()); 00192 // set a unique object name. Required by session management. 00193 QCString objname; 00194 QCString s; 00195 int unusedNumber; 00196 if ( !name ) 00197 { // no name given 00198 objname = kapp->instanceName() + "-mainwindow#"; 00199 s = objname + '1'; // start adding number immediately 00200 unusedNumber = 1; 00201 } 00202 else if( name[ strlen( name ) - 1 ] == '#' ) 00203 { // trailing # - always add a number 00204 objname = name; 00205 s = objname + '1'; // start adding number immediately 00206 unusedNumber = 1; 00207 } 00208 else 00209 { 00210 objname = name; 00211 s = objname; 00212 unusedNumber = 0; // add numbers only when needed 00213 } 00214 for(;;) { 00215 QWidgetList* list = kapp->topLevelWidgets(); 00216 QWidgetListIt it( *list ); 00217 bool found = false; 00218 for( QWidget* w = it.current(); 00219 w != NULL; 00220 ++it, w = it.current()) 00221 if( w != this && w->name() == s ) 00222 { 00223 found = true; 00224 break; 00225 } 00226 delete list; 00227 if( !found ) 00228 break; 00229 s.setNum( ++unusedNumber ); 00230 s = objname + s; 00231 } 00232 setName( s ); 00233 00234 memberList->append( this ); 00235 00236 d = new KMainWindowPrivate; 00237 d->showHelpMenu = true; 00238 d->settingsDirty = false; 00239 d->autoSaveSettings = false; 00240 d->autoSaveWindowSize = true; // for compatibility 00241 d->kaccel = actionCollection()->kaccel(); 00242 d->toolBarHandler = 0; 00243 d->settingsTimer = 0; 00244 d->showStatusBarAction = NULL; 00245 d->shuttingDown = false; 00246 if ((d->care_about_geometry = being_first)) { 00247 being_first = false; 00248 if ( kapp->geometryArgument().isNull() ) // if there is no geometry, it doesn't mater 00249 d->care_about_geometry = false; 00250 else 00251 parseGeometry(false); 00252 } 00253 00254 setCaption( kapp->caption() ); 00255 if ( cflags & NoDCOPObject) 00256 d->m_interface = 0; 00257 else 00258 d->m_interface = new KMainWindowInterface(this); 00259 00260 if (!kapp->authorize("movable_toolbars")) 00261 setDockWindowsMovable(false); 00262 } 00263 00264 KAction *KMainWindow::toolBarMenuAction() 00265 { 00266 if ( !d->toolBarHandler ) 00267 return 0; 00268 00269 return d->toolBarHandler->toolBarMenuAction(); 00270 } 00271 00272 00273 void KMainWindow::setupToolbarMenuActions() 00274 { 00275 if ( d->toolBarHandler ) 00276 d->toolBarHandler->setupActions(); 00277 } 00278 00279 void KMainWindow::parseGeometry(bool parsewidth) 00280 { 00281 assert ( !kapp->geometryArgument().isNull() ); 00282 assert ( d->care_about_geometry ); 00283 00284 #if defined Q_WS_X11 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) ) 00292 w = width(); 00293 if ( !(m & HeightValue) ) 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) ) 00302 x = geometry().x(); 00303 if ( parsewidth && !(m & YValue) ) 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 ) { 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 ) 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 ) { 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) 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 00581 NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), 0 ); 00582 info.setName( caption.utf8().data() ); 00583 #endif 00584 } 00585 00586 void KMainWindow::appHelpActivated( void ) 00587 { 00588 if( !mHelpMenu ) { 00589 mHelpMenu = new KHelpMenu( this ); 00590 if ( !mHelpMenu ) 00591 return; 00592 } 00593 mHelpMenu->appHelpActivated(); 00594 } 00595 00596 void KMainWindow::slotStateChanged(const QString &newstate) 00597 { 00598 stateChanged(newstate, KXMLGUIClient::StateNoReverse); 00599 } 00600 00601 /* 00602 * Get rid of this for KDE 4.0 00603 */ 00604 void KMainWindow::slotStateChanged(const QString &newstate, 00605 KXMLGUIClient::ReverseStateChange reverse) 00606 { 00607 stateChanged(newstate, reverse); 00608 } 00609 00610 /* 00611 * Enable this for KDE 4.0 00612 */ 00613 // void KMainWindow::slotStateChanged(const QString &newstate, 00614 // bool reverse) 00615 // { 00616 // stateChanged(newstate, 00617 // reverse ? KXMLGUIClient::StateReverse : KXMLGUIClient::StateNoReverse); 00618 // } 00619 00620 void KMainWindow::closeEvent ( QCloseEvent *e ) 00621 { 00622 // Save settings if auto-save is enabled, and settings have changed 00623 if (d->settingsDirty && d->autoSaveSettings) 00624 saveAutoSaveSettings(); 00625 00626 if (queryClose()) { 00627 e->accept(); 00628 00629 int not_withdrawn = 0; 00630 QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); 00631 for (it.toFirst(); it.current(); ++it){ 00632 if ( !it.current()->isHidden() && it.current()->isTopLevel() && it.current() != this ) 00633 not_withdrawn++; 00634 } 00635 00636 if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted? 00637 if ( queryExit() && !kapp->sessionSaving() && !d->shuttingDown ) { // Yes, Quit app? 00638 // don't call queryExit() twice 00639 disconnect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown())); 00640 d->shuttingDown = true; 00641 kapp->deref(); // ...and quit application. 00642 } else { 00643 // cancel closing, it's stupid to end up with no windows at all.... 00644 e->ignore(); 00645 } 00646 } 00647 } 00648 } 00649 00650 bool KMainWindow::queryExit() 00651 { 00652 return true; 00653 } 00654 00655 bool KMainWindow::queryClose() 00656 { 00657 return true; 00658 } 00659 00660 void KMainWindow::saveGlobalProperties( KConfig* ) 00661 { 00662 } 00663 00664 void KMainWindow::readGlobalProperties( KConfig* ) 00665 { 00666 } 00667 00668 #if defined(KDE_COMPAT) 00669 void KMainWindow::updateRects() 00670 { 00671 } 00672 #endif 00673 00674 void KMainWindow::showAboutApplication() 00675 { 00676 } 00677 00678 void KMainWindow::savePropertiesInternal( KConfig *config, int number ) 00679 { 00680 bool oldASWS = d->autoSaveWindowSize; 00681 d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size 00682 00683 QString s; 00684 s.setNum(number); 00685 s.prepend(QString::fromLatin1("WindowProperties")); 00686 config->setGroup(s); 00687 00688 // store objectName, className, Width and Height for later restoring 00689 // (Only useful for session management) 00690 config->writeEntry(QString::fromLatin1("ObjectName"), name()); 00691 config->writeEntry(QString::fromLatin1("ClassName"), className()); 00692 00693 saveMainWindowSettings(config); // Menubar, statusbar and Toolbar settings. 00694 00695 s.setNum(number); 00696 config->setGroup(s); 00697 saveProperties(config); 00698 00699 d->autoSaveWindowSize = oldASWS; 00700 } 00701 00702 void KMainWindow::saveMainWindowSettings(KConfig *config, const QString &configGroup) 00703 { 00704 kdDebug(200) << "KMainWindow::saveMainWindowSettings " << configGroup << endl; 00705 QString oldGroup; 00706 00707 if (!configGroup.isEmpty()) 00708 { 00709 oldGroup = config->group(); 00710 config->setGroup(configGroup); 00711 } 00712 00713 // Called by session management - or if we want to save the window size anyway 00714 if ( d->autoSaveWindowSize ) 00715 saveWindowSize( config ); 00716 00717 QStatusBar* sb = internalStatusBar(); 00718 if (sb) { 00719 if(!config->hasDefault("StatusBar") && !sb->isHidden() ) 00720 config->revertToDefault("StatusBar"); 00721 else 00722 config->writeEntry("StatusBar", sb->isHidden() ? "Disabled" : "Enabled"); 00723 } 00724 00725 QMenuBar* mb = internalMenuBar(); 00726 if (mb) { 00727 QString MenuBar = QString::fromLatin1("MenuBar"); 00728 if(!config->hasDefault("MenuBar") && !mb->isHidden() ) 00729 config->revertToDefault("MenuBar"); 00730 else 00731 config->writeEntry("MenuBar", mb->isHidden() ? "Disabled" : "Enabled"); 00732 } 00733 00734 int n = 1; // Toolbar counter. toolbars are counted from 1, 00735 KToolBar *toolbar = 0; 00736 QPtrListIterator<KToolBar> it( toolBarIterator() ); 00737 while ( ( toolbar = it.current() ) ) { 00738 ++it; 00739 QString group; 00740 if (!configGroup.isEmpty()) 00741 { 00742 // Give a number to the toolbar, but prefer a name if there is one, 00743 // because there's no real guarantee on the ordering of toolbars 00744 group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name()); 00745 group.prepend(" Toolbar"); 00746 group.prepend(configGroup); 00747 } 00748 toolbar->saveSettings(config, group); 00749 n++; 00750 } 00751 if (!configGroup.isEmpty()) 00752 config->setGroup(oldGroup); 00753 } 00754 00755 void KMainWindow::setStandardToolBarMenuEnabled( bool enable ) 00756 { 00757 if ( enable ) { 00758 if ( d->toolBarHandler ) 00759 return; 00760 00761 d->toolBarHandler = new KDEPrivate::ToolBarHandler( this ); 00762 00763 if ( factory() ) 00764 factory()->addClient( d->toolBarHandler ); 00765 } else { 00766 if ( !d->toolBarHandler ) 00767 return; 00768 00769 if ( factory() ) 00770 factory()->removeClient( d->toolBarHandler ); 00771 00772 delete d->toolBarHandler; 00773 d->toolBarHandler = 0; 00774 } 00775 } 00776 00777 bool KMainWindow::isStandardToolBarMenuEnabled() const 00778 { 00779 return ( d->toolBarHandler ); 00780 } 00781 00782 void KMainWindow::createStandardStatusBarAction(){ 00783 if(!d->showStatusBarAction){ 00784 d->showStatusBarAction = KStdAction::showStatusbar(this, SLOT(setSettingsDirty()), actionCollection()); 00785 KStatusBar *sb = statusBar(); // Creates statusbar if it doesn't exist already. 00786 connect(d->showStatusBarAction, SIGNAL(toggled(bool)), sb, SLOT(setShown(bool))); 00787 d->showStatusBarAction->setChecked(sb->isHidden()); 00788 } 00789 } 00790 00791 bool KMainWindow::readPropertiesInternal( KConfig *config, int number ) 00792 { 00793 if ( number == 1 ) 00794 readGlobalProperties( config ); 00795 00796 // in order they are in toolbar list 00797 QString s; 00798 s.setNum(number); 00799 s.prepend(QString::fromLatin1("WindowProperties")); 00800 00801 config->setGroup(s); 00802 00803 // restore the object name (window role) 00804 if ( config->hasKey(QString::fromLatin1("ObjectName" )) ) 00805 setName( config->readEntry(QString::fromLatin1("ObjectName")).latin1()); // latin1 is right here 00806 00807 applyMainWindowSettings(config); // Menubar, statusbar and toolbar settings. 00808 00809 s.setNum(number); 00810 config->setGroup(s); 00811 readProperties(config); 00812 return true; 00813 } 00814 00815 void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup) 00816 { 00817 return applyMainWindowSettings(config,configGroup,false); 00818 } 00819 00820 void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup,bool force) 00821 { 00822 kdDebug(200) << "KMainWindow::applyMainWindowSettings" << endl; 00823 00824 KConfigGroupSaver saver( config, configGroup.isEmpty() ? config->group() : configGroup ); 00825 00826 restoreWindowSize(config); 00827 00828 QStatusBar* sb = internalStatusBar(); 00829 if (sb) { 00830 QString entry = config->readEntry("StatusBar", "Enabled"); 00831 if ( entry == "Disabled" ) 00832 sb->hide(); 00833 else 00834 sb->show(); 00835 if(d->showStatusBarAction) 00836 d->showStatusBarAction->setChecked(!sb->isHidden()); 00837 } 00838 00839 QMenuBar* mb = internalMenuBar(); 00840 if (mb) { 00841 QString entry = config->readEntry ("MenuBar", "Enabled"); 00842 if ( entry == "Disabled" ) 00843 mb->hide(); 00844 else 00845 mb->show(); 00846 } 00847 00848 int n = 1; // Toolbar counter. toolbars are counted from 1, 00849 KToolBar *toolbar; 00850 QPtrListIterator<KToolBar> it( toolBarIterator() ); // must use own iterator 00851 00852 for ( ; it.current(); ++it) { 00853 toolbar= it.current(); 00854 QString group; 00855 if (!configGroup.isEmpty()) 00856 { 00857 // Give a number to the toolbar, but prefer a name if there is one, 00858 // because there's no real guarantee on the ordering of toolbars 00859 group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name()); 00860 group.prepend(" Toolbar"); 00861 group.prepend(configGroup); 00862 } 00863 toolbar->applySettings(config, group, force); 00864 n++; 00865 } 00866 00867 finalizeGUI( true ); 00868 } 00869 00870 void KMainWindow::finalizeGUI( bool force ) 00871 { 00872 //kdDebug(200) << "KMainWindow::finalizeGUI force=" << force << endl; 00873 // The whole reason for this is that moveToolBar relies on the indexes 00874 // of the other toolbars, so in theory it should be called only once per 00875 // toolbar, but in increasing order of indexes. 00876 // Since we can't do that immediately, we move them, and _then_ 00877 // we call positionYourself again for each of them, but this time 00878 // the toolbariterator should give them in the proper order. 00879 // Both the XMLGUI and applySettings call this, hence "force" for the latter. 00880 QPtrListIterator<KToolBar> it( toolBarIterator() ); 00881 for ( ; it.current() ; ++it ) { 00882 it.current()->positionYourself( force ); 00883 } 00884 00885 d->settingsDirty = false; 00886 } 00887 00888 void KMainWindow::saveWindowSize( KConfig * config ) const 00889 { 00890 int scnum = QApplication::desktop()->screenNumber(parentWidget()); 00891 QRect desk = QApplication::desktop()->screenGeometry(scnum); 00892 int w, h; 00893 #if defined Q_WS_X11 00894 // save maximalization as desktop size + 1 in that direction 00895 KWin::WindowInfo info = KWin::windowInfo( winId(), NET::WMState ); 00896 w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width(); 00897 h = info.state() & NET::MaxVert ? desk.height() + 1 : height(); 00898 #else 00899 if (isMaximized()) { 00900 w = desk.width() + 1; 00901 h = desk.height() + 1; 00902 } 00903 //TODO: add "Maximized" property instead "+1" hack 00904 #endif 00905 QRect size( desk.width(), w, desk.height(), h ); 00906 bool defaultSize = (size == d->defaultWindowSize); 00907 QString widthString = QString::fromLatin1("Width %1").arg(desk.width()); 00908 QString heightString = QString::fromLatin1("Height %1").arg(desk.height()); 00909 if (!config->hasDefault(widthString) && defaultSize) 00910 config->revertToDefault(widthString); 00911 else 00912 config->writeEntry(widthString, w ); 00913 00914 if (!config->hasDefault(heightString) && defaultSize) 00915 config->revertToDefault(heightString); 00916 else 00917 config->writeEntry(heightString, h ); 00918 } 00919 00920 void KMainWindow::restoreWindowSize( KConfig * config ) 00921 { 00922 if (d->care_about_geometry) { 00923 parseGeometry(true); 00924 } else { 00925 // restore the size 00926 int scnum = QApplication::desktop()->screenNumber(parentWidget()); 00927 QRect desk = QApplication::desktop()->screenGeometry(scnum); 00928 if ( d->defaultWindowSize.isNull() ) // only once 00929 d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); // store default values 00930 QSize size( config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ), 00931 config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) ); 00932 if (size.isEmpty()) { 00933 // try the KDE 2.0 way 00934 size = QSize( config->readNumEntry( QString::fromLatin1("Width"), 0 ), 00935 config->readNumEntry( QString::fromLatin1("Height"), 0 ) ); 00936 if (!size.isEmpty()) { 00937 // make sure the other resolutions don't get old settings 00938 config->writeEntry( QString::fromLatin1("Width"), 0 ); 00939 config->writeEntry( QString::fromLatin1("Height"), 0 ); 00940 } 00941 } 00942 if ( !size.isEmpty() ) { 00943 #ifdef Q_WS_X11 00944 int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 ) 00945 | ( size.height() > desk.height() ? NET::MaxVert : 0 ); 00946 if(( state & NET::Max ) == NET::Max ) 00947 ; // no resize 00948 else if(( state & NET::MaxHoriz ) == NET::MaxHoriz ) 00949 resize( width(), size.height()); 00950 else if(( state & NET::MaxVert ) == NET::MaxVert ) 00951 resize( size.width(), height()); 00952 else 00953 resize( size ); 00954 // QWidget::showMaximized() is both insufficient and broken 00955 KWin::setState( winId(), state ); 00956 #else 00957 if (size.width() > desk.width() || size.height() > desk.height()) 00958 setWindowState( WindowMaximized ); 00959 else 00960 resize( size ); 00961 #endif 00962 } 00963 } 00964 } 00965 00966 bool KMainWindow::initialGeometrySet() const 00967 { 00968 return d->care_about_geometry; 00969 } 00970 00971 void KMainWindow::ignoreInitialGeometry() 00972 { 00973 d->care_about_geometry = false; 00974 } 00975 00976 void KMainWindow::setSettingsDirty() 00977 { 00978 //kdDebug(200) << "KMainWindow::setSettingsDirty" << endl; 00979 d->settingsDirty = true; 00980 if ( d->autoSaveSettings ) 00981 { 00982 // Use a timer to save "immediately" user-wise, but not too immediately 00983 // (to compress calls and save only once, in case of multiple changes) 00984 if ( !d->settingsTimer ) 00985 { 00986 d->settingsTimer = new QTimer( this ); 00987 connect( d->settingsTimer, SIGNAL( timeout() ), SLOT( saveAutoSaveSettings() ) ); 00988 } 00989 d->settingsTimer->start( 500, true ); 00990 } 00991 } 00992 00993 bool KMainWindow::settingsDirty() const 00994 { 00995 return d->settingsDirty; 00996 } 00997 00998 QString KMainWindow::settingsGroup() const 00999 { 01000 return d->autoSaveGroup; 01001 } 01002 01003 void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize ) 01004 { 01005 d->autoSaveSettings = true; 01006 d->autoSaveGroup = groupName; 01007 d->autoSaveWindowSize = saveWindowSize; 01008 // Get notified when the user moves a toolbar around 01009 disconnect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ), 01010 this, SLOT( setSettingsDirty() ) ); 01011 connect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ), 01012 this, SLOT( setSettingsDirty() ) ); 01013 01014 // Now read the previously saved settings 01015 applyMainWindowSettings( KGlobal::config(), groupName ); 01016 } 01017 01018 void KMainWindow::resetAutoSaveSettings() 01019 { 01020 d->autoSaveSettings = false; 01021 if ( d->settingsTimer ) 01022 d->settingsTimer->stop(); 01023 } 01024 01025 bool KMainWindow::autoSaveSettings() const 01026 { 01027 return d->autoSaveSettings; 01028 } 01029 01030 QString KMainWindow::autoSaveGroup() const 01031 { 01032 return d->autoSaveGroup; 01033 } 01034 01035 void KMainWindow::saveAutoSaveSettings() 01036 { 01037 Q_ASSERT( d->autoSaveSettings ); 01038 //kdDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings" << endl; 01039 saveMainWindowSettings( KGlobal::config(), d->autoSaveGroup ); 01040 KGlobal::config()->sync(); 01041 d->settingsDirty = false; 01042 if ( d->settingsTimer ) 01043 d->settingsTimer->stop(); 01044 } 01045 01046 void KMainWindow::resizeEvent( QResizeEvent * ) 01047 { 01048 if ( d->autoSaveWindowSize ) 01049 setSettingsDirty(); 01050 } 01051 01052 bool KMainWindow::hasMenuBar() 01053 { 01054 return (internalMenuBar()); 01055 } 01056 01057 KMenuBar *KMainWindow::menuBar() 01058 { 01059 KMenuBar * mb = internalMenuBar(); 01060 if ( !mb ) { 01061 mb = new KMenuBar( this ); 01062 // trigger a re-layout and trigger a call to the private 01063 // setMenuBar method. 01064 QMainWindow::menuBar(); 01065 } 01066 return mb; 01067 } 01068 01069 KStatusBar *KMainWindow::statusBar() 01070 { 01071 KStatusBar * sb = internalStatusBar(); 01072 if ( !sb ) { 01073 sb = new KStatusBar( this ); 01074 // trigger a re-layout and trigger a call to the private 01075 // setStatusBar method. 01076 QMainWindow::statusBar(); 01077 } 01078 return sb; 01079 } 01080 01081 void KMainWindow::shuttingDown() 01082 { 01083 // Needed for Qt <= 3.0.3 at least to prevent reentrancy 01084 // when queryExit() shows a dialog. Check before removing! 01085 static bool reentrancy_protection = false; 01086 if (!reentrancy_protection) 01087 { 01088 reentrancy_protection = true; 01089 // call the virtual queryExit 01090 queryExit(); 01091 reentrancy_protection = false; 01092 } 01093 01094 } 01095 01096 KMenuBar *KMainWindow::internalMenuBar() 01097 { 01098 QObjectList *l = queryList( "KMenuBar", 0, false, false ); 01099 if ( !l || !l->first() ) { 01100 delete l; 01101 return 0; 01102 } 01103 01104 KMenuBar *m = (KMenuBar*)l->first(); 01105 delete l; 01106 return m; 01107 } 01108 01109 KStatusBar *KMainWindow::internalStatusBar() 01110 { 01111 QObjectList *l = queryList( "KStatusBar", 0, false, false ); 01112 if ( !l || !l->first() ) { 01113 delete l; 01114 return 0; 01115 } 01116 01117 KStatusBar *s = (KStatusBar*)l->first(); 01118 delete l; 01119 return s; 01120 } 01121 01122 void KMainWindow::childEvent( QChildEvent* e) 01123 { 01124 QMainWindow::childEvent( e ); 01125 } 01126 01127 KToolBar *KMainWindow::toolBar( const char * name ) 01128 { 01129 if (!name) 01130 name = "mainToolBar"; 01131 KToolBar *tb = (KToolBar*)child( name, "KToolBar" ); 01132 if ( tb ) 01133 return tb; 01134 bool honor_mode = (name == "mainToolBar"); 01135 01136 if ( builderClient() ) 01137 return new KToolBar(this, name, honor_mode); // XMLGUI constructor 01138 else 01139 return new KToolBar(this, DockTop, false, name, honor_mode ); // non-XMLGUI 01140 } 01141 01142 QPtrListIterator<KToolBar> KMainWindow::toolBarIterator() 01143 { 01144 toolbarList.clear(); 01145 QPtrList<QToolBar> lst; 01146 for ( int i = (int)QMainWindow::DockUnmanaged; i <= (int)DockMinimized; ++i ) { 01147 lst = toolBars( (ToolBarDock)i ); 01148 for ( QToolBar *tb = lst.first(); tb; tb = lst.next() ) { 01149 if ( !tb->inherits( "KToolBar" ) ) 01150 continue; 01151 toolbarList.append( (KToolBar*)tb ); 01152 } 01153 } 01154 return QPtrListIterator<KToolBar>( toolbarList ); 01155 } 01156 01157 KAccel * KMainWindow::accel() 01158 { 01159 if ( !d->kaccel ) 01160 d->kaccel = new KAccel( this, "kmw-kaccel" ); 01161 return d->kaccel; 01162 } 01163 01164 void KMainWindow::paintEvent( QPaintEvent * pe ) 01165 { 01166 QMainWindow::paintEvent(pe); //Upcall to handle SH_MainWindow_SpaceBelowMenuBar rendering 01167 } 01168 01169 QSize KMainWindow::sizeForCentralWidgetSize(QSize size) 01170 { 01171 KToolBar *tb = (KToolBar*)child( "mainToolBar", "KToolBar" ); 01172 if (tb && !tb->isHidden()) { 01173 switch( tb->barPos() ) 01174 { 01175 case KToolBar::Top: 01176 case KToolBar::Bottom: 01177 size += QSize(0, tb->sizeHint().height()); 01178 break; 01179 01180 case KToolBar::Left: 01181 case KToolBar::Right: 01182 size += QSize(toolBar()->sizeHint().width(), 0); 01183 break; 01184 01185 case KToolBar::Flat: 01186 size += QSize(0, 3+kapp->style().pixelMetric( QStyle::PM_DockWindowHandleExtent )); 01187 break; 01188 01189 default: 01190 break; 01191 } 01192 } 01193 KMenuBar *mb = internalMenuBar(); 01194 if (mb && !mb->isHidden()) { 01195 size += QSize(0,mb->heightForWidth(size.width())); 01196 if (style().styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, this)) 01197 size += QSize( 0, dockWindowsMovable() ? 1 : 2); 01198 } 01199 QStatusBar *sb = internalStatusBar(); 01200 if( sb && !sb->isHidden() ) 01201 size += QSize(0, sb->sizeHint().height()); 01202 01203 return size; 01204 } 01205 01206 #if KDE_IS_VERSION( 3, 9, 0 ) 01207 #ifdef __GNUC__ 01208 #warning Remove, should be in Qt 01209 #endif 01210 #endif 01211 void KMainWindow::setIcon( const QPixmap& p ) 01212 { 01213 QMainWindow::setIcon( p ); 01214 #ifdef Q_WS_X11 01215 // Qt3 doesn't support _NET_WM_ICON, but KApplication::setTopWidget(), which 01216 // is used by KMainWindow, sets it 01217 KWin::setIcons( winId(), p, QPixmap()); 01218 #endif 01219 } 01220 01221 QPtrList<KMainWindow>* KMainWindow::getMemberList() { return memberList; } 01222 01223 // why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI; 01224 // DF: because they compile KDE much faster :) 01225 void KMainWindow::finalizeGUI( KXMLGUIClient *client ) 01226 { KXMLGUIBuilder::finalizeGUI( client ); } 01227 01228 void KMainWindow::virtual_hook( int id, void* data ) 01229 { KXMLGUIBuilder::virtual_hook( id, data ); 01230 KXMLGUIClient::virtual_hook( id, data ); } 01231 01232 01233 01234 #include "kmainwindow.moc" 01235
KDE Logo
This file is part of the documentation for kdeui Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 14 00:10:13 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003