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 00046 #include <klocale.h> 00047 #include <kstandarddirs.h> 00048 #include <kstaticdeleter.h> 00049 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00050 #include <netwm.h> 00051 #endif 00052 00053 #include <stdlib.h> 00054 #include <ctype.h> 00055 #include <assert.h> 00056 00057 class KMainWindowPrivate { 00058 public: 00059 bool showHelpMenu:1; 00060 00061 bool autoSaveSettings:1; 00062 bool settingsDirty:1; 00063 bool autoSaveWindowSize:1; 00064 bool care_about_geometry:1; 00065 bool shuttingDown:1; 00066 QString autoSaveGroup; 00067 KAccel * kaccel; 00068 KMainWindowInterface *m_interface; 00069 KDEPrivate::ToolBarHandler *toolBarHandler; 00070 QTimer* settingsTimer; 00071 KToggleAction *showStatusBarAction; 00072 QRect defaultWindowSize; 00073 QPtrList<QDockWindow> hiddenDockWindows; 00074 }; 00075 00076 QPtrList<KMainWindow>* KMainWindow::memberList = 0L; 00077 static bool no_query_exit = false; 00078 static KMWSessionManaged* ksm = 0; 00079 static KStaticDeleter<KMWSessionManaged> ksmd; 00080 00081 class KMWSessionManaged : public KSessionManaged 00082 { 00083 public: 00084 KMWSessionManaged() 00085 { 00086 }; 00087 ~KMWSessionManaged() 00088 { 00089 } 00090 bool saveState( QSessionManager& ) 00091 { 00092 KConfig* config = KApplication::kApplication()->sessionConfig(); 00093 if ( KMainWindow::memberList->first() ){ 00094 // According to Jochen Wilhelmy <digisnap@cs.tu-berlin.de>, this 00095 // hook is useful for better document orientation 00096 KMainWindow::memberList->first()->saveGlobalProperties(config); 00097 } 00098 00099 QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); 00100 int n = 0; 00101 for (it.toFirst(); it.current(); ++it){ 00102 if( it.current()->isVisible()) { 00103 n++; 00104 it.current()->savePropertiesInternal(config, n); 00105 } 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->isVisible()) { 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->isVisible()) { 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 void KMainWindow::createGUI( const QString &xmlfile, bool _conserveMemory ) 00425 { 00426 // disabling the updates prevents unnecessary redraws 00427 setUpdatesEnabled( false ); 00428 00429 // just in case we are rebuilding, let's remove our old client 00430 guiFactory()->removeClient( this ); 00431 00432 // make sure to have an empty GUI 00433 QMenuBar* mb = internalMenuBar(); 00434 if ( mb ) 00435 mb->clear(); 00436 00437 (void)toolBarIterator(); // make sure toolbarList is most-up-to-date 00438 toolbarList.setAutoDelete( true ); 00439 toolbarList.clear(); 00440 toolbarList.setAutoDelete( false ); 00441 00442 // don't build a help menu unless the user ask for it 00443 if (d->showHelpMenu) { 00444 // we always want a help menu 00445 if (helpMenu2 == 0) 00446 helpMenu2 = new KHelpMenu(this, instance()->aboutData(), true, 00447 actionCollection()); 00448 } 00449 00450 // we always want to load in our global standards file 00451 setXMLFile( locate( "config", "ui/ui_standards.rc", instance() ) ); 00452 00453 // now, merge in our local xml file. if this is null, then that 00454 // means that we will be only using the global file 00455 if ( !xmlfile.isNull() ) { 00456 setXMLFile( xmlfile, true ); 00457 } else { 00458 QString auto_file(instance()->instanceName() + "ui.rc"); 00459 setXMLFile( auto_file, true ); 00460 } 00461 00462 // make sure we don't have any state saved already 00463 setXMLGUIBuildDocument( QDomDocument() ); 00464 00465 // do the actual GUI building 00466 guiFactory()->addClient( this ); 00467 00468 // try and get back *some* of our memory 00469 if ( _conserveMemory ) 00470 { 00471 // before freeing the memory allocated by the DOM document we also 00472 // free all memory allocated internally in the KXMLGUIFactory for 00473 // the menubar and the toolbars . This however implies that we 00474 // have to take care of deleting those widgets ourselves. For 00475 // destruction this is no problem, but when rebuilding we have 00476 // to take care of that (and we want to rebuild the GUI when 00477 // using stuff like the toolbar editor ). 00478 // In addition we have to take care of not removing containers 00479 // like popupmenus, defined in the XML document. 00480 // this code should probably go into a separate method in KMainWindow. 00481 // there's just one problem: I'm bad in finding names ;-) , so 00482 // I skipped this ;-) 00483 00484 QDomDocument doc = domDocument(); 00485 00486 QDomElement e = doc.documentElement().firstChild().toElement(); 00487 for (; !e.isNull(); e = e.nextSibling().toElement() ) { 00488 if ( e.tagName().lower() == "toolbar" ) 00489 factory_->resetContainer( e.attribute( "name" ) ); 00490 else if ( e.tagName().lower() == "menubar" ) 00491 factory_->resetContainer( e.tagName(), true ); 00492 } 00493 00494 conserveMemory(); 00495 } 00496 00497 setUpdatesEnabled( true ); 00498 updateGeometry(); 00499 } 00500 00501 void KMainWindow::setHelpMenuEnabled(bool showHelpMenu) 00502 { 00503 d->showHelpMenu = showHelpMenu; 00504 } 00505 00506 bool KMainWindow::isHelpMenuEnabled() 00507 { 00508 return d->showHelpMenu; 00509 } 00510 00511 void KMainWindow::setCaption( const QString &caption ) 00512 { 00513 setPlainCaption( kapp->makeStdCaption(caption) ); 00514 } 00515 00516 void KMainWindow::setCaption( const QString &caption, bool modified ) 00517 { 00518 setPlainCaption( kapp->makeStdCaption(caption, true, modified) ); 00519 } 00520 00521 void KMainWindow::setPlainCaption( const QString &caption ) 00522 { 00523 QMainWindow::setCaption( caption ); 00524 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00525 //#ifndef Q_WS_QWS 00526 NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), 0 ); 00527 info.setName( caption.utf8().data() ); 00528 #endif 00529 } 00530 00531 void KMainWindow::appHelpActivated( void ) 00532 { 00533 if( mHelpMenu == 0 ) { 00534 mHelpMenu = new KHelpMenu( this ); 00535 if ( mHelpMenu == 0 ) 00536 return; 00537 } 00538 mHelpMenu->appHelpActivated(); 00539 } 00540 00541 void KMainWindow::slotStateChanged(const QString &newstate) 00542 { 00543 stateChanged(newstate, KXMLGUIClient::StateNoReverse); 00544 } 00545 00546 /* 00547 * Get rid of this for KDE 4.0 00548 */ 00549 void KMainWindow::slotStateChanged(const QString &newstate, 00550 KXMLGUIClient::ReverseStateChange reverse) 00551 { 00552 stateChanged(newstate, reverse); 00553 } 00554 00555 /* 00556 * Enable this for KDE 4.0 00557 */ 00558 // void KMainWindow::slotStateChanged(const QString &newstate, 00559 // bool reverse) 00560 // { 00561 // stateChanged(newstate, 00562 // reverse ? KXMLGUIClient::StateReverse : KXMLGUIClient::StateNoReverse); 00563 // } 00564 00565 void KMainWindow::closeEvent ( QCloseEvent *e ) 00566 { 00567 // Save settings if auto-save is enabled, and settings have changed 00568 if (d->settingsDirty && d->autoSaveSettings) 00569 saveAutoSaveSettings(); 00570 00571 if (queryClose()) { 00572 e->accept(); 00573 00574 int not_withdrawn = 0; 00575 QPtrListIterator<KMainWindow> it(*KMainWindow::memberList); 00576 for (it.toFirst(); it.current(); ++it){ 00577 if ( !it.current()->isHidden() && it.current()->isTopLevel() && it.current() != this ) 00578 not_withdrawn++; 00579 } 00580 00581 if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted? 00582 if ( queryExit() && !kapp->sessionSaving() && !d->shuttingDown ) { // Yes, Quit app? 00583 // don't call queryExit() twice 00584 disconnect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown())); 00585 d->shuttingDown = true; 00586 kapp->deref(); // ...and quit application. 00587 } else { 00588 // cancel closing, it's stupid to end up with no windows at all.... 00589 e->ignore(); 00590 } 00591 } 00592 } 00593 } 00594 00595 bool KMainWindow::queryExit() 00596 { 00597 return true; 00598 } 00599 00600 bool KMainWindow::queryClose() 00601 { 00602 return true; 00603 } 00604 00605 void KMainWindow::saveGlobalProperties( KConfig* ) 00606 { 00607 } 00608 00609 void KMainWindow::readGlobalProperties( KConfig* ) 00610 { 00611 } 00612 00613 #if defined(KDE_COMPAT) 00614 void KMainWindow::updateRects() 00615 { 00616 } 00617 #endif 00618 00619 void KMainWindow::showAboutApplication() 00620 { 00621 } 00622 00623 void KMainWindow::savePropertiesInternal( KConfig *config, int number ) 00624 { 00625 bool oldASWS = d->autoSaveWindowSize; 00626 d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size 00627 00628 QString s; 00629 s.setNum(number); 00630 s.prepend(QString::fromLatin1("WindowProperties")); 00631 config->setGroup(s); 00632 00633 // store objectName, className, Width and Height for later restoring 00634 // (Only useful for session management) 00635 config->writeEntry(QString::fromLatin1("ObjectName"), name()); 00636 config->writeEntry(QString::fromLatin1("ClassName"), className()); 00637 00638 saveMainWindowSettings(config); // Menubar, statusbar and Toolbar settings. 00639 00640 s.setNum(number); 00641 config->setGroup(s); 00642 saveProperties(config); 00643 00644 d->autoSaveWindowSize = oldASWS; 00645 } 00646 00647 void KMainWindow::saveMainWindowSettings(KConfig *config, const QString &configGroup) 00648 { 00649 kdDebug(200) << "KMainWindow::saveMainWindowSettings " << configGroup << endl; 00650 QString oldGroup; 00651 00652 if (!configGroup.isEmpty()) 00653 { 00654 oldGroup = config->group(); 00655 config->setGroup(configGroup); 00656 } 00657 00658 // Called by session management - or if we want to save the window size anyway 00659 if ( d->autoSaveWindowSize ) 00660 saveWindowSize( config ); 00661 00662 QStatusBar* sb = internalStatusBar(); 00663 if (sb) { 00664 if(!config->hasDefault("StatusBar") && !sb->isHidden() ) 00665 config->revertToDefault("StatusBar"); 00666 else 00667 config->writeEntry("StatusBar", sb->isHidden() ? "Disabled" : "Enabled"); 00668 } 00669 00670 QMenuBar* mb = internalMenuBar(); 00671 if (mb) { 00672 QString MenuBar = QString::fromLatin1("MenuBar"); 00673 if(!config->hasDefault("MenuBar") && !mb->isHidden() ) 00674 config->revertToDefault("MenuBar"); 00675 else 00676 config->writeEntry("MenuBar", mb->isHidden() ? "Disabled" : "Enabled"); 00677 } 00678 00679 int n = 1; // Toolbar counter. toolbars are counted from 1, 00680 KToolBar *toolbar = 0; 00681 QPtrListIterator<KToolBar> it( toolBarIterator() ); 00682 while ( ( toolbar = it.current() ) ) { 00683 ++it; 00684 QString group; 00685 if (!configGroup.isEmpty()) 00686 { 00687 // Give a number to the toolbar, but prefer a name if there is one, 00688 // because there's no real guarantee on the ordering of toolbars 00689 group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name()); 00690 group.prepend(" Toolbar"); 00691 group.prepend(configGroup); 00692 } 00693 toolbar->saveSettings(config, group); 00694 n++; 00695 } 00696 if (!configGroup.isEmpty()) 00697 config->setGroup(oldGroup); 00698 } 00699 00700 void KMainWindow::setStandardToolBarMenuEnabled( bool enable ) 00701 { 00702 if ( enable ) { 00703 if ( d->toolBarHandler ) 00704 return; 00705 00706 d->toolBarHandler = new KDEPrivate::ToolBarHandler( this ); 00707 00708 if ( factory() ) 00709 factory()->addClient( d->toolBarHandler ); 00710 } else { 00711 if ( !d->toolBarHandler ) 00712 return; 00713 00714 if ( factory() ) 00715 factory()->removeClient( d->toolBarHandler ); 00716 00717 delete d->toolBarHandler; 00718 d->toolBarHandler = 0; 00719 } 00720 } 00721 00722 bool KMainWindow::isStandardToolBarMenuEnabled() const 00723 { 00724 return ( d->toolBarHandler != 0 ); 00725 } 00726 00727 void KMainWindow::createStandardStatusBarAction(){ 00728 if(!d->showStatusBarAction){ 00729 d->showStatusBarAction = KStdAction::showStatusbar(this, SLOT(setSettingsDirty()), actionCollection()); 00730 KStatusBar *sb = statusBar(); // Creates statusbar if it doesn't exist already. 00731 connect(d->showStatusBarAction, SIGNAL(toggled(bool)), sb, SLOT(setShown(bool))); 00732 d->showStatusBarAction->setChecked(sb->isHidden()); 00733 } 00734 } 00735 00736 bool KMainWindow::readPropertiesInternal( KConfig *config, int number ) 00737 { 00738 if ( number == 1 ) 00739 readGlobalProperties( config ); 00740 00741 // in order they are in toolbar list 00742 QString s; 00743 s.setNum(number); 00744 s.prepend(QString::fromLatin1("WindowProperties")); 00745 00746 config->setGroup(s); 00747 00748 // restore the object name (window role) 00749 if ( config->hasKey(QString::fromLatin1("ObjectName" )) ) 00750 setName( config->readEntry(QString::fromLatin1("ObjectName")).latin1()); // latin1 is right here 00751 00752 applyMainWindowSettings(config); // Menubar, statusbar and toolbar settings. 00753 00754 s.setNum(number); 00755 config->setGroup(s); 00756 readProperties(config); 00757 return true; 00758 } 00759 00760 void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup) 00761 { 00762 kdDebug(200) << "KMainWindow::applyMainWindowSettings" << endl; 00763 if (!configGroup.isEmpty()) 00764 config->setGroup(configGroup); 00765 00766 restoreWindowSize(config); 00767 00768 QStatusBar* sb = internalStatusBar(); 00769 if (sb) { 00770 QString entry = config->readEntry("StatusBar", "Enabled"); 00771 if ( entry == "Disabled" ) 00772 sb->hide(); 00773 else 00774 sb->show(); 00775 if(d->showStatusBarAction) 00776 d->showStatusBarAction->setChecked(!sb->isHidden()); 00777 } 00778 00779 QMenuBar* mb = internalMenuBar(); 00780 if (mb) { 00781 QString entry = config->readEntry ("MenuBar", "Enabled"); 00782 if ( entry == "Disabled" ) 00783 mb->hide(); 00784 else 00785 mb->show(); 00786 } 00787 00788 int n = 1; // Toolbar counter. toolbars are counted from 1, 00789 KToolBar *toolbar; 00790 QPtrListIterator<KToolBar> it( toolBarIterator() ); // must use own iterator 00791 00792 for ( ; it.current(); ++it) { 00793 toolbar= it.current(); 00794 QString group; 00795 if (!configGroup.isEmpty()) 00796 { 00797 // Give a number to the toolbar, but prefer a name if there is one, 00798 // because there's no real guarantee on the ordering of toolbars 00799 group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name()); 00800 group.prepend(" Toolbar"); 00801 group.prepend(configGroup); 00802 } 00803 toolbar->applySettings(config, group); 00804 n++; 00805 } 00806 00807 finalizeGUI( true ); 00808 } 00809 00810 void KMainWindow::finalizeGUI( bool force ) 00811 { 00812 //kdDebug(200) << "KMainWindow::finalizeGUI force=" << force << endl; 00813 // The whole reason for this is that moveToolBar relies on the indexes 00814 // of the other toolbars, so in theory it should be called only once per 00815 // toolbar, but in increasing order of indexes. 00816 // Since we can't do that immediately, we move them, and _then_ 00817 // we call positionYourself again for each of them, but this time 00818 // the toolbariterator should give them in the proper order. 00819 // Both the XMLGUI and applySettings call this, hence "force" for the latter. 00820 QPtrListIterator<KToolBar> it( toolBarIterator() ); 00821 for ( ; it.current() ; ++ it ) 00822 it.current()->positionYourself( force ); 00823 00824 d->settingsDirty = false; 00825 } 00826 00827 void KMainWindow::saveWindowSize( KConfig * config ) const 00828 { 00829 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00830 int scnum = QApplication::desktop()->screenNumber(parentWidget()); 00831 QRect desk = QApplication::desktop()->screenGeometry(scnum); 00832 // save maximalization as desktop size + 1 in that direction 00833 KWin::WindowInfo info = KWin::windowInfo( winId(), NET::WMState ); 00834 int w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width(); 00835 int h = info.state() & NET::MaxVert ? desk.height() + 1 : height(); 00836 QRect size( desk.width(), w, desk.height(), h ); 00837 #else 00838 int w = 500; 00839 int h = 500; 00840 QRect desk( 100, 100, 200, 200 ); // fixme 00841 QRect size( 100, 100, 200, 200 ); // fixme 00842 #endif 00843 bool defaultSize = (size == d->defaultWindowSize); 00844 QString widthString = QString::fromLatin1("Width %1").arg(desk.width()); 00845 QString heightString = QString::fromLatin1("Height %1").arg(desk.height()); 00846 if (!config->hasDefault(widthString) && defaultSize) 00847 config->revertToDefault(widthString); 00848 else 00849 config->writeEntry(widthString, w ); 00850 00851 if (!config->hasDefault(heightString) && defaultSize) 00852 config->revertToDefault(heightString); 00853 else 00854 config->writeEntry(heightString, h ); 00855 } 00856 00857 void KMainWindow::restoreWindowSize( KConfig * config ) 00858 { 00859 if (d->care_about_geometry) { 00860 parseGeometry(true); 00861 } else { 00862 // restore the size 00863 int scnum = QApplication::desktop()->screenNumber(parentWidget()); 00864 QRect desk = QApplication::desktop()->screenGeometry(scnum); 00865 if ( d->defaultWindowSize.isNull() ) // only once 00866 d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); // store default values 00867 QSize size( config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ), 00868 config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) ); 00869 if (size.isEmpty()) { 00870 // try the KDE 2.0 way 00871 size = QSize( config->readNumEntry( QString::fromLatin1("Width"), 0 ), 00872 config->readNumEntry( QString::fromLatin1("Height"), 0 ) ); 00873 if (!size.isEmpty()) { 00874 // make sure the other resolutions don't get old settings 00875 config->writeEntry( QString::fromLatin1("Width"), 0 ); 00876 config->writeEntry( QString::fromLatin1("Height"), 0 ); 00877 } 00878 } 00879 if ( !size.isEmpty() ) { 00880 int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 ) 00881 | ( size.height() > desk.height() ? NET::MaxVert : 0 ); 00882 if(( state & NET::Max ) == NET::Max ) 00883 ; // no resize 00884 else if(( state & NET::MaxHoriz ) == NET::MaxHoriz ) 00885 resize( width(), size.height()); 00886 else if(( state & NET::MaxVert ) == NET::MaxVert ) 00887 resize( size.width(), height()); 00888 else 00889 resize( size ); 00890 // QWidget::showMaximized() is both insufficient and broken 00891 KWin::setState( winId(), state ); 00892 } 00893 } 00894 } 00895 00896 bool KMainWindow::initialGeometrySet() const 00897 { 00898 return d->care_about_geometry; 00899 } 00900 00901 void KMainWindow::ignoreInitialGeometry() 00902 { 00903 d->care_about_geometry = false; 00904 } 00905 00906 void KMainWindow::setSettingsDirty() 00907 { 00908 //kdDebug(200) << "KMainWindow::setSettingsDirty" << endl; 00909 d->settingsDirty = true; 00910 if ( d->autoSaveSettings ) 00911 { 00912 // Use a timer to save "immediately" user-wise, but not too immediately 00913 // (to compress calls and save only once, in case of multiple changes) 00914 if ( !d->settingsTimer ) 00915 { 00916 d->settingsTimer = new QTimer( this ); 00917 connect( d->settingsTimer, SIGNAL( timeout() ), SLOT( saveAutoSaveSettings() ) ); 00918 } 00919 d->settingsTimer->start( 500, true ); 00920 } 00921 } 00922 00923 bool KMainWindow::settingsDirty() const 00924 { 00925 return d->settingsDirty; 00926 } 00927 00928 QString KMainWindow::settingsGroup() const 00929 { 00930 return d->autoSaveGroup; 00931 } 00932 00933 void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize ) 00934 { 00935 d->autoSaveSettings = true; 00936 d->autoSaveGroup = groupName; 00937 d->autoSaveWindowSize = saveWindowSize; 00938 // Get notified when the user moves a toolbar around 00939 connect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ), 00940 this, SLOT( setSettingsDirty() ) ); 00941 00942 // Now read the previously saved settings 00943 applyMainWindowSettings( KGlobal::config(), groupName ); 00944 } 00945 00946 void KMainWindow::resetAutoSaveSettings() 00947 { 00948 d->autoSaveSettings = false; 00949 if ( d->settingsTimer ) 00950 d->settingsTimer->stop(); 00951 } 00952 00953 bool KMainWindow::autoSaveSettings() const 00954 { 00955 return d->autoSaveSettings; 00956 } 00957 00958 QString KMainWindow::autoSaveGroup() const 00959 { 00960 return d->autoSaveGroup; 00961 } 00962 00963 void KMainWindow::saveAutoSaveSettings() 00964 { 00965 Q_ASSERT( d->autoSaveSettings ); 00966 //kdDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings" << endl; 00967 saveMainWindowSettings( KGlobal::config(), d->autoSaveGroup ); 00968 KGlobal::config()->sync(); 00969 d->settingsDirty = false; 00970 if ( d->settingsTimer ) 00971 d->settingsTimer->stop(); 00972 } 00973 00974 void KMainWindow::resizeEvent( QResizeEvent * ) 00975 { 00976 if ( d->autoSaveWindowSize ) 00977 setSettingsDirty(); 00978 } 00979 00980 bool KMainWindow::hasMenuBar() 00981 { 00982 return (internalMenuBar()); 00983 } 00984 00985 KMenuBar *KMainWindow::menuBar() 00986 { 00987 KMenuBar * mb = internalMenuBar(); 00988 if ( !mb ) { 00989 mb = new KMenuBar( this ); 00990 // trigger a re-layout and trigger a call to the private 00991 // setMenuBar method. 00992 QMainWindow::menuBar(); 00993 } 00994 return mb; 00995 } 00996 00997 KStatusBar *KMainWindow::statusBar() 00998 { 00999 KStatusBar * sb = internalStatusBar(); 01000 if ( !sb ) { 01001 sb = new KStatusBar( this ); 01002 // trigger a re-layout and trigger a call to the private 01003 // setStatusBar method. 01004 QMainWindow::statusBar(); 01005 } 01006 return sb; 01007 } 01008 01009 void KMainWindow::shuttingDown() 01010 { 01011 // Needed for Qt <= 3.0.3 at least to prevent reentrancy 01012 // when queryExit() shows a dialog. Check before removing! 01013 static bool reentrancy_protection = false; 01014 if (!reentrancy_protection) 01015 { 01016 reentrancy_protection = true; 01017 // call the virtual queryExit 01018 queryExit(); 01019 reentrancy_protection = false; 01020 } 01021 01022 } 01023 01024 KMenuBar *KMainWindow::internalMenuBar() 01025 { 01026 QObjectList *l = queryList( "KMenuBar", 0, false, false ); 01027 if ( !l || !l->first() ) { 01028 delete l; 01029 return 0; 01030 } 01031 01032 KMenuBar *m = (KMenuBar*)l->first(); 01033 delete l; 01034 return m; 01035 } 01036 01037 KStatusBar *KMainWindow::internalStatusBar() 01038 { 01039 QObjectList *l = queryList( "KStatusBar", 0, false, false ); 01040 if ( !l || !l->first() ) { 01041 delete l; 01042 return 0; 01043 } 01044 01045 KStatusBar *s = (KStatusBar*)l->first(); 01046 delete l; 01047 return s; 01048 } 01049 01050 void KMainWindow::childEvent( QChildEvent* e) 01051 { 01052 QMainWindow::childEvent( e ); 01053 } 01054 01055 KToolBar *KMainWindow::toolBar( const char * name ) 01056 { 01057 if (!name) 01058 name = "mainToolBar"; 01059 KToolBar *tb = (KToolBar*)child( name, "KToolBar" ); 01060 if ( tb ) 01061 return tb; 01062 bool honor_mode = (name == "mainToolBar"); 01063 01064 if ( builderClient() ) 01065 return new KToolBar(this, name, honor_mode); // XMLGUI constructor 01066 else 01067 return new KToolBar(this, DockTop, false, name, honor_mode ); // non-XMLGUI 01068 } 01069 01070 QPtrListIterator<KToolBar> KMainWindow::toolBarIterator() 01071 { 01072 toolbarList.clear(); 01073 QPtrList<QToolBar> lst; 01074 for ( int i = (int)QMainWindow::DockUnmanaged; i <= (int)DockMinimized; ++i ) { 01075 lst = toolBars( (ToolBarDock)i ); 01076 for ( QToolBar *tb = lst.first(); tb; tb = lst.next() ) { 01077 if ( !tb->inherits( "KToolBar" ) ) 01078 continue; 01079 toolbarList.append( (KToolBar*)tb ); 01080 } 01081 } 01082 return QPtrListIterator<KToolBar>( toolbarList ); 01083 } 01084 01085 KAccel * KMainWindow::accel() 01086 { 01087 if ( !d->kaccel ) 01088 d->kaccel = new KAccel( this, "kmw-kaccel" ); 01089 return d->kaccel; 01090 } 01091 01092 void KMainWindow::paintEvent( QPaintEvent * ) 01093 { 01094 // do nothing 01095 } 01096 01097 QSize KMainWindow::sizeForCentralWidgetSize(QSize size) 01098 { 01099 KToolBar *tb = (KToolBar*)child( "mainToolBar", "KToolBar" ); 01100 if (tb && !tb->isHidden()) { 01101 switch( tb->barPos() ) 01102 { 01103 case KToolBar::Top: 01104 case KToolBar::Bottom: 01105 size += QSize(0, tb->sizeHint().height()); 01106 break; 01107 01108 case KToolBar::Left: 01109 case KToolBar::Right: 01110 size += QSize(toolBar()->sizeHint().width(), 0); 01111 break; 01112 01113 case KToolBar::Flat: 01114 size += QSize(0, 3+kapp->style().pixelMetric( QStyle::PM_DockWindowHandleExtent )); 01115 break; 01116 01117 default: 01118 break; 01119 } 01120 } 01121 KMenuBar *mb = internalMenuBar(); 01122 if (mb && !mb->isHidden()) { 01123 size += QSize(0,mb->heightForWidth(size.width())); 01124 if (style().styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, this)) 01125 size += QSize( 0, dockWindowsMovable() ? 1 : 2); 01126 } 01127 QStatusBar *sb = internalStatusBar(); 01128 if( sb && !sb->isHidden() ) 01129 size += QSize(0, sb->sizeHint().height()); 01130 01131 return size; 01132 } 01133 01134 // why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI; 01135 // DF: because they compile KDE much faster :) 01136 void KMainWindow::finalizeGUI( KXMLGUIClient *client ) 01137 { KXMLGUIBuilder::finalizeGUI( client ); } 01138 01139 void KMainWindow::virtual_hook( int id, void* data ) 01140 { KXMLGUIBuilder::virtual_hook( id, data ); 01141 KXMLGUIClient::virtual_hook( id, data ); } 01142 01143 01144 01145 #include "kmainwindow.moc" 01146
KDE Logo
This file is part of the documentation for kdeui Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Oct 10 18:55:09 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003