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