kdeui Library API Documentation

kmainwindow.cpp

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