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 
00271 void KMainWindow::setupToolbarMenuActions()
00272 {
00273     if ( d->toolBarHandler )
00274         d->toolBarHandler->setupActions();
00275 }
00276 
00277 void KMainWindow::parseGeometry(bool parsewidth)
00278 {
00279     assert ( !kapp->geometryArgument().isNull() );
00280     assert ( d->care_about_geometry );
00281 
00282 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00283 //#ifndef Q_WS_QWS
00284     // FIXME: (E) Implement something similar for Qt Embedded (or decide we don't need it)
00285     int x, y;
00286     int w, h;
00287     int m = XParseGeometry( kapp->geometryArgument().latin1(), &x, &y, (unsigned int*)&w, (unsigned int*)&h);
00288     if (parsewidth) {
00289         QSize minSize = minimumSize();
00290         QSize maxSize = maximumSize();
00291         if ( (m & WidthValue) == 0 )
00292             w = width();
00293         if ( (m & HeightValue) == 0 )
00294             h = height();
00295          w = QMIN(w,maxSize.width());
00296          h = QMIN(h,maxSize.height());
00297          w = QMAX(w,minSize.width());
00298          h = QMAX(h,minSize.height());
00299          resize(w, h);
00300     } else {
00301         if ( parsewidth && (m & XValue) == 0 )
00302             x = geometry().x();
00303         if ( parsewidth && (m & YValue) == 0 )
00304             y = geometry().y();
00305         if ( (m & XNegative) )
00306             x = KApplication::desktop()->width()  + x - w;
00307         if ( (m & YNegative) )
00308             y = KApplication::desktop()->height() + y - h;
00309         move(x, y);
00310     }
00311 #endif
00312 }
00313 
00314 KMainWindow::~KMainWindow()
00315 {
00316     delete d->settingsTimer;
00317     QMenuBar* mb = internalMenuBar();
00318     delete mb;
00319     delete d->m_interface;
00320     delete d;
00321     memberList->remove( this );
00322 }
00323 
00324 KPopupMenu* KMainWindow::helpMenu( const QString &aboutAppText, bool showWhatsThis )
00325 {
00326     if( mHelpMenu == 0 ) {
00327         if ( aboutAppText.isEmpty() )
00328             mHelpMenu = new KHelpMenu( this, instance()->aboutData(), showWhatsThis);
00329         else
00330             mHelpMenu = new KHelpMenu( this, aboutAppText, showWhatsThis );
00331 
00332         if ( mHelpMenu == 0 )
00333             return 0;
00334         connect( mHelpMenu, SIGNAL( showAboutApplication() ),
00335                  this, SLOT( showAboutApplication() ) );
00336     }
00337 
00338     return mHelpMenu->menu();
00339 }
00340 
00341 KPopupMenu* KMainWindow::customHelpMenu( bool showWhatsThis )
00342 {
00343     if( mHelpMenu == 0 ) {
00344         mHelpMenu = new KHelpMenu( this, QString::null, showWhatsThis );
00345         connect( mHelpMenu, SIGNAL( showAboutApplication() ),
00346                  this, SLOT( showAboutApplication() ) );
00347     }
00348 
00349     return mHelpMenu->menu();
00350 }
00351 
00352 bool KMainWindow::canBeRestored( int number )
00353 {
00354     if ( !kapp->isRestored() )
00355         return false;
00356     KConfig *config = kapp->sessionConfig();
00357     if ( !config )
00358         return false;
00359     config->setGroup( QString::fromLatin1("Number") );
00360     int n = config->readNumEntry( QString::fromLatin1("NumberOfWindows") , 1 );
00361     return number >= 1 && number <= n;
00362 }
00363 
00364 const QString KMainWindow::classNameOfToplevel( int number )
00365 {
00366     if ( !kapp->isRestored() )
00367         return QString::null;
00368     KConfig *config = kapp->sessionConfig();
00369     if ( !config )
00370         return QString::null;
00371     QString s;
00372     s.setNum( number );
00373     s.prepend( QString::fromLatin1("WindowProperties") );
00374     config->setGroup( s );
00375     if ( !config->hasKey( QString::fromLatin1("ClassName") ) )
00376         return QString::null;
00377     else
00378         return config->readEntry( QString::fromLatin1("ClassName") );
00379 }
00380 
00381 void KMainWindow::show()
00382 {
00383     QMainWindow::show();
00384 
00385     for ( QPtrListIterator<QDockWindow> it( d->hiddenDockWindows ); it.current(); ++it )
00386     it.current()->show();
00387 
00388     d->hiddenDockWindows.clear();
00389 }
00390 
00391 void KMainWindow::hide()
00392 {
00393     if ( isVisible() ) {
00394 
00395         d->hiddenDockWindows.clear();
00396 
00397         QObjectList *list = queryList( "QDockWindow" );
00398         for( QObjectListIt it( *list ); it.current(); ++it ) {
00399             QDockWindow *dw = (QDockWindow*)it.current();
00400             if ( dw->isTopLevel() && dw->isVisible() ) {
00401                 d->hiddenDockWindows.append( dw );
00402                 dw->hide();
00403             }
00404         }
00405         delete list;
00406     }
00407 
00408     QWidget::hide();
00409 }
00410 
00411 bool KMainWindow::restore( int number, bool show )
00412 {
00413     if ( !canBeRestored( number ) )
00414         return false;
00415     KConfig *config = kapp->sessionConfig();
00416     if ( readPropertiesInternal( config, number ) ){
00417         if ( show )
00418             KMainWindow::show();
00419         return false;
00420     }
00421     return false;
00422 }
00423 
00424 KXMLGUIFactory *KMainWindow::guiFactory()
00425 {
00426     if ( !factory_ )
00427         factory_ = new KXMLGUIFactory( this, this, "guifactory" );
00428     return factory_;
00429 }
00430 
00431 int KMainWindow::configureToolbars()
00432 {
00433     saveMainWindowSettings(KGlobal::config());
00434     KEditToolbar dlg(actionCollection(), xmlFile(), true, this);
00435     connect(&dlg, SIGNAL(newToolbarConfig()), SLOT(saveNewToolbarConfig()));
00436     return dlg.exec();
00437 }
00438 
00439 void KMainWindow::saveNewToolbarConfig()
00440 {
00441     createGUI(xmlFile());
00442     applyMainWindowSettings( KGlobal::config() );
00443 }
00444 
00445 void KMainWindow::setupGUI( int options, const QString & xmlfile ) {
00446     if( options & Keys ){
00447         KStdAction::keyBindings(guiFactory(),
00448                     SLOT(configureShortcuts()), actionCollection());
00449     }
00450 
00451     if( (options & StatusBar) && internalStatusBar() ){
00452         createStandardStatusBarAction();
00453     }
00454 
00455     if( options & ToolBar ){
00456         setStandardToolBarMenuEnabled( true );
00457         KStdAction::configureToolbars(this,
00458                       SLOT(configureToolbars() ), actionCollection());
00459     }
00460 
00461     if( options & Create ){
00462         createGUI(xmlfile);
00463     }
00464 
00465     if( options & Save ){
00466         // setupGUI() is typically called in the constructor before show(),
00467         // so the default window size will be incorrect unless the application
00468         // hard coded the size which they should try not to do (i.e. use
00469         // size hints).
00470         if(!isShown())
00471           adjustSize();
00472         setAutoSaveSettings();
00473     }
00474 
00475 }
00476 
00477 void KMainWindow::createGUI( const QString &xmlfile, bool _conserveMemory )
00478 {
00479     // disabling the updates prevents unnecessary redraws
00480     setUpdatesEnabled( false );
00481 
00482     // just in case we are rebuilding, let's remove our old client
00483     guiFactory()->removeClient( this );
00484 
00485     // make sure to have an empty GUI
00486     QMenuBar* mb = internalMenuBar();
00487     if ( mb )
00488         mb->clear();
00489 
00490     (void)toolBarIterator(); // make sure toolbarList is most-up-to-date
00491     toolbarList.setAutoDelete( true );
00492     toolbarList.clear();
00493     toolbarList.setAutoDelete( false );
00494 
00495     // don't build a help menu unless the user ask for it
00496     if (d->showHelpMenu) {
00497         // we always want a help menu
00498         if (helpMenu2 == 0)
00499             helpMenu2 = new KHelpMenu(this, instance()->aboutData(), true,
00500                                       actionCollection());
00501     }
00502 
00503     // we always want to load in our global standards file
00504     setXMLFile( locate( "config", "ui/ui_standards.rc", instance() ) );
00505 
00506     // now, merge in our local xml file.  if this is null, then that
00507     // means that we will be only using the global file
00508     if ( !xmlfile.isNull() ) {
00509         setXMLFile( xmlfile, true );
00510     } else {
00511         QString auto_file(instance()->instanceName() + "ui.rc");
00512         setXMLFile( auto_file, true );
00513     }
00514 
00515     // make sure we don't have any state saved already
00516     setXMLGUIBuildDocument( QDomDocument() );
00517 
00518     // do the actual GUI building
00519     guiFactory()->addClient( this );
00520 
00521     // try and get back *some* of our memory
00522     if ( _conserveMemory )
00523     {
00524       // before freeing the memory allocated by the DOM document we also
00525       // free all memory allocated internally in the KXMLGUIFactory for
00526       // the menubar and the toolbars . This however implies that we
00527       // have to take care of deleting those widgets ourselves. For
00528       // destruction this is no problem, but when rebuilding we have
00529       // to take care of that (and we want to rebuild the GUI when
00530       // using stuff like the toolbar editor ).
00531       // In addition we have to take care of not removing containers
00532       // like popupmenus, defined in the XML document.
00533       // this code should probably go into a separate method in KMainWindow.
00534       // there's just one problem: I'm bad in finding names ;-) , so
00535       // I skipped this ;-)
00536 
00537       QDomDocument doc = domDocument();
00538 
00539       for( QDomNode n = doc.documentElement().firstChild();
00540            !n.isNull(); n = n.nextSibling())
00541       {
00542           QDomElement e = n.toElement();
00543 
00544           if ( e.tagName().lower() == "toolbar" )
00545               factory_->resetContainer( e.attribute( "name" ) );
00546           else if ( e.tagName().lower() == "menubar" )
00547               factory_->resetContainer( e.tagName(), true );
00548       }
00549 
00550       conserveMemory();
00551     }
00552 
00553     setUpdatesEnabled( true );
00554     updateGeometry();
00555 }
00556 
00557 void KMainWindow::setHelpMenuEnabled(bool showHelpMenu)
00558 {
00559     d->showHelpMenu = showHelpMenu;
00560 }
00561 
00562 bool KMainWindow::isHelpMenuEnabled()
00563 {
00564     return d->showHelpMenu;
00565 }
00566 
00567 void KMainWindow::setCaption( const QString &caption )
00568 {
00569     setPlainCaption( kapp->makeStdCaption(caption) );
00570 }
00571 
00572 void KMainWindow::setCaption( const QString &caption, bool modified )
00573 {
00574     setPlainCaption( kapp->makeStdCaption(caption, true, modified) );
00575 }
00576 
00577 void KMainWindow::setPlainCaption( const QString &caption )
00578 {
00579     QMainWindow::setCaption( caption );
00580 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00581 //#ifndef Q_WS_QWS
00582     NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), 0 );
00583     info.setName( caption.utf8().data() );
00584 #endif
00585 }
00586 
00587 void KMainWindow::appHelpActivated( void )
00588 {
00589     if( mHelpMenu == 0 ) {
00590         mHelpMenu = new KHelpMenu( this );
00591         if ( mHelpMenu == 0 )
00592             return;
00593     }
00594     mHelpMenu->appHelpActivated();
00595 }
00596 
00597 void KMainWindow::slotStateChanged(const QString &newstate)
00598 {
00599   stateChanged(newstate, KXMLGUIClient::StateNoReverse);
00600 }
00601 
00602 /*
00603  * Get rid of this for KDE 4.0
00604  */
00605 void KMainWindow::slotStateChanged(const QString &newstate,
00606                                    KXMLGUIClient::ReverseStateChange reverse)
00607 {
00608   stateChanged(newstate, reverse);
00609 }
00610 
00611 /*
00612  * Enable this for KDE 4.0
00613  */
00614 // void KMainWindow::slotStateChanged(const QString &newstate,
00615 //                                    bool reverse)
00616 // {
00617 //   stateChanged(newstate,
00618 //                reverse ? KXMLGUIClient::StateReverse : KXMLGUIClient::StateNoReverse);
00619 // }
00620 
00621 void KMainWindow::closeEvent ( QCloseEvent *e )
00622 {
00623     // Save settings if auto-save is enabled, and settings have changed
00624     if (d->settingsDirty && d->autoSaveSettings)
00625         saveAutoSaveSettings();
00626 
00627     if (queryClose()) {
00628         e->accept();
00629 
00630         int not_withdrawn = 0;
00631         QPtrListIterator<KMainWindow> it(*KMainWindow::memberList);
00632         for (it.toFirst(); it.current(); ++it){
00633             if ( !it.current()->isHidden() && it.current()->isTopLevel() && it.current() != this )
00634                 not_withdrawn++;
00635         }
00636 
00637         if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted?
00638             if ( queryExit() && !kapp->sessionSaving() && !d->shuttingDown ) { // Yes, Quit app?
00639                 // don't call queryExit() twice
00640                 disconnect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown()));
00641                 d->shuttingDown = true;
00642                 kapp->deref();             // ...and quit application.
00643             }  else {
00644                 // cancel closing, it's stupid to end up with no windows at all....
00645                 e->ignore();
00646             }
00647         }
00648     }
00649 }
00650 
00651 bool KMainWindow::queryExit()
00652 {
00653     return true;
00654 }
00655 
00656 bool KMainWindow::queryClose()
00657 {
00658     return true;
00659 }
00660 
00661 void KMainWindow::saveGlobalProperties( KConfig*  )
00662 {
00663 }
00664 
00665 void KMainWindow::readGlobalProperties( KConfig*  )
00666 {
00667 }
00668 
00669 #if defined(KDE_COMPAT)
00670 void KMainWindow::updateRects()
00671 {
00672 }
00673 #endif
00674 
00675 void KMainWindow::showAboutApplication()
00676 {
00677 }
00678 
00679 void KMainWindow::savePropertiesInternal( KConfig *config, int number )
00680 {
00681     bool oldASWS = d->autoSaveWindowSize;
00682     d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size
00683 
00684     QString s;
00685     s.setNum(number);
00686     s.prepend(QString::fromLatin1("WindowProperties"));
00687     config->setGroup(s);
00688 
00689     // store objectName, className, Width and Height  for later restoring
00690     // (Only useful for session management)
00691     config->writeEntry(QString::fromLatin1("ObjectName"), name());
00692     config->writeEntry(QString::fromLatin1("ClassName"), className());
00693 
00694     saveMainWindowSettings(config); // Menubar, statusbar and Toolbar settings.
00695 
00696     s.setNum(number);
00697     config->setGroup(s);
00698     saveProperties(config);
00699 
00700     d->autoSaveWindowSize = oldASWS;
00701 }
00702 
00703 void KMainWindow::saveMainWindowSettings(KConfig *config, const QString &configGroup)
00704 {
00705     kdDebug(200) << "KMainWindow::saveMainWindowSettings " << configGroup << endl;
00706     QString oldGroup;
00707 
00708     if (!configGroup.isEmpty())
00709     {
00710        oldGroup = config->group();
00711        config->setGroup(configGroup);
00712     }
00713 
00714     // Called by session management - or if we want to save the window size anyway
00715     if ( d->autoSaveWindowSize )
00716         saveWindowSize( config );
00717 
00718     QStatusBar* sb = internalStatusBar();
00719     if (sb) {
00720        if(!config->hasDefault("StatusBar") && !sb->isHidden() )
00721            config->revertToDefault("StatusBar");
00722        else
00723            config->writeEntry("StatusBar", sb->isHidden() ? "Disabled" : "Enabled");
00724     }
00725 
00726     QMenuBar* mb = internalMenuBar();
00727     if (mb) {
00728        QString MenuBar = QString::fromLatin1("MenuBar");
00729        if(!config->hasDefault("MenuBar") && !mb->isHidden() )
00730            config->revertToDefault("MenuBar");
00731        else
00732            config->writeEntry("MenuBar", mb->isHidden() ? "Disabled" : "Enabled");
00733     }
00734 
00735     int n = 1; // Toolbar counter. toolbars are counted from 1,
00736     KToolBar *toolbar = 0;
00737     QPtrListIterator<KToolBar> it( toolBarIterator() );
00738     while ( ( toolbar = it.current() ) ) {
00739         ++it;
00740         QString group;
00741         if (!configGroup.isEmpty())
00742         {
00743            // Give a number to the toolbar, but prefer a name if there is one,
00744            // because there's no real guarantee on the ordering of toolbars
00745            group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name());
00746            group.prepend(" Toolbar");
00747            group.prepend(configGroup);
00748         }
00749         toolbar->saveSettings(config, group);
00750         n++;
00751     }
00752     if (!configGroup.isEmpty())
00753        config->setGroup(oldGroup);
00754 }
00755 
00756 void KMainWindow::setStandardToolBarMenuEnabled( bool enable )
00757 {
00758     if ( enable ) {
00759         if ( d->toolBarHandler )
00760             return;
00761 
00762     d->toolBarHandler = new KDEPrivate::ToolBarHandler( this );
00763 
00764     if ( factory() )
00765         factory()->addClient( d->toolBarHandler );
00766     } else {
00767         if ( !d->toolBarHandler )
00768             return;
00769 
00770         if ( factory() )
00771             factory()->removeClient( d->toolBarHandler );
00772 
00773         delete d->toolBarHandler;
00774         d->toolBarHandler = 0;
00775     }
00776 }
00777 
00778 bool KMainWindow::isStandardToolBarMenuEnabled() const
00779 {
00780     return ( d->toolBarHandler != 0 );
00781 }
00782 
00783 void KMainWindow::createStandardStatusBarAction(){
00784   if(!d->showStatusBarAction){
00785     d->showStatusBarAction = KStdAction::showStatusbar(this, SLOT(setSettingsDirty()), actionCollection());
00786     KStatusBar *sb = statusBar(); // Creates statusbar if it doesn't exist already.
00787     connect(d->showStatusBarAction, SIGNAL(toggled(bool)), sb, SLOT(setShown(bool)));
00788     d->showStatusBarAction->setChecked(sb->isHidden());
00789   }
00790 }
00791 
00792 bool KMainWindow::readPropertiesInternal( KConfig *config, int number )
00793 {
00794     if ( number == 1 )
00795         readGlobalProperties( config );
00796 
00797     // in order they are in toolbar list
00798     QString s;
00799     s.setNum(number);
00800     s.prepend(QString::fromLatin1("WindowProperties"));
00801 
00802     config->setGroup(s);
00803 
00804     // restore the object name (window role)
00805     if ( config->hasKey(QString::fromLatin1("ObjectName" )) )
00806         setName( config->readEntry(QString::fromLatin1("ObjectName")).latin1()); // latin1 is right here
00807 
00808     applyMainWindowSettings(config); // Menubar, statusbar and toolbar settings.
00809 
00810     s.setNum(number);
00811     config->setGroup(s);
00812     readProperties(config);
00813     return true;
00814 }
00815 
00816 void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup)
00817 {
00818     return applyMainWindowSettings(config,configGroup,false);
00819 }
00820 
00821 void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup,bool force)
00822 {
00823     kdDebug(200) << "KMainWindow::applyMainWindowSettings" << endl;
00824     if (!configGroup.isEmpty())
00825        config->setGroup(configGroup);
00826 
00827     restoreWindowSize(config);
00828 
00829     QStatusBar* sb = internalStatusBar();
00830     if (sb) {
00831         QString entry = config->readEntry("StatusBar", "Enabled");
00832         if ( entry == "Disabled" )
00833            sb->hide();
00834         else
00835            sb->show();
00836         if(d->showStatusBarAction)
00837             d->showStatusBarAction->setChecked(!sb->isHidden());
00838     }
00839 
00840     QMenuBar* mb = internalMenuBar();
00841     if (mb) {
00842         QString entry = config->readEntry ("MenuBar", "Enabled");
00843         if ( entry == "Disabled" )
00844            mb->hide();
00845         else
00846            mb->show();
00847     }
00848 
00849     int n = 1; // Toolbar counter. toolbars are counted from 1,
00850     KToolBar *toolbar;
00851     QPtrListIterator<KToolBar> it( toolBarIterator() ); // must use own iterator
00852 
00853     for ( ; it.current(); ++it) {
00854         toolbar= it.current();
00855         QString group;
00856         if (!configGroup.isEmpty())
00857         {
00858            // Give a number to the toolbar, but prefer a name if there is one,
00859            // because there's no real guarantee on the ordering of toolbars
00860            group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name());
00861            group.prepend(" Toolbar");
00862            group.prepend(configGroup);
00863         }
00864         toolbar->applySettings(config, group, force);
00865         n++;
00866     }
00867 
00868     finalizeGUI( true );
00869 }
00870 
00871 void KMainWindow::finalizeGUI( bool force )
00872 {
00873     //kdDebug(200) << "KMainWindow::finalizeGUI force=" << force << endl;
00874     // The whole reason for this is that moveToolBar relies on the indexes
00875     // of the other toolbars, so in theory it should be called only once per
00876     // toolbar, but in increasing order of indexes.
00877     // Since we can't do that immediately, we move them, and _then_
00878     // we call positionYourself again for each of them, but this time
00879     // the toolbariterator should give them in the proper order.
00880     // Both the XMLGUI and applySettings call this, hence "force" for the latter.
00881     QPtrListIterator<KToolBar> it( toolBarIterator() );
00882     for ( ; it.current() ; ++ it )
00883             it.current()->positionYourself( force );
00884 
00885     d->settingsDirty = false;
00886 }
00887 
00888 void KMainWindow::saveWindowSize( KConfig * config ) const
00889 {
00890 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00891   int scnum = QApplication::desktop()->screenNumber(parentWidget());
00892   QRect desk = QApplication::desktop()->screenGeometry(scnum);
00893   // save maximalization as desktop size + 1 in that direction
00894   KWin::WindowInfo info = KWin::windowInfo( winId(), NET::WMState );
00895   int w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width();
00896   int h = info.state() & NET::MaxVert ? desk.height() + 1 : height();
00897   QRect size( desk.width(), w, desk.height(), h );
00898 #else
00899   int w = 500;
00900   int h = 500;
00901   QRect desk( 100, 100, 200, 200 ); // fixme
00902   QRect size( 100, 100, 200, 200 ); // fixme
00903 #endif
00904   bool defaultSize = (size == d->defaultWindowSize);
00905   QString widthString = QString::fromLatin1("Width %1").arg(desk.width());
00906   QString heightString = QString::fromLatin1("Height %1").arg(desk.height());
00907   if (!config->hasDefault(widthString) && defaultSize)
00908      config->revertToDefault(widthString);
00909   else
00910      config->writeEntry(widthString, w );
00911 
00912   if (!config->hasDefault(heightString) && defaultSize)
00913      config->revertToDefault(heightString);
00914   else
00915      config->writeEntry(heightString, h );
00916 }
00917 
00918 void KMainWindow::restoreWindowSize( KConfig * config )
00919 {
00920     if (d->care_about_geometry) {
00921         parseGeometry(true);
00922     } else {
00923         // restore the size
00924         int scnum = QApplication::desktop()->screenNumber(parentWidget());
00925         QRect desk = QApplication::desktop()->screenGeometry(scnum);
00926         if ( d->defaultWindowSize.isNull() ) // only once
00927           d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); // store default values
00928         QSize size( config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ),
00929                     config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) );
00930         if (size.isEmpty()) {
00931             // try the KDE 2.0 way
00932             size = QSize( config->readNumEntry( QString::fromLatin1("Width"), 0 ),
00933                           config->readNumEntry( QString::fromLatin1("Height"), 0 ) );
00934             if (!size.isEmpty()) {
00935                 // make sure the other resolutions don't get old settings
00936                 config->writeEntry( QString::fromLatin1("Width"), 0 );
00937                 config->writeEntry( QString::fromLatin1("Height"), 0 );
00938             }
00939         }
00940         if ( !size.isEmpty() ) {
00941             int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 )
00942                         | ( size.height() > desk.height() ? NET::MaxVert : 0 );
00943             if(( state & NET::Max ) == NET::Max )
00944                 ; // no resize
00945             else if(( state & NET::MaxHoriz ) == NET::MaxHoriz )
00946                 resize( width(), size.height());
00947             else if(( state & NET::MaxVert ) == NET::MaxVert )
00948                 resize( size.width(), height());
00949             else
00950                 resize( size );
00951             // QWidget::showMaximized() is both insufficient and broken
00952             KWin::setState( winId(), state );
00953         }
00954     }
00955 }
00956 
00957 bool KMainWindow::initialGeometrySet() const
00958 {
00959     return d->care_about_geometry;
00960 }
00961 
00962 void KMainWindow::ignoreInitialGeometry()
00963 {
00964     d->care_about_geometry = false;
00965 }
00966 
00967 void KMainWindow::setSettingsDirty()
00968 {
00969     //kdDebug(200) << "KMainWindow::setSettingsDirty" << endl;
00970     d->settingsDirty = true;
00971     if ( d->autoSaveSettings )
00972     {
00973         // Use a timer to save "immediately" user-wise, but not too immediately
00974         // (to compress calls and save only once, in case of multiple changes)
00975         if ( !d->settingsTimer )
00976         {
00977            d->settingsTimer = new QTimer( this );
00978            connect( d->settingsTimer, SIGNAL( timeout() ), SLOT( saveAutoSaveSettings() ) );
00979         }
00980         d->settingsTimer->start( 500, true );
00981     }
00982 }
00983 
00984 bool KMainWindow::settingsDirty() const
00985 {
00986     return d->settingsDirty;
00987 }
00988 
00989 QString KMainWindow::settingsGroup() const
00990 {
00991     return d->autoSaveGroup;
00992 }
00993 
00994 void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize )
00995 {
00996     d->autoSaveSettings = true;
00997     d->autoSaveGroup = groupName;
00998     d->autoSaveWindowSize = saveWindowSize;
00999     // Get notified when the user moves a toolbar around
01000     connect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ),
01001              this, SLOT( setSettingsDirty() ) );
01002 
01003     // Now read the previously saved settings
01004     applyMainWindowSettings( KGlobal::config(), groupName );
01005 }
01006 
01007 void KMainWindow::resetAutoSaveSettings()
01008 {
01009     d->autoSaveSettings = false;
01010     if ( d->settingsTimer )
01011         d->settingsTimer->stop();
01012 }
01013 
01014 bool KMainWindow::autoSaveSettings() const
01015 {
01016     return d->autoSaveSettings;
01017 }
01018 
01019 QString KMainWindow::autoSaveGroup() const
01020 {
01021     return d->autoSaveGroup;
01022 }
01023 
01024 void KMainWindow::saveAutoSaveSettings()
01025 {
01026     Q_ASSERT( d->autoSaveSettings );
01027     //kdDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings" << endl;
01028     saveMainWindowSettings( KGlobal::config(), d->autoSaveGroup );
01029     KGlobal::config()->sync();
01030     d->settingsDirty = false;
01031     if ( d->settingsTimer )
01032         d->settingsTimer->stop();
01033 }
01034 
01035 void KMainWindow::resizeEvent( QResizeEvent * )
01036 {
01037     if ( d->autoSaveWindowSize )
01038         setSettingsDirty();
01039 }
01040 
01041 bool KMainWindow::hasMenuBar()
01042 {
01043     return (internalMenuBar());
01044 }
01045 
01046 KMenuBar *KMainWindow::menuBar()
01047 {
01048     KMenuBar * mb = internalMenuBar();
01049     if ( !mb ) {
01050         mb = new KMenuBar( this );
01051         // trigger a re-layout and trigger a call to the private
01052         // setMenuBar method.
01053         QMainWindow::menuBar();
01054     }
01055     return mb;
01056 }
01057 
01058 KStatusBar *KMainWindow::statusBar()
01059 {
01060     KStatusBar * sb = internalStatusBar();
01061     if ( !sb ) {
01062         sb = new KStatusBar( this );
01063         // trigger a re-layout and trigger a call to the private
01064         // setStatusBar method.
01065         QMainWindow::statusBar();
01066     }
01067     return sb;
01068 }
01069 
01070 void KMainWindow::shuttingDown()
01071 {
01072     // Needed for Qt <= 3.0.3 at least to prevent reentrancy
01073     // when queryExit() shows a dialog. Check before removing!
01074     static bool reentrancy_protection = false;
01075     if (!reentrancy_protection)
01076     {
01077        reentrancy_protection = true;
01078        // call the virtual queryExit
01079        queryExit();
01080        reentrancy_protection = false;
01081     }
01082 
01083 }
01084 
01085 KMenuBar *KMainWindow::internalMenuBar()
01086 {
01087     QObjectList *l = queryList( "KMenuBar", 0, false, false );
01088     if ( !l || !l->first() ) {
01089         delete l;
01090         return 0;
01091     }
01092 
01093     KMenuBar *m = (KMenuBar*)l->first();
01094     delete l;
01095     return m;
01096 }
01097 
01098 KStatusBar *KMainWindow::internalStatusBar()
01099 {
01100     QObjectList *l = queryList( "KStatusBar", 0, false, false );
01101     if ( !l || !l->first() ) {
01102         delete l;
01103         return 0;
01104     }
01105 
01106     KStatusBar *s = (KStatusBar*)l->first();
01107     delete l;
01108     return s;
01109 }
01110 
01111 void KMainWindow::childEvent( QChildEvent* e)
01112 {
01113     QMainWindow::childEvent( e );
01114 }
01115 
01116 KToolBar *KMainWindow::toolBar( const char * name )
01117 {
01118     if (!name)
01119        name = "mainToolBar";
01120     KToolBar *tb = (KToolBar*)child( name, "KToolBar" );
01121     if ( tb )
01122         return tb;
01123     bool honor_mode = (name == "mainToolBar");
01124 
01125     if ( builderClient() )
01126         return new KToolBar(this, name, honor_mode); // XMLGUI constructor
01127     else
01128         return new KToolBar(this, DockTop, false, name, honor_mode ); // non-XMLGUI
01129 }
01130 
01131 QPtrListIterator<KToolBar> KMainWindow::toolBarIterator()
01132 {
01133     toolbarList.clear();
01134     QPtrList<QToolBar> lst;
01135     for ( int i = (int)QMainWindow::DockUnmanaged; i <= (int)DockMinimized; ++i ) {
01136         lst = toolBars( (ToolBarDock)i );
01137         for ( QToolBar *tb = lst.first(); tb; tb = lst.next() ) {
01138             if ( !tb->inherits( "KToolBar" ) )
01139                 continue;
01140             toolbarList.append( (KToolBar*)tb );
01141         }
01142     }
01143     return QPtrListIterator<KToolBar>( toolbarList );
01144 }
01145 
01146 KAccel * KMainWindow::accel()
01147 {
01148     if ( !d->kaccel )
01149         d->kaccel = new KAccel( this, "kmw-kaccel" );
01150     return d->kaccel;
01151 }
01152 
01153 void KMainWindow::paintEvent( QPaintEvent * pe )
01154 {
01155     QMainWindow::paintEvent(pe); //Upcall to handle SH_MainWindow_SpaceBelowMenuBar rendering
01156 }
01157 
01158 QSize KMainWindow::sizeForCentralWidgetSize(QSize size)
01159 {
01160     KToolBar *tb = (KToolBar*)child( "mainToolBar", "KToolBar" );
01161     if (tb && !tb->isHidden()) {
01162         switch( tb->barPos() )
01163         {
01164           case KToolBar::Top:
01165           case KToolBar::Bottom:
01166             size += QSize(0, tb->sizeHint().height());
01167             break;
01168 
01169           case KToolBar::Left:
01170           case KToolBar::Right:
01171             size += QSize(toolBar()->sizeHint().width(), 0);
01172             break;
01173 
01174           case KToolBar::Flat:
01175             size += QSize(0, 3+kapp->style().pixelMetric( QStyle::PM_DockWindowHandleExtent ));
01176             break;
01177 
01178           default:
01179             break;
01180         }
01181     }
01182     KMenuBar *mb = internalMenuBar();
01183     if (mb && !mb->isHidden()) {
01184         size += QSize(0,mb->heightForWidth(size.width()));
01185         if (style().styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, this))
01186            size += QSize( 0, dockWindowsMovable() ? 1 : 2);
01187     }
01188     QStatusBar *sb = internalStatusBar();
01189     if( sb && !sb->isHidden() )
01190        size += QSize(0, sb->sizeHint().height());
01191 
01192     return size;
01193 }
01194 
01195 // why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI;
01196 // DF: because they compile KDE much faster :)
01197 void KMainWindow::finalizeGUI( KXMLGUIClient *client )
01198 { KXMLGUIBuilder::finalizeGUI( client ); }
01199 
01200 void KMainWindow::virtual_hook( int id, void* data )
01201 { KXMLGUIBuilder::virtual_hook( id, data );
01202   KXMLGUIClient::virtual_hook( id, data ); }
01203 
01204 
01205 
01206 #include "kmainwindow.moc"
01207 
KDE Logo
This file is part of the documentation for kdeui Library Version 3.3.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jan 22 16:45:14 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003