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