kdeui Library API Documentation

kmainwindow.cpp

00001  /* This file is part of the KDE libraries
00002      Copyright
00003      (C) 2000 Reginald Stadlbauer (reggie@kde.org)
00004      (C) 1997 Stephan Kulow (coolo@kde.org)
00005      (C) 1997-2000 Sven Radej (radej@kde.org)
00006      (C) 1997-2000 Matthias Ettrich (ettrich@kde.org)
00007      (C) 1999 Chris Schlaeger (cs@kde.org)
00008      (C) 2002 Joseph Wenninger (jowenn@kde.org)
00009 
00010      This library is free software; you can redistribute it and/or
00011      modify it under the terms of the GNU Library General Public
00012      License version 2 as published by the Free Software Foundation.
00013 
00014      This library is distributed in the hope that it will be useful,
00015      but WITHOUT ANY WARRANTY; without even the implied warranty of
00016      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017      Library General Public License for more details.
00018 
00019      You should have received a copy of the GNU Library General Public License
00020      along with this library; see the file COPYING.LIB.  If not, write to
00021      the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00022      Boston, MA 02111-1307, USA.
00023  */
00024 #include "config.h"
00025 
00026 #include "kmainwindow.h"
00027 #include "kmainwindowiface.h"
00028 #include "ktoolbarhandler.h"
00029 #include <qsessionmanager.h>
00030 #include <qobjectlist.h>
00031 #include <qstyle.h>
00032 #include <qlayout.h>
00033 #include <qwidgetlist.h>
00034 #include <qtimer.h>
00035 
00036 #include <kaccel.h>
00037 #include <kaction.h>
00038 #include <kapplication.h>
00039 #include <kconfig.h>
00040 #include <kdebug.h>
00041 #include <khelpmenu.h>
00042 #include <kmenubar.h>
00043 #include <kstatusbar.h>
00044 #include <kwin.h>
00045 #include <kedittoolbar.h>
00046 #include <kmainwindow.h>
00047 
00048 #include <klocale.h>
00049 #include <kstandarddirs.h>
00050 #include <kstaticdeleter.h>
00051 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00052 #include <netwm.h>
00053 #endif
00054 
00055 #include <stdlib.h>
00056 #include <ctype.h>
00057 #include <assert.h>
00058 
00059 class KMainWindowPrivate {
00060 public:
00061     bool showHelpMenu:1;
00062 
00063     bool autoSaveSettings:1;
00064     bool settingsDirty:1;
00065     bool autoSaveWindowSize:1;
00066     bool care_about_geometry:1;
00067     bool shuttingDown:1;
00068     QString autoSaveGroup;
00069     KAccel * kaccel;
00070     KMainWindowInterface *m_interface;
00071     KDEPrivate::ToolBarHandler *toolBarHandler;
00072     QTimer* settingsTimer;
00073     KToggleAction *showStatusBarAction;
00074     QRect defaultWindowSize;
00075     QPtrList<QDockWindow> hiddenDockWindows;
00076 };
00077 
00078 QPtrList<KMainWindow>* KMainWindow::memberList = 0L;
00079 static bool no_query_exit = false;
00080 static KMWSessionManaged* ksm = 0;
00081 static KStaticDeleter<KMWSessionManaged> ksmd;
00082 
00083 class KMWSessionManaged : public KSessionManaged
00084 {
00085 public:
00086     KMWSessionManaged()
00087     {
00088     };
00089     ~KMWSessionManaged()
00090     {
00091     }
00092     bool saveState( QSessionManager& )
00093     {
00094         KConfig* config = KApplication::kApplication()->sessionConfig();
00095         if ( KMainWindow::memberList->first() ){
00096             // According to Jochen Wilhelmy <digisnap@cs.tu-berlin.de>, this
00097             // hook is useful for better document orientation
00098             KMainWindow::memberList->first()->saveGlobalProperties(config);
00099         }
00100 
00101         QPtrListIterator<KMainWindow> it(*KMainWindow::memberList);
00102         int n = 0;
00103         for (it.toFirst(); it.current(); ++it){
00104             n++;
00105             it.current()->savePropertiesInternal(config, n);
00106         }
00107         config->setGroup(QString::fromLatin1("Number"));
00108         config->writeEntry(QString::fromLatin1("NumberOfWindows"), n );
00109         return true;
00110     }
00111 
00112     bool commitData( QSessionManager& sm )
00113     {
00114         // not really a fast method but the only compatible one
00115         if ( sm.allowsInteraction() ) {
00116             bool canceled = false;
00117             QPtrListIterator<KMainWindow> it(*KMainWindow::memberList);
00118             ::no_query_exit = true;
00119             for (it.toFirst(); it.current() && !canceled;){
00120                 KMainWindow *window = *it;
00121                 ++it; // Update now, the current window might get deleted
00122                 if ( !window->testWState( Qt::WState_ForceHide ) ) {
00123                     QCloseEvent e;
00124                     QApplication::sendEvent( window, &e );
00125                     canceled = !e.isAccepted();
00126             /* Don't even think_about deleting widgets with
00127              Qt::WDestructiveClose flag set at this point. We
00128              are faking a close event, but we are *not*_
00129              closing the window. The purpose of the faked
00130              close event is to prepare the application so it
00131              can safely be quit without the user losing data
00132              (possibly showing a message box "do you want to
00133              save this or that?"). It is possible that the
00134              session manager quits the application later
00135              (emitting QApplication::aboutToQuit() when this
00136              happens), but it is also possible that the user
00137              cancels the shutdown, so the application will
00138              continue to run.
00139              */
00140                 }
00141             }
00142             ::no_query_exit = false;
00143             if (canceled)
00144                return false;
00145 
00146             KMainWindow* last = 0;
00147             for (it.toFirst(); it.current() && !canceled; ++it){
00148                 KMainWindow *window = *it;
00149                 if ( !window->testWState( Qt::WState_ForceHide ) ) {
00150                     last = window;
00151                 }
00152             }
00153             if ( last )
00154                 return last->queryExit();
00155             // else
00156             return true;
00157         }
00158 
00159         // the user wants it, the user gets it
00160         return true;
00161     }
00162 };
00163 
00164 static bool being_first = true;
00165 
00166 KMainWindow::KMainWindow( QWidget* parent, const char *name, WFlags f )
00167     : QMainWindow( parent, name, f ), KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 )
00168 {
00169     initKMainWindow(name, 0);
00170 }
00171 
00172 KMainWindow::KMainWindow( int cflags, QWidget* parent, const char *name, WFlags f )
00173     : QMainWindow( parent, name, f ), KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 )
00174 {
00175     initKMainWindow(name, cflags);
00176 }
00177 
00178 void KMainWindow::initKMainWindow(const char *name, int cflags)
00179 {
00180     setDockMenuEnabled( false );
00181     mHelpMenu = 0;
00182     kapp->setTopWidget( this );
00183     actionCollection()->setWidget( this );
00184     connect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown()));
00185     if( !memberList )
00186         memberList = new QPtrList<KMainWindow>;
00187 
00188     if ( !ksm )
00189         ksm = ksmd.setObject(ksm, new KMWSessionManaged());
00190     // set a unique object name. Required by session management.
00191     QCString objname;
00192     QCString s;
00193     int unusedNumber;
00194     if ( !name )
00195         { // no name given
00196         objname = kapp->instanceName() + "-mainwindow#";
00197         s = objname + '1'; // start adding number immediately
00198         unusedNumber = 1;
00199         }
00200     else if( name[ strlen( name ) - 1 ] == '#' )
00201         { // trailing # - always add a number
00202         objname = name;
00203         s = objname + '1'; // start adding number immediately
00204         unusedNumber = 1;
00205         }
00206     else
00207         {
00208         objname = name;
00209         s = objname;
00210         unusedNumber = 0; // add numbers only when needed
00211         }
00212     for(;;) {
00213         QWidgetList* list = kapp->topLevelWidgets();
00214         QWidgetListIt it( *list );
00215         bool found = false;
00216         for( QWidget* w = it.current();
00217              w != NULL;
00218              ++it, w = it.current())
00219             if( w != this && w->name() == s )
00220                 {
00221                 found = true;
00222                 break;
00223                 }
00224         delete list;
00225         if( !found )
00226             break;
00227         s.setNum( ++unusedNumber );
00228         s = objname + s;
00229     }
00230     setName( s );
00231 
00232     memberList->append( this );
00233 
00234     d = new KMainWindowPrivate;
00235     d->showHelpMenu = true;
00236     d->settingsDirty = false;
00237     d->autoSaveSettings = false;
00238     d->autoSaveWindowSize = true; // for compatibility
00239     d->kaccel = actionCollection()->kaccel();
00240     d->toolBarHandler = 0;
00241     d->settingsTimer = 0;
00242     d->showStatusBarAction = NULL;
00243     d->shuttingDown = false;
00244     if ((d->care_about_geometry = being_first)) {
00245         being_first = false;
00246         if ( kapp->geometryArgument().isNull() ) // if there is no geometry, it doesn't mater
00247             d->care_about_geometry = false;
00248         else
00249             parseGeometry(false);
00250     }
00251 
00252     setCaption( kapp->caption() );
00253     if ( cflags & NoDCOPObject)
00254         d->m_interface = 0;
00255     else
00256         d->m_interface = new KMainWindowInterface(this);
00257 
00258     if (!kapp->authorize("movable_toolbars"))
00259         setDockWindowsMovable(false);
00260 }
00261 
00262 KAction *KMainWindow::toolBarMenuAction()
00263 {
00264     if ( !d->toolBarHandler )
00265     return 0;
00266 
00267     return d->toolBarHandler->toolBarMenuAction();
00268 }
00269 
00270 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 int KMainWindow::configureToolbars()
00425 {
00426     saveMainWindowSettings(KGlobal::config());
00427     KEditToolbar dlg(actionCollection(), xmlFile(), true, this);
00428     connect(&dlg, SIGNAL(newToolbarConfig()), SLOT(saveNewToolbarConfig()));
00429     return dlg.exec();
00430 }
00431 
00432 void KMainWindow::saveNewToolbarConfig()
00433 {
00434     createGUI(xmlFile());
00435     applyMainWindowSettings( KGlobal::config() );
00436 }
00437 
00438 void KMainWindow::setupGUI( int options, const QString & xmlfile ) {
00439     if( options & Keys ){
00440         KStdAction::keyBindings(guiFactory(),
00441                     SLOT(configureShortcuts()), actionCollection());
00442     }
00443 
00444     if( (options & StatusBar) && internalStatusBar() ){
00445         createStandardStatusBarAction();
00446     }
00447 
00448     if( options & ToolBar ){
00449         setStandardToolBarMenuEnabled( true );
00450         KStdAction::configureToolbars(this,
00451                       SLOT(configureToolbars() ), actionCollection());
00452     }
00453 
00454     if( options & Create ){
00455         createGUI(xmlfile);
00456     }
00457 
00458     if( options & Save ){
00459         // setupGUI() is typically called in the constructor before show(),
00460         // so the default window size will be incorrect unless the application
00461         // hard coded the size which they should try not to do (i.e. use 
00462         // size hints).
00463         if(!isShown())
00464           adjustSize();
00465         setAutoSaveSettings();
00466     }
00467 
00468 }
00469 
00470 void KMainWindow::createGUI( const QString &xmlfile, bool _conserveMemory )
00471 {
00472     // disabling the updates prevents unnecessary redraws
00473     setUpdatesEnabled( false );
00474 
00475     // just in case we are rebuilding, let's remove our old client
00476     guiFactory()->removeClient( this );
00477 
00478     // make sure to have an empty GUI
00479     QMenuBar* mb = internalMenuBar();
00480     if ( mb )
00481         mb->clear();
00482 
00483     (void)toolBarIterator(); // make sure toolbarList is most-up-to-date
00484     toolbarList.setAutoDelete( true );
00485     toolbarList.clear();
00486     toolbarList.setAutoDelete( false );
00487 
00488     // don't build a help menu unless the user ask for it
00489     if (d->showHelpMenu) {
00490         // we always want a help menu
00491         if (helpMenu2 == 0)
00492             helpMenu2 = new KHelpMenu(this, instance()->aboutData(), true,
00493                                       actionCollection());
00494     }
00495 
00496     // we always want to load in our global standards file
00497     setXMLFile( locate( "config", "ui/ui_standards.rc", instance() ) );
00498 
00499     // now, merge in our local xml file.  if this is null, then that
00500     // means that we will be only using the global file
00501     if ( !xmlfile.isNull() ) {
00502         setXMLFile( xmlfile, true );
00503     } else {
00504         QString auto_file(instance()->instanceName() + "ui.rc");
00505         setXMLFile( auto_file, true );
00506     }
00507 
00508     // make sure we don't have any state saved already
00509     setXMLGUIBuildDocument( QDomDocument() );
00510 
00511     // do the actual GUI building
00512     guiFactory()->addClient( this );
00513 
00514     // try and get back *some* of our memory
00515     if ( _conserveMemory )
00516     {
00517       // before freeing the memory allocated by the DOM document we also
00518       // free all memory allocated internally in the KXMLGUIFactory for
00519       // the menubar and the toolbars . This however implies that we
00520       // have to take care of deleting those widgets ourselves. For
00521       // destruction this is no problem, but when rebuilding we have
00522       // to take care of that (and we want to rebuild the GUI when
00523       // using stuff like the toolbar editor ).
00524       // In addition we have to take care of not removing containers
00525       // like popupmenus, defined in the XML document.
00526       // this code should probably go into a separate method in KMainWindow.
00527       // there's just one problem: I'm bad in finding names ;-) , so
00528       // I skipped this ;-)
00529 
00530       QDomDocument doc = domDocument();
00531 
00532       for( QDomNode n = doc.documentElement().firstChild();
00533            !n.isNull(); n = n.nextSibling())
00534       {
00535           QDomElement e = n.toElement();
00536 
00537           if ( e.tagName().lower() == "toolbar" )
00538               factory_->resetContainer( e.attribute( "name" ) );
00539           else if ( e.tagName().lower() == "menubar" )
00540               factory_->resetContainer( e.tagName(), true );
00541       }
00542 
00543       conserveMemory();
00544     }
00545 
00546     setUpdatesEnabled( true );
00547     updateGeometry();
00548 }
00549 
00550 void KMainWindow::setHelpMenuEnabled(bool showHelpMenu)
00551 {
00552     d->showHelpMenu = showHelpMenu;
00553 }
00554 
00555 bool KMainWindow::isHelpMenuEnabled()
00556 {
00557     return d->showHelpMenu;
00558 }
00559 
00560 void KMainWindow::setCaption( const QString &caption )
00561 {
00562     setPlainCaption( kapp->makeStdCaption(caption) );
00563 }
00564 
00565 void KMainWindow::setCaption( const QString &caption, bool modified )
00566 {
00567     setPlainCaption( kapp->makeStdCaption(caption, true, modified) );
00568 }
00569 
00570 void KMainWindow::setPlainCaption( const QString &caption )
00571 {
00572     QMainWindow::setCaption( caption );
00573 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00574 //#ifndef Q_WS_QWS
00575     NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), 0 );
00576     info.setName( caption.utf8().data() );
00577 #endif
00578 }
00579 
00580 void KMainWindow::appHelpActivated( void )
00581 {
00582     if( mHelpMenu == 0 ) {
00583         mHelpMenu = new KHelpMenu( this );
00584         if ( mHelpMenu == 0 )
00585             return;
00586     }
00587     mHelpMenu->appHelpActivated();
00588 }
00589 
00590 void KMainWindow::slotStateChanged(const QString &newstate)
00591 {
00592   stateChanged(newstate, KXMLGUIClient::StateNoReverse);
00593 }
00594 
00595 /*
00596  * Get rid of this for KDE 4.0
00597  */
00598 void KMainWindow::slotStateChanged(const QString &newstate,
00599                                    KXMLGUIClient::ReverseStateChange reverse)
00600 {
00601   stateChanged(newstate, reverse);
00602 }
00603 
00604 /*
00605  * Enable this for KDE 4.0
00606  */
00607 // void KMainWindow::slotStateChanged(const QString &newstate,
00608 //                                    bool reverse)
00609 // {
00610 //   stateChanged(newstate,
00611 //                reverse ? KXMLGUIClient::StateReverse : KXMLGUIClient::StateNoReverse);
00612 // }
00613 
00614 void KMainWindow::closeEvent ( QCloseEvent *e )
00615 {
00616     // Save settings if auto-save is enabled, and settings have changed
00617     if (d->settingsDirty && d->autoSaveSettings)
00618         saveAutoSaveSettings();
00619 
00620     if (queryClose()) {
00621         e->accept();
00622 
00623         int not_withdrawn = 0;
00624         QPtrListIterator<KMainWindow> it(*KMainWindow::memberList);
00625         for (it.toFirst(); it.current(); ++it){
00626             if ( !it.current()->isHidden() && it.current()->isTopLevel() && it.current() != this )
00627                 not_withdrawn++;
00628         }
00629 
00630         if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted?
00631             if ( queryExit() && !kapp->sessionSaving() && !d->shuttingDown ) { // Yes, Quit app?
00632                 // don't call queryExit() twice
00633                 disconnect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown()));
00634                 d->shuttingDown = true;
00635                 kapp->deref();             // ...and quit application.
00636             }  else {
00637                 // cancel closing, it's stupid to end up with no windows at all....
00638                 e->ignore();
00639             }
00640         }
00641     }
00642 }
00643 
00644 bool KMainWindow::queryExit()
00645 {
00646     return true;
00647 }
00648 
00649 bool KMainWindow::queryClose()
00650 {
00651     return true;
00652 }
00653 
00654 void KMainWindow::saveGlobalProperties( KConfig*  )
00655 {
00656 }
00657 
00658 void KMainWindow::readGlobalProperties( KConfig*  )
00659 {
00660 }
00661 
00662 #if defined(KDE_COMPAT)
00663 void KMainWindow::updateRects()
00664 {
00665 }
00666 #endif
00667 
00668 void KMainWindow::showAboutApplication()
00669 {
00670 }
00671 
00672 void KMainWindow::savePropertiesInternal( KConfig *config, int number )
00673 {
00674     bool oldASWS = d->autoSaveWindowSize;
00675     d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size
00676 
00677     QString s;
00678     s.setNum(number);
00679     s.prepend(QString::fromLatin1("WindowProperties"));
00680     config->setGroup(s);
00681 
00682     // store objectName, className, Width and Height  for later restoring
00683     // (Only useful for session management)
00684     config->writeEntry(QString::fromLatin1("ObjectName"), name());
00685     config->writeEntry(QString::fromLatin1("ClassName"), className());
00686 
00687     saveMainWindowSettings(config); // Menubar, statusbar and Toolbar settings.
00688 
00689     s.setNum(number);
00690     config->setGroup(s);
00691     saveProperties(config);
00692 
00693     d->autoSaveWindowSize = oldASWS;
00694 }
00695 
00696 void KMainWindow::saveMainWindowSettings(KConfig *config, const QString &configGroup)
00697 {
00698     kdDebug(200) << "KMainWindow::saveMainWindowSettings " << configGroup << endl;
00699     QString oldGroup;
00700 
00701     if (!configGroup.isEmpty())
00702     {
00703        oldGroup = config->group();
00704        config->setGroup(configGroup);
00705     }
00706 
00707     // Called by session management - or if we want to save the window size anyway
00708     if ( d->autoSaveWindowSize )
00709         saveWindowSize( config );
00710 
00711     QStatusBar* sb = internalStatusBar();
00712     if (sb) {
00713        if(!config->hasDefault("StatusBar") && !sb->isHidden() )
00714            config->revertToDefault("StatusBar");
00715        else
00716            config->writeEntry("StatusBar", sb->isHidden() ? "Disabled" : "Enabled");
00717     }
00718 
00719     QMenuBar* mb = internalMenuBar();
00720     if (mb) {
00721        QString MenuBar = QString::fromLatin1("MenuBar");
00722        if(!config->hasDefault("MenuBar") && !mb->isHidden() )
00723            config->revertToDefault("MenuBar");
00724        else
00725            config->writeEntry("MenuBar", mb->isHidden() ? "Disabled" : "Enabled");
00726     }
00727 
00728     int n = 1; // Toolbar counter. toolbars are counted from 1,
00729     KToolBar *toolbar = 0;
00730     QPtrListIterator<KToolBar> it( toolBarIterator() );
00731     while ( ( toolbar = it.current() ) ) {
00732         ++it;
00733         QString group;
00734         if (!configGroup.isEmpty())
00735         {
00736            // Give a number to the toolbar, but prefer a name if there is one,
00737            // because there's no real guarantee on the ordering of toolbars
00738            group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name());
00739            group.prepend(" Toolbar");
00740            group.prepend(configGroup);
00741         }
00742         toolbar->saveSettings(config, group);
00743         n++;
00744     }
00745     if (!configGroup.isEmpty())
00746        config->setGroup(oldGroup);
00747 }
00748 
00749 void KMainWindow::setStandardToolBarMenuEnabled( bool enable )
00750 {
00751     if ( enable ) {
00752         if ( d->toolBarHandler )
00753             return;
00754 
00755     d->toolBarHandler = new KDEPrivate::ToolBarHandler( this );
00756 
00757     if ( factory() )
00758         factory()->addClient( d->toolBarHandler );
00759     } else {
00760         if ( !d->toolBarHandler )
00761             return;
00762 
00763         if ( factory() )
00764             factory()->removeClient( d->toolBarHandler );
00765 
00766         delete d->toolBarHandler;
00767         d->toolBarHandler = 0;
00768     }
00769 }
00770 
00771 bool KMainWindow::isStandardToolBarMenuEnabled() const
00772 {
00773     return ( d->toolBarHandler != 0 );
00774 }
00775 
00776 void KMainWindow::createStandardStatusBarAction(){
00777   if(!d->showStatusBarAction){
00778     d->showStatusBarAction = KStdAction::showStatusbar(this, SLOT(setSettingsDirty()), actionCollection());
00779     KStatusBar *sb = statusBar(); // Creates statusbar if it doesn't exist already.
00780     connect(d->showStatusBarAction, SIGNAL(toggled(bool)), sb, SLOT(setShown(bool)));
00781     d->showStatusBarAction->setChecked(sb->isHidden());
00782   }
00783 }
00784 
00785 bool KMainWindow::readPropertiesInternal( KConfig *config, int number )
00786 {
00787     if ( number == 1 )
00788         readGlobalProperties( config );
00789 
00790     // in order they are in toolbar list
00791     QString s;
00792     s.setNum(number);
00793     s.prepend(QString::fromLatin1("WindowProperties"));
00794 
00795     config->setGroup(s);
00796 
00797     // restore the object name (window role)
00798     if ( config->hasKey(QString::fromLatin1("ObjectName" )) )
00799         setName( config->readEntry(QString::fromLatin1("ObjectName")).latin1()); // latin1 is right here
00800 
00801     applyMainWindowSettings(config); // Menubar, statusbar and toolbar settings.
00802 
00803     s.setNum(number);
00804     config->setGroup(s);
00805     readProperties(config);
00806     return true;
00807 }
00808 
00809 void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup)
00810 {
00811     return applyMainWindowSettings(config,configGroup,false);
00812 }
00813 
00814 void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup,bool force)
00815 {
00816     kdDebug(200) << "KMainWindow::applyMainWindowSettings" << endl;
00817     if (!configGroup.isEmpty())
00818        config->setGroup(configGroup);
00819 
00820     restoreWindowSize(config);
00821 
00822     QStatusBar* sb = internalStatusBar();
00823     if (sb) {
00824         QString entry = config->readEntry("StatusBar", "Enabled");
00825         if ( entry == "Disabled" )
00826            sb->hide();
00827         else
00828            sb->show();
00829         if(d->showStatusBarAction)
00830             d->showStatusBarAction->setChecked(!sb->isHidden());
00831     }
00832 
00833     QMenuBar* mb = internalMenuBar();
00834     if (mb) {
00835         QString entry = config->readEntry ("MenuBar", "Enabled");
00836         if ( entry == "Disabled" )
00837            mb->hide();
00838         else
00839            mb->show();
00840     }
00841 
00842     int n = 1; // Toolbar counter. toolbars are counted from 1,
00843     KToolBar *toolbar;
00844     QPtrListIterator<KToolBar> it( toolBarIterator() ); // must use own iterator
00845 
00846     for ( ; it.current(); ++it) {
00847         toolbar= it.current();
00848         QString group;
00849         if (!configGroup.isEmpty())
00850         {
00851            // Give a number to the toolbar, but prefer a name if there is one,
00852            // because there's no real guarantee on the ordering of toolbars
00853            group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name());
00854            group.prepend(" Toolbar");
00855            group.prepend(configGroup);
00856         }
00857         toolbar->applySettings(config, group, force);
00858         n++;
00859     }
00860 
00861     finalizeGUI( true );
00862 }
00863 
00864 void KMainWindow::finalizeGUI( bool force )
00865 {
00866     //kdDebug(200) << "KMainWindow::finalizeGUI force=" << force << endl;
00867     // The whole reason for this is that moveToolBar relies on the indexes
00868     // of the other toolbars, so in theory it should be called only once per
00869     // toolbar, but in increasing order of indexes.
00870     // Since we can't do that immediately, we move them, and _then_
00871     // we call positionYourself again for each of them, but this time
00872     // the toolbariterator should give them in the proper order.
00873     // Both the XMLGUI and applySettings call this, hence "force" for the latter.
00874     QPtrListIterator<KToolBar> it( toolBarIterator() );
00875     for ( ; it.current() ; ++ it )
00876             it.current()->positionYourself( force );
00877 
00878     d->settingsDirty = false;
00879 }
00880 
00881 void KMainWindow::saveWindowSize( KConfig * config ) const
00882 {
00883 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00884   int scnum = QApplication::desktop()->screenNumber(parentWidget());
00885   QRect desk = QApplication::desktop()->screenGeometry(scnum);
00886   // save maximalization as desktop size + 1 in that direction
00887   KWin::WindowInfo info = KWin::windowInfo( winId(), NET::WMState );
00888   int w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width();
00889   int h = info.state() & NET::MaxVert ? desk.height() + 1 : height();
00890   QRect size( desk.width(), w, desk.height(), h );
00891 #else
00892   int w = 500;
00893   int h = 500;
00894   QRect desk( 100, 100, 200, 200 ); // fixme
00895   QRect size( 100, 100, 200, 200 ); // fixme
00896 #endif
00897   bool defaultSize = (size == d->defaultWindowSize);
00898   QString widthString = QString::fromLatin1("Width %1").arg(desk.width());
00899   QString heightString = QString::fromLatin1("Height %1").arg(desk.height());
00900   if (!config->hasDefault(widthString) && defaultSize)
00901      config->revertToDefault(widthString);
00902   else
00903      config->writeEntry(widthString, w );
00904 
00905   if (!config->hasDefault(heightString) && defaultSize)
00906      config->revertToDefault(heightString);
00907   else
00908      config->writeEntry(heightString, h );
00909 }
00910 
00911 void KMainWindow::restoreWindowSize( KConfig * config )
00912 {
00913     if (d->care_about_geometry) {
00914         parseGeometry(true);
00915     } else {
00916         // restore the size
00917         int scnum = QApplication::desktop()->screenNumber(parentWidget());
00918         QRect desk = QApplication::desktop()->screenGeometry(scnum);
00919         if ( d->defaultWindowSize.isNull() ) // only once
00920           d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); // store default values
00921         QSize size( config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ),
00922                     config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) );
00923         if (size.isEmpty()) {
00924             // try the KDE 2.0 way
00925             size = QSize( config->readNumEntry( QString::fromLatin1("Width"), 0 ),
00926                           config->readNumEntry( QString::fromLatin1("Height"), 0 ) );
00927             if (!size.isEmpty()) {
00928                 // make sure the other resolutions don't get old settings
00929                 config->writeEntry( QString::fromLatin1("Width"), 0 );
00930                 config->writeEntry( QString::fromLatin1("Height"), 0 );
00931             }
00932         }
00933         if ( !size.isEmpty() ) {
00934             int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 )
00935                         | ( size.height() > desk.height() ? NET::MaxVert : 0 );
00936             if(( state & NET::Max ) == NET::Max )
00937                 ; // no resize
00938             else if(( state & NET::MaxHoriz ) == NET::MaxHoriz )
00939                 resize( width(), size.height());
00940             else if(( state & NET::MaxVert ) == NET::MaxVert )
00941                 resize( size.width(), height());
00942             else
00943                 resize( size );
00944             // QWidget::showMaximized() is both insufficient and broken
00945             KWin::setState( winId(), state );
00946         }
00947     }
00948 }
00949 
00950 bool KMainWindow::initialGeometrySet() const
00951 {
00952     return d->care_about_geometry;
00953 }
00954 
00955 void KMainWindow::ignoreInitialGeometry()
00956 {
00957     d->care_about_geometry = false;
00958 }
00959 
00960 void KMainWindow::setSettingsDirty()
00961 {
00962     //kdDebug(200) << "KMainWindow::setSettingsDirty" << endl;
00963     d->settingsDirty = true;
00964     if ( d->autoSaveSettings )
00965     {
00966         // Use a timer to save "immediately" user-wise, but not too immediately
00967         // (to compress calls and save only once, in case of multiple changes)
00968         if ( !d->settingsTimer )
00969         {
00970            d->settingsTimer = new QTimer( this );
00971            connect( d->settingsTimer, SIGNAL( timeout() ), SLOT( saveAutoSaveSettings() ) );
00972         }
00973         d->settingsTimer->start( 500, true );
00974     }
00975 }
00976 
00977 bool KMainWindow::settingsDirty() const
00978 {
00979     return d->settingsDirty;
00980 }
00981 
00982 QString KMainWindow::settingsGroup() const
00983 {
00984     return d->autoSaveGroup;
00985 }
00986 
00987 void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize )
00988 {
00989     d->autoSaveSettings = true;
00990     d->autoSaveGroup = groupName;
00991     d->autoSaveWindowSize = saveWindowSize;
00992     // Get notified when the user moves a toolbar around
00993     connect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ),
00994              this, SLOT( setSettingsDirty() ) );
00995 
00996     // Now read the previously saved settings
00997     applyMainWindowSettings( KGlobal::config(), groupName );
00998 }
00999 
01000 void KMainWindow::resetAutoSaveSettings()
01001 {
01002     d->autoSaveSettings = false;
01003     if ( d->settingsTimer )
01004         d->settingsTimer->stop();
01005 }
01006 
01007 bool KMainWindow::autoSaveSettings() const
01008 {
01009     return d->autoSaveSettings;
01010 }
01011 
01012 QString KMainWindow::autoSaveGroup() const
01013 {
01014     return d->autoSaveGroup;
01015 }
01016 
01017 void KMainWindow::saveAutoSaveSettings()
01018 {
01019     Q_ASSERT( d->autoSaveSettings );
01020     //kdDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings" << endl;
01021     saveMainWindowSettings( KGlobal::config(), d->autoSaveGroup );
01022     KGlobal::config()->sync();
01023     d->settingsDirty = false;
01024     if ( d->settingsTimer )
01025         d->settingsTimer->stop();
01026 }
01027 
01028 void KMainWindow::resizeEvent( QResizeEvent * )
01029 {
01030     if ( d->autoSaveWindowSize )
01031         setSettingsDirty();
01032 }
01033 
01034 bool KMainWindow::hasMenuBar()
01035 {
01036     return (internalMenuBar());
01037 }
01038 
01039 KMenuBar *KMainWindow::menuBar()
01040 {
01041     KMenuBar * mb = internalMenuBar();
01042     if ( !mb ) {
01043         mb = new KMenuBar( this );
01044         // trigger a re-layout and trigger a call to the private
01045         // setMenuBar method.
01046         QMainWindow::menuBar();
01047     }
01048     return mb;
01049 }
01050 
01051 KStatusBar *KMainWindow::statusBar()
01052 {
01053     KStatusBar * sb = internalStatusBar();
01054     if ( !sb ) {
01055         sb = new KStatusBar( this );
01056         // trigger a re-layout and trigger a call to the private
01057         // setStatusBar method.
01058         QMainWindow::statusBar();
01059     }
01060     return sb;
01061 }
01062 
01063 void KMainWindow::shuttingDown()
01064 {
01065     // Needed for Qt <= 3.0.3 at least to prevent reentrancy
01066     // when queryExit() shows a dialog. Check before removing!
01067     static bool reentrancy_protection = false;
01068     if (!reentrancy_protection)
01069     {
01070        reentrancy_protection = true;
01071        // call the virtual queryExit
01072        queryExit();
01073        reentrancy_protection = false;
01074     }
01075 
01076 }
01077 
01078 KMenuBar *KMainWindow::internalMenuBar()
01079 {
01080     QObjectList *l = queryList( "KMenuBar", 0, false, false );
01081     if ( !l || !l->first() ) {
01082         delete l;
01083         return 0;
01084     }
01085 
01086     KMenuBar *m = (KMenuBar*)l->first();
01087     delete l;
01088     return m;
01089 }
01090 
01091 KStatusBar *KMainWindow::internalStatusBar()
01092 {
01093     QObjectList *l = queryList( "KStatusBar", 0, false, false );
01094     if ( !l || !l->first() ) {
01095         delete l;
01096         return 0;
01097     }
01098 
01099     KStatusBar *s = (KStatusBar*)l->first();
01100     delete l;
01101     return s;
01102 }
01103 
01104 void KMainWindow::childEvent( QChildEvent* e)
01105 {
01106     QMainWindow::childEvent( e );
01107 }
01108 
01109 KToolBar *KMainWindow::toolBar( const char * name )
01110 {
01111     if (!name)
01112        name = "mainToolBar";
01113     KToolBar *tb = (KToolBar*)child( name, "KToolBar" );
01114     if ( tb )
01115         return tb;
01116     bool honor_mode = (name == "mainToolBar");
01117 
01118     if ( builderClient() )
01119         return new KToolBar(this, name, honor_mode); // XMLGUI constructor
01120     else
01121         return new KToolBar(this, DockTop, false, name, honor_mode ); // non-XMLGUI
01122 }
01123 
01124 QPtrListIterator<KToolBar> KMainWindow::toolBarIterator()
01125 {
01126     toolbarList.clear();
01127     QPtrList<QToolBar> lst;
01128     for ( int i = (int)QMainWindow::DockUnmanaged; i <= (int)DockMinimized; ++i ) {
01129         lst = toolBars( (ToolBarDock)i );
01130         for ( QToolBar *tb = lst.first(); tb; tb = lst.next() ) {
01131             if ( !tb->inherits( "KToolBar" ) )
01132                 continue;
01133             toolbarList.append( (KToolBar*)tb );
01134         }
01135     }
01136     return QPtrListIterator<KToolBar>( toolbarList );
01137 }
01138 
01139 KAccel * KMainWindow::accel()
01140 {
01141     if ( !d->kaccel )
01142         d->kaccel = new KAccel( this, "kmw-kaccel" );
01143     return d->kaccel;
01144 }
01145 
01146 void KMainWindow::paintEvent( QPaintEvent * pe )
01147 {
01148     QMainWindow::paintEvent(pe); //Upcall to handle SH_MainWindow_SpaceBelowMenuBar rendering
01149 }
01150 
01151 QSize KMainWindow::sizeForCentralWidgetSize(QSize size)
01152 {
01153     KToolBar *tb = (KToolBar*)child( "mainToolBar", "KToolBar" );
01154     if (tb && !tb->isHidden()) {
01155         switch( tb->barPos() )
01156         {
01157           case KToolBar::Top:
01158           case KToolBar::Bottom:
01159             size += QSize(0, tb->sizeHint().height());
01160             break;
01161 
01162           case KToolBar::Left:
01163           case KToolBar::Right:
01164             size += QSize(toolBar()->sizeHint().width(), 0);
01165             break;
01166 
01167           case KToolBar::Flat:
01168             size += QSize(0, 3+kapp->style().pixelMetric( QStyle::PM_DockWindowHandleExtent ));
01169             break;
01170 
01171           default:
01172             break;
01173         }
01174     }
01175     KMenuBar *mb = internalMenuBar();
01176     if (mb && !mb->isHidden()) {
01177         size += QSize(0,mb->heightForWidth(size.width()));
01178         if (style().styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, this))
01179            size += QSize( 0, dockWindowsMovable() ? 1 : 2);
01180     }
01181     QStatusBar *sb = internalStatusBar();
01182     if( sb && !sb->isHidden() )
01183        size += QSize(0, sb->sizeHint().height());
01184 
01185     return size;
01186 }
01187 
01188 // why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI;
01189 // DF: because they compile KDE much faster :)
01190 void KMainWindow::finalizeGUI( KXMLGUIClient *client )
01191 { KXMLGUIBuilder::finalizeGUI( client ); }
01192 
01193 void KMainWindow::virtual_hook( int id, void* data )
01194 { KXMLGUIBuilder::virtual_hook( id, data );
01195   KXMLGUIClient::virtual_hook( id, data ); }
01196 
01197 
01198 
01199 #include "kmainwindow.moc"
01200 
KDE Logo
This file is part of the documentation for kdeui Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Nov 27 13:43:08 2004 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003