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., 51 Franklin Street, Fifth Floor, 00022 Boston, MA 02110-1301, 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 <tqsessionmanager.h> 00031 #include <tqobjectlist.h> 00032 #include <tqstyle.h> 00033 #include <tqlayout.h> 00034 #include <tqwidgetlist.h> 00035 #include <tqtimer.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 TQString autoSaveGroup; 00070 KAccel * kaccel; 00071 KMainWindowInterface *m_interface; 00072 KDEPrivate::ToolBarHandler *toolBarHandler; 00073 TQTimer* settingsTimer; 00074 KToggleAction *showStatusBarAction; 00075 TQRect defaultWindowSize; 00076 TQPtrList<TQDockWindow> hiddenDockWindows; 00077 }; 00078 00079 TQPtrList<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 TQPtrListIterator<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(TQString::fromLatin1("Number")); 00109 config->writeEntry(TQString::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 TQPtrListIterator<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( TQt::WState_ForceHide ) ) { 00124 TQCloseEvent e; 00125 TQApplication::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 TQApplication::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( TQt::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( TQWidget* parent, const char *name, WFlags f ) 00168 : TQMainWindow( parent, name, f ), KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 ) 00169 { 00170 initKMainWindow(name, 0); 00171 } 00172 00173 KMainWindow::KMainWindow( int cflags, TQWidget* parent, const char *name, WFlags f ) 00174 : TQMainWindow( 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, TQT_SIGNAL(shutDown()), this, TQT_SLOT(shuttingDown())); 00187 if( !memberList ) 00188 memberList = new TQPtrList<KMainWindow>; 00189 00190 if ( !ksm ) 00191 ksm = ksmd.setObject(ksm, new KMWSessionManaged()); 00192 // set a unique object name. Required by session management. 00193 TQCString objname; 00194 TQCString 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[0] != '\0' && 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 TQWidgetList* list = kapp->topLevelWidgets(); 00216 TQWidgetListIt it( *list ); 00217 bool found = false; 00218 for( TQWidget* 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 TQSize minSize = minimumSize(); 00290 TQSize 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 TQMenuBar* mb = internalMenuBar(); 00318 delete mb; 00319 delete d->m_interface; 00320 delete d; 00321 memberList->remove( this ); 00322 } 00323 00324 KPopupMenu* KMainWindow::helpMenu( const TQString &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, TQT_SIGNAL( showAboutApplication() ), 00335 this, TQT_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, TQString::null, showWhatsThis ); 00345 connect( mHelpMenu, TQT_SIGNAL( showAboutApplication() ), 00346 this, TQT_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( TQString::fromLatin1("Number") ); 00360 int n = config->readNumEntry( TQString::fromLatin1("NumberOfWindows") , 1 ); 00361 return number >= 1 && number <= n; 00362 } 00363 00364 const TQString KMainWindow::classNameOfToplevel( int number ) 00365 { 00366 if ( !kapp->isRestored() ) 00367 return TQString::null; 00368 KConfig *config = kapp->sessionConfig(); 00369 if ( !config ) 00370 return TQString::null; 00371 TQString s; 00372 s.setNum( number ); 00373 s.prepend( TQString::fromLatin1("WindowProperties") ); 00374 config->setGroup( s ); 00375 if ( !config->hasKey( TQString::fromLatin1("ClassName") ) ) 00376 return TQString::null; 00377 else 00378 return config->readEntry( TQString::fromLatin1("ClassName") ); 00379 } 00380 00381 void KMainWindow::show() 00382 { 00383 TQMainWindow::show(); 00384 00385 for ( TQPtrListIterator<TQDockWindow> 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 TQObjectList *list = queryList( TQDOCKWINDOW_OBJECT_NAME_STRING ); 00398 for( TQObjectListIt it( *list ); it.current(); ++it ) { 00399 TQDockWindow *dw = (TQDockWindow*)it.current(); 00400 if ( dw->isTopLevel() && dw->isVisible() ) { 00401 d->hiddenDockWindows.append( dw ); 00402 dw->hide(); 00403 } 00404 } 00405 delete list; 00406 } 00407 00408 TQWidget::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, TQT_TQOBJECT(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, TQT_SIGNAL(newToolbarConfig()), TQT_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 TQString & xmlfile ) { 00446 setupGUI(TQSize(), options, xmlfile); 00447 } 00448 00449 void KMainWindow::setupGUI( TQSize defaultSize, int options, const TQString & xmlfile ) { 00450 if( options & Keys ){ 00451 KStdAction::keyBindings(guiFactory(), 00452 TQT_SLOT(configureShortcuts()), actionCollection()); 00453 } 00454 00455 if( (options & StatusBar) && internalStatusBar() ){ 00456 createStandardStatusBarAction(); 00457 } 00458 00459 if( options & ToolBar ){ 00460 setStandardToolBarMenuEnabled( true ); 00461 KStdAction::configureToolbars(TQT_TQOBJECT(this), 00462 TQT_SLOT(configureToolbars() ), actionCollection()); 00463 } 00464 00465 if( options & Create ){ 00466 createGUI(xmlfile,false); 00467 } 00468 00469 if( options & Save ){ 00470 // setupGUI() is typically called in the constructor before show(), 00471 // so the default window size will be incorrect unless the application 00472 // hard coded the size which they should try not to do (i.e. use 00473 // size hints). 00474 if(initialGeometrySet()) 00475 { 00476 // Do nothing... 00477 } 00478 else if(defaultSize.isValid()) 00479 { 00480 resize(defaultSize); 00481 } 00482 else if(!isShown()) 00483 { 00484 adjustSize(); 00485 } 00486 setAutoSaveSettings(); 00487 } 00488 00489 } 00490 00491 void KMainWindow::createGUI( const TQString &xmlfile, bool _conserveMemory ) 00492 { 00493 // disabling the updates prevents unnecessary redraws 00494 setUpdatesEnabled( false ); 00495 00496 // just in case we are rebuilding, let's remove our old client 00497 guiFactory()->removeClient( this ); 00498 00499 // make sure to have an empty GUI 00500 TQMenuBar* mb = internalMenuBar(); 00501 if ( mb ) 00502 mb->clear(); 00503 00504 (void)toolBarIterator(); // make sure toolbarList is most-up-to-date 00505 toolbarList.setAutoDelete( true ); 00506 toolbarList.clear(); 00507 toolbarList.setAutoDelete( false ); 00508 00509 // don't build a help menu unless the user ask for it 00510 if (d->showHelpMenu) { 00511 // we always want a help menu 00512 if (!helpMenu2) 00513 helpMenu2 = new KHelpMenu(this, instance()->aboutData(), true, 00514 actionCollection()); 00515 } 00516 00517 // we always want to load in our global standards file 00518 setXMLFile( locate( "config", "ui/ui_standards.rc", instance() ) ); 00519 00520 // now, merge in our local xml file. if this is null, then that 00521 // means that we will be only using the global file 00522 if ( !xmlfile.isNull() ) { 00523 setXMLFile( xmlfile, true ); 00524 } else { 00525 TQString auto_file(instance()->instanceName() + "ui.rc"); 00526 setXMLFile( auto_file, true ); 00527 } 00528 00529 // make sure we don't have any state saved already 00530 setXMLGUIBuildDocument( TQDomDocument() ); 00531 00532 // do the actual GUI building 00533 guiFactory()->addClient( this ); 00534 00535 // try and get back *some* of our memory 00536 if ( _conserveMemory ) 00537 { 00538 // before freeing the memory allocated by the DOM document we also 00539 // free all memory allocated internally in the KXMLGUIFactory for 00540 // the menubar and the toolbars . This however implies that we 00541 // have to take care of deleting those widgets ourselves. For 00542 // destruction this is no problem, but when rebuilding we have 00543 // to take care of that (and we want to rebuild the GUI when 00544 // using stuff like the toolbar editor ). 00545 // In addition we have to take care of not removing containers 00546 // like popupmenus, defined in the XML document. 00547 // this code should probably go into a separate method in KMainWindow. 00548 // there's just one problem: I'm bad in finding names ;-) , so 00549 // I skipped this ;-) 00550 00551 TQDomDocument doc = domDocument(); 00552 00553 for( TQDomNode n = doc.documentElement().firstChild(); 00554 !n.isNull(); n = n.nextSibling()) 00555 { 00556 TQDomElement e = n.toElement(); 00557 00558 if ( e.tagName().lower() == "toolbar" ) 00559 factory_->resetContainer( e.attribute( "name" ) ); 00560 else if ( e.tagName().lower() == "menubar" ) 00561 factory_->resetContainer( e.tagName(), true ); 00562 } 00563 00564 conserveMemory(); 00565 } 00566 00567 setUpdatesEnabled( true ); 00568 updateGeometry(); 00569 } 00570 00571 void KMainWindow::setHelpMenuEnabled(bool showHelpMenu) 00572 { 00573 d->showHelpMenu = showHelpMenu; 00574 } 00575 00576 bool KMainWindow::isHelpMenuEnabled() 00577 { 00578 return d->showHelpMenu; 00579 } 00580 00581 void KMainWindow::setCaption( const TQString &caption ) 00582 { 00583 setPlainCaption( kapp->makeStdCaption(caption) ); 00584 } 00585 00586 void KMainWindow::setCaption( const TQString &caption, bool modified ) 00587 { 00588 setPlainCaption( kapp->makeStdCaption(caption, true, modified) ); 00589 } 00590 00591 void KMainWindow::setPlainCaption( const TQString &caption ) 00592 { 00593 TQMainWindow::setCaption( caption ); 00594 #if defined Q_WS_X11 00595 NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), 0 ); 00596 info.setName( caption.utf8().data() ); 00597 #endif 00598 } 00599 00600 void KMainWindow::appHelpActivated( void ) 00601 { 00602 if( !mHelpMenu ) { 00603 mHelpMenu = new KHelpMenu( this ); 00604 if ( !mHelpMenu ) 00605 return; 00606 } 00607 mHelpMenu->appHelpActivated(); 00608 } 00609 00610 void KMainWindow::slotStateChanged(const TQString &newstate) 00611 { 00612 stateChanged(newstate, KXMLGUIClient::StateNoReverse); 00613 } 00614 00615 /* 00616 * Get rid of this for KDE 4.0 00617 */ 00618 void KMainWindow::slotStateChanged(const TQString &newstate, 00619 KXMLGUIClient::ReverseStateChange reverse) 00620 { 00621 stateChanged(newstate, reverse); 00622 } 00623 00624 /* 00625 * Enable this for KDE 4.0 00626 */ 00627 // void KMainWindow::slotStateChanged(const TQString &newstate, 00628 // bool reverse) 00629 // { 00630 // stateChanged(newstate, 00631 // reverse ? KXMLGUIClient::StateReverse : KXMLGUIClient::StateNoReverse); 00632 // } 00633 00634 void KMainWindow::closeEvent ( TQCloseEvent *e ) 00635 { 00636 // Save settings if auto-save is enabled, and settings have changed 00637 if (d->settingsDirty && d->autoSaveSettings) 00638 saveAutoSaveSettings(); 00639 00640 if (queryClose()) { 00641 e->accept(); 00642 00643 int not_withdrawn = 0; 00644 TQPtrListIterator<KMainWindow> it(*KMainWindow::memberList); 00645 for (it.toFirst(); it.current(); ++it){ 00646 if ( !it.current()->isHidden() && it.current()->isTopLevel() && it.current() != this ) 00647 not_withdrawn++; 00648 } 00649 00650 if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted? 00651 if ( queryExit() && !kapp->sessionSaving() && !d->shuttingDown ) { // Yes, Quit app? 00652 // don't call queryExit() twice 00653 disconnect(kapp, TQT_SIGNAL(shutDown()), this, TQT_SLOT(shuttingDown())); 00654 d->shuttingDown = true; 00655 kapp->deref(); // ...and quit application. 00656 } else { 00657 // cancel closing, it's stupid to end up with no windows at all.... 00658 e->ignore(); 00659 } 00660 } 00661 } 00662 } 00663 00664 bool KMainWindow::queryExit() 00665 { 00666 return true; 00667 } 00668 00669 bool KMainWindow::queryClose() 00670 { 00671 return true; 00672 } 00673 00674 void KMainWindow::saveGlobalProperties( KConfig* ) 00675 { 00676 } 00677 00678 void KMainWindow::readGlobalProperties( KConfig* ) 00679 { 00680 } 00681 00682 #if defined(KDE_COMPAT) 00683 void KMainWindow::updateRects() 00684 { 00685 } 00686 #endif 00687 00688 void KMainWindow::showAboutApplication() 00689 { 00690 } 00691 00692 void KMainWindow::savePropertiesInternal( KConfig *config, int number ) 00693 { 00694 bool oldASWS = d->autoSaveWindowSize; 00695 d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size 00696 00697 TQString s; 00698 s.setNum(number); 00699 s.prepend(TQString::fromLatin1("WindowProperties")); 00700 config->setGroup(s); 00701 00702 // store objectName, className, Width and Height for later restoring 00703 // (Only useful for session management) 00704 config->writeEntry(TQString::fromLatin1("ObjectName"), name()); 00705 config->writeEntry(TQString::fromLatin1("ClassName"), className()); 00706 00707 saveMainWindowSettings(config); // Menubar, statusbar and Toolbar settings. 00708 00709 s.setNum(number); 00710 config->setGroup(s); 00711 saveProperties(config); 00712 00713 d->autoSaveWindowSize = oldASWS; 00714 } 00715 00716 void KMainWindow::saveMainWindowSettings(KConfig *config, const TQString &configGroup) 00717 { 00718 kdDebug(200) << "KMainWindow::saveMainWindowSettings " << configGroup << endl; 00719 TQString oldGroup; 00720 00721 if (!configGroup.isEmpty()) 00722 { 00723 oldGroup = config->group(); 00724 config->setGroup(configGroup); 00725 } 00726 00727 // Called by session management - or if we want to save the window size anyway 00728 if ( d->autoSaveWindowSize ) 00729 saveWindowSize( config ); 00730 00731 TQStatusBar* sb = internalStatusBar(); 00732 if (sb) { 00733 if(!config->hasDefault("StatusBar") && !sb->isHidden() ) 00734 config->revertToDefault("StatusBar"); 00735 else 00736 config->writeEntry("StatusBar", sb->isHidden() ? "Disabled" : "Enabled"); 00737 } 00738 00739 TQMenuBar* mb = internalMenuBar(); 00740 if (mb) { 00741 TQString MenuBar = TQString::fromLatin1("MenuBar"); 00742 if(!config->hasDefault("MenuBar") && !mb->isHidden() ) 00743 config->revertToDefault("MenuBar"); 00744 else 00745 config->writeEntry("MenuBar", mb->isHidden() ? "Disabled" : "Enabled"); 00746 } 00747 00748 int n = 1; // Toolbar counter. toolbars are counted from 1, 00749 KToolBar *toolbar = 0; 00750 TQPtrListIterator<KToolBar> it( toolBarIterator() ); 00751 while ( ( toolbar = it.current() ) ) { 00752 ++it; 00753 TQString group; 00754 if (!configGroup.isEmpty()) 00755 { 00756 // Give a number to the toolbar, but prefer a name if there is one, 00757 // because there's no real guarantee on the ordering of toolbars 00758 group = (!::qstrcmp(toolbar->name(), "unnamed") ? TQString::number(n) : TQString(" ")+toolbar->name()); 00759 group.prepend(" Toolbar"); 00760 group.prepend(configGroup); 00761 } 00762 toolbar->saveSettings(config, group); 00763 n++; 00764 } 00765 if (!configGroup.isEmpty()) 00766 config->setGroup(oldGroup); 00767 } 00768 00769 void KMainWindow::setStandardToolBarMenuEnabled( bool enable ) 00770 { 00771 if ( enable ) { 00772 if ( d->toolBarHandler ) 00773 return; 00774 00775 d->toolBarHandler = new KDEPrivate::ToolBarHandler( this ); 00776 00777 if ( factory() ) 00778 factory()->addClient( d->toolBarHandler ); 00779 } else { 00780 if ( !d->toolBarHandler ) 00781 return; 00782 00783 if ( factory() ) 00784 factory()->removeClient( d->toolBarHandler ); 00785 00786 delete d->toolBarHandler; 00787 d->toolBarHandler = 0; 00788 } 00789 } 00790 00791 bool KMainWindow::isStandardToolBarMenuEnabled() const 00792 { 00793 return ( d->toolBarHandler ); 00794 } 00795 00796 void KMainWindow::createStandardStatusBarAction(){ 00797 if(!d->showStatusBarAction){ 00798 d->showStatusBarAction = KStdAction::showStatusbar(TQT_TQOBJECT(this), TQT_SLOT(setSettingsDirty()), actionCollection()); 00799 KStatusBar *sb = statusBar(); // Creates statusbar if it doesn't exist already. 00800 connect(d->showStatusBarAction, TQT_SIGNAL(toggled(bool)), sb, TQT_SLOT(setShown(bool))); 00801 d->showStatusBarAction->setChecked(sb->isHidden()); 00802 } 00803 } 00804 00805 bool KMainWindow::readPropertiesInternal( KConfig *config, int number ) 00806 { 00807 if ( number == 1 ) 00808 readGlobalProperties( config ); 00809 00810 // in order they are in toolbar list 00811 TQString s; 00812 s.setNum(number); 00813 s.prepend(TQString::fromLatin1("WindowProperties")); 00814 00815 config->setGroup(s); 00816 00817 // restore the object name (window role) 00818 if ( config->hasKey(TQString::fromLatin1("ObjectName" )) ) 00819 setName( config->readEntry(TQString::fromLatin1("ObjectName")).latin1()); // latin1 is right here 00820 00821 applyMainWindowSettings(config); // Menubar, statusbar and toolbar settings. 00822 00823 s.setNum(number); 00824 config->setGroup(s); 00825 readProperties(config); 00826 return true; 00827 } 00828 00829 void KMainWindow::applyMainWindowSettings(KConfig *config, const TQString &configGroup) 00830 { 00831 return applyMainWindowSettings(config,configGroup,false); 00832 } 00833 00834 void KMainWindow::applyMainWindowSettings(KConfig *config, const TQString &configGroup,bool force) 00835 { 00836 kdDebug(200) << "KMainWindow::applyMainWindowSettings" << endl; 00837 00838 KConfigGroupSaver saver( config, configGroup.isEmpty() ? config->group() : configGroup ); 00839 00840 restoreWindowSize(config); 00841 00842 TQStatusBar* sb = internalStatusBar(); 00843 if (sb) { 00844 TQString entry = config->readEntry("StatusBar", "Enabled"); 00845 if ( entry == "Disabled" ) 00846 sb->hide(); 00847 else 00848 sb->show(); 00849 if(d->showStatusBarAction) 00850 d->showStatusBarAction->setChecked(!sb->isHidden()); 00851 } 00852 00853 TQMenuBar* mb = internalMenuBar(); 00854 if (mb) { 00855 TQString entry = config->readEntry ("MenuBar", "Enabled"); 00856 if ( entry == "Disabled" ) 00857 mb->hide(); 00858 else 00859 mb->show(); 00860 } 00861 00862 int n = 1; // Toolbar counter. toolbars are counted from 1, 00863 KToolBar *toolbar; 00864 TQPtrListIterator<KToolBar> it( toolBarIterator() ); // must use own iterator 00865 00866 for ( ; it.current(); ++it) { 00867 toolbar= it.current(); 00868 TQString group; 00869 if (!configGroup.isEmpty()) 00870 { 00871 // Give a number to the toolbar, but prefer a name if there is one, 00872 // because there's no real guarantee on the ordering of toolbars 00873 group = (!::qstrcmp(toolbar->name(), "unnamed") ? TQString::number(n) : TQString(" ")+toolbar->name()); 00874 group.prepend(" Toolbar"); 00875 group.prepend(configGroup); 00876 } 00877 toolbar->applySettings(config, group, force); 00878 n++; 00879 } 00880 00881 finalizeGUI( true ); 00882 } 00883 00884 void KMainWindow::finalizeGUI( bool force ) 00885 { 00886 //kdDebug(200) << "KMainWindow::finalizeGUI force=" << force << endl; 00887 // The whole reason for this is that moveToolBar relies on the indexes 00888 // of the other toolbars, so in theory it should be called only once per 00889 // toolbar, but in increasing order of indexes. 00890 // Since we can't do that immediately, we move them, and _then_ 00891 // we call positionYourself again for each of them, but this time 00892 // the toolbariterator should give them in the proper order. 00893 // Both the XMLGUI and applySettings call this, hence "force" for the latter. 00894 TQPtrListIterator<KToolBar> it( toolBarIterator() ); 00895 for ( ; it.current() ; ++it ) { 00896 it.current()->positionYourself( force ); 00897 } 00898 00899 d->settingsDirty = false; 00900 } 00901 00902 void KMainWindow::saveWindowSize( KConfig * config ) const 00903 { 00904 int scnum = TQApplication::desktop()->screenNumber(parentWidget()); 00905 TQRect desk = TQApplication::desktop()->screenGeometry(scnum); 00906 int w, h; 00907 #if defined Q_WS_X11 00908 // save maximalization as desktop size + 1 in that direction 00909 KWin::WindowInfo info = KWin::windowInfo( winId(), NET::WMState ); 00910 w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width(); 00911 h = info.state() & NET::MaxVert ? desk.height() + 1 : height(); 00912 #else 00913 if (isMaximized()) { 00914 w = desk.width() + 1; 00915 h = desk.height() + 1; 00916 } 00917 //TODO: add "Maximized" property instead "+1" hack 00918 #endif 00919 TQRect size( desk.width(), w, desk.height(), h ); 00920 bool defaultSize = (size == d->defaultWindowSize); 00921 TQString widthString = TQString::fromLatin1("Width %1").arg(desk.width()); 00922 TQString heightString = TQString::fromLatin1("Height %1").arg(desk.height()); 00923 if (!config->hasDefault(widthString) && defaultSize) 00924 config->revertToDefault(widthString); 00925 else 00926 config->writeEntry(widthString, w ); 00927 00928 if (!config->hasDefault(heightString) && defaultSize) 00929 config->revertToDefault(heightString); 00930 else 00931 config->writeEntry(heightString, h ); 00932 } 00933 00934 void KMainWindow::restoreWindowSize( KConfig * config ) 00935 { 00936 if (d->care_about_geometry) { 00937 parseGeometry(true); 00938 } else { 00939 // restore the size 00940 int scnum = TQApplication::desktop()->screenNumber(parentWidget()); 00941 TQRect desk = TQApplication::desktop()->screenGeometry(scnum); 00942 if ( d->defaultWindowSize.isNull() ) // only once 00943 d->defaultWindowSize = TQRect(desk.width(), width(), desk.height(), height()); // store default values 00944 TQSize size( config->readNumEntry( TQString::fromLatin1("Width %1").arg(desk.width()), 0 ), 00945 config->readNumEntry( TQString::fromLatin1("Height %1").arg(desk.height()), 0 ) ); 00946 if (size.isEmpty()) { 00947 // try the KDE 2.0 way 00948 size = TQSize( config->readNumEntry( TQString::fromLatin1("Width"), 0 ), 00949 config->readNumEntry( TQString::fromLatin1("Height"), 0 ) ); 00950 if (!size.isEmpty()) { 00951 // make sure the other resolutions don't get old settings 00952 config->writeEntry( TQString::fromLatin1("Width"), 0 ); 00953 config->writeEntry( TQString::fromLatin1("Height"), 0 ); 00954 } 00955 } 00956 if ( !size.isEmpty() ) { 00957 #ifdef Q_WS_X11 00958 int state = 0; 00959 if (size.width() > desk.width()) { 00960 state = state | NET::MaxHoriz; 00961 } 00962 if (size.height() > desk.height()) { 00963 state = state | NET::MaxVert; 00964 } 00965 00966 if (( state & NET::Max ) == NET::Max ) { 00967 resize( desk.width(), desk.height()); 00968 } 00969 else if(( state & NET::MaxHoriz ) == NET::MaxHoriz ) { 00970 resize( width(), size.height()); 00971 } 00972 else if(( state & NET::MaxVert ) == NET::MaxVert ) { 00973 resize( size.width(), height()); 00974 } 00975 else { 00976 resize( size ); 00977 } 00978 // TQWidget::showMaximized() is both insufficient and broken 00979 KWin::setState( winId(), state ); 00980 #else 00981 if (size.width() > desk.width() || size.height() > desk.height()) 00982 setWindowState( WindowMaximized ); 00983 else 00984 resize( size ); 00985 #endif 00986 } 00987 } 00988 } 00989 00990 bool KMainWindow::initialGeometrySet() const 00991 { 00992 return d->care_about_geometry; 00993 } 00994 00995 void KMainWindow::ignoreInitialGeometry() 00996 { 00997 d->care_about_geometry = false; 00998 } 00999 01000 void KMainWindow::setSettingsDirty() 01001 { 01002 //kdDebug(200) << "KMainWindow::setSettingsDirty" << endl; 01003 d->settingsDirty = true; 01004 if ( d->autoSaveSettings ) 01005 { 01006 // Use a timer to save "immediately" user-wise, but not too immediately 01007 // (to compress calls and save only once, in case of multiple changes) 01008 if ( !d->settingsTimer ) 01009 { 01010 d->settingsTimer = new TQTimer( this ); 01011 connect( d->settingsTimer, TQT_SIGNAL( timeout() ), TQT_SLOT( saveAutoSaveSettings() ) ); 01012 } 01013 d->settingsTimer->start( 500, true ); 01014 } 01015 } 01016 01017 bool KMainWindow::settingsDirty() const 01018 { 01019 return d->settingsDirty; 01020 } 01021 01022 TQString KMainWindow::settingsGroup() const 01023 { 01024 return d->autoSaveGroup; 01025 } 01026 01027 void KMainWindow::setAutoSaveSettings( const TQString & groupName, bool saveWindowSize ) 01028 { 01029 d->autoSaveSettings = true; 01030 d->autoSaveGroup = groupName; 01031 d->autoSaveWindowSize = saveWindowSize; 01032 // Get notified when the user moves a toolbar around 01033 disconnect( this, TQT_SIGNAL( dockWindowPositionChanged( TQDockWindow * ) ), 01034 this, TQT_SLOT( setSettingsDirty() ) ); 01035 connect( this, TQT_SIGNAL( dockWindowPositionChanged( TQDockWindow * ) ), 01036 this, TQT_SLOT( setSettingsDirty() ) ); 01037 01038 // Now read the previously saved settings 01039 applyMainWindowSettings( KGlobal::config(), groupName ); 01040 } 01041 01042 void KMainWindow::resetAutoSaveSettings() 01043 { 01044 d->autoSaveSettings = false; 01045 if ( d->settingsTimer ) 01046 d->settingsTimer->stop(); 01047 } 01048 01049 bool KMainWindow::autoSaveSettings() const 01050 { 01051 return d->autoSaveSettings; 01052 } 01053 01054 TQString KMainWindow::autoSaveGroup() const 01055 { 01056 return d->autoSaveGroup; 01057 } 01058 01059 void KMainWindow::saveAutoSaveSettings() 01060 { 01061 Q_ASSERT( d->autoSaveSettings ); 01062 //kdDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings" << endl; 01063 saveMainWindowSettings( KGlobal::config(), d->autoSaveGroup ); 01064 KGlobal::config()->sync(); 01065 d->settingsDirty = false; 01066 if ( d->settingsTimer ) 01067 d->settingsTimer->stop(); 01068 } 01069 01070 void KMainWindow::resizeEvent( TQResizeEvent * ) 01071 { 01072 if ( d->autoSaveWindowSize ) 01073 setSettingsDirty(); 01074 } 01075 01076 bool KMainWindow::hasMenuBar() 01077 { 01078 return (internalMenuBar()); 01079 } 01080 01081 KMenuBar *KMainWindow::menuBar() 01082 { 01083 KMenuBar * mb = internalMenuBar(); 01084 if ( !mb ) { 01085 mb = new KMenuBar( this ); 01086 // trigger a re-layout and trigger a call to the private 01087 // setMenuBar method. 01088 TQMainWindow::menuBar(); 01089 } 01090 return mb; 01091 } 01092 01093 KStatusBar *KMainWindow::statusBar() 01094 { 01095 KStatusBar * sb = internalStatusBar(); 01096 if ( !sb ) { 01097 sb = new KStatusBar( this ); 01098 // trigger a re-layout and trigger a call to the private 01099 // setStatusBar method. 01100 TQMainWindow::statusBar(); 01101 } 01102 return sb; 01103 } 01104 01105 void KMainWindow::shuttingDown() 01106 { 01107 // Needed for Qt <= 3.0.3 at least to prevent reentrancy 01108 // when queryExit() shows a dialog. Check before removing! 01109 static bool reentrancy_protection = false; 01110 if (!reentrancy_protection) 01111 { 01112 reentrancy_protection = true; 01113 // call the virtual queryExit 01114 queryExit(); 01115 reentrancy_protection = false; 01116 } 01117 01118 } 01119 01120 KMenuBar *KMainWindow::internalMenuBar() 01121 { 01122 TQObjectList *l = queryList( "KMenuBar", 0, false, false ); 01123 if ( !l || !l->first() ) { 01124 delete l; 01125 return 0; 01126 } 01127 01128 KMenuBar *m = (KMenuBar*)l->first(); 01129 delete l; 01130 return m; 01131 } 01132 01133 KStatusBar *KMainWindow::internalStatusBar() 01134 { 01135 TQObjectList *l = queryList( "KStatusBar", 0, false, false ); 01136 if ( !l || !l->first() ) { 01137 delete l; 01138 return 0; 01139 } 01140 01141 KStatusBar *s = (KStatusBar*)l->first(); 01142 delete l; 01143 return s; 01144 } 01145 01146 void KMainWindow::childEvent( TQChildEvent* e) 01147 { 01148 TQMainWindow::childEvent( e ); 01149 } 01150 01151 KToolBar *KMainWindow::toolBar( const char * name ) 01152 { 01153 if (!name) 01154 name = "mainToolBar"; 01155 KToolBar *tb = (KToolBar*)child( name, "KToolBar" ); 01156 if ( tb ) 01157 return tb; 01158 bool honor_mode = (!strcmp(name, "mainToolBar")); 01159 01160 if ( builderClient() ) 01161 return new KToolBar(this, name, honor_mode); // XMLGUI constructor 01162 else 01163 return new KToolBar(this, DockTop, false, name, honor_mode ); // non-XMLGUI 01164 } 01165 01166 TQPtrListIterator<KToolBar> KMainWindow::toolBarIterator() 01167 { 01168 toolbarList.clear(); 01169 TQPtrList<TQToolBar> lst; 01170 for ( int i = (int)TQMainWindow::DockUnmanaged; i <= (int)DockMinimized; ++i ) { 01171 lst = toolBars( (ToolBarDock)i ); 01172 for ( TQToolBar *tb = lst.first(); tb; tb = lst.next() ) { 01173 if ( !tb->inherits( "KToolBar" ) ) 01174 continue; 01175 toolbarList.append( (KToolBar*)tb ); 01176 } 01177 } 01178 return TQPtrListIterator<KToolBar>( toolbarList ); 01179 } 01180 01181 KAccel * KMainWindow::accel() 01182 { 01183 if ( !d->kaccel ) 01184 d->kaccel = new KAccel( this, "kmw-kaccel" ); 01185 return d->kaccel; 01186 } 01187 01188 void KMainWindow::paintEvent( TQPaintEvent * pe ) 01189 { 01190 TQMainWindow::paintEvent(pe); //Upcall to handle SH_MainWindow_SpaceBelowMenuBar rendering 01191 } 01192 01193 TQSize KMainWindow::sizeForCentralWidgetSize(TQSize size) 01194 { 01195 KToolBar *tb = (KToolBar*)child( "mainToolBar", "KToolBar" ); 01196 if (tb && !tb->isHidden()) { 01197 switch( tb->barPos() ) 01198 { 01199 case KToolBar::Top: 01200 case KToolBar::Bottom: 01201 size += TQSize(0, tb->sizeHint().height()); 01202 break; 01203 01204 case KToolBar::Left: 01205 case KToolBar::Right: 01206 size += TQSize(toolBar()->sizeHint().width(), 0); 01207 break; 01208 01209 case KToolBar::Flat: 01210 size += TQSize(0, 3+kapp->style().pixelMetric( TQStyle::PM_DockWindowHandleExtent )); 01211 break; 01212 01213 default: 01214 break; 01215 } 01216 } 01217 KMenuBar *mb = internalMenuBar(); 01218 if (mb && !mb->isHidden()) { 01219 size += TQSize(0,mb->heightForWidth(size.width())); 01220 if (style().styleHint(TQStyle::SH_MainWindow_SpaceBelowMenuBar, this)) 01221 size += TQSize( 0, dockWindowsMovable() ? 1 : 2); 01222 } 01223 TQStatusBar *sb = internalStatusBar(); 01224 if( sb && !sb->isHidden() ) 01225 size += TQSize(0, sb->sizeHint().height()); 01226 01227 return size; 01228 } 01229 01230 #if KDE_IS_VERSION( 3, 9, 0 ) 01231 #ifdef __GNUC__ 01232 #warning Remove, should be in Qt 01233 #endif 01234 #endif 01235 void KMainWindow::setIcon( const TQPixmap& p ) 01236 { 01237 TQMainWindow::setIcon( p ); 01238 #ifdef Q_WS_X11 01239 // Qt3 doesn't support _NET_WM_ICON, but KApplication::setTopWidget(), which 01240 // is used by KMainWindow, sets it 01241 KWin::setIcons( winId(), p, TQPixmap()); 01242 #endif 01243 } 01244 01245 TQPtrList<KMainWindow>* KMainWindow::getMemberList() { return memberList; } 01246 01247 // why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI; 01248 // DF: because they compile KDE much faster :) 01249 void KMainWindow::finalizeGUI( KXMLGUIClient *client ) 01250 { KXMLGUIBuilder::finalizeGUI( client ); } 01251 01252 void KMainWindow::virtual_hook( int id, void* data ) 01253 { KXMLGUIBuilder::virtual_hook( id, data ); 01254 KXMLGUIClient::virtual_hook( id, data ); } 01255 01256 01257 01258 #include "kmainwindow.moc" 01259