kdeui Library: kmainwindow.cpp Source File (kdeui Library)

| # kdeui Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# 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 "kwhatsthismanager_p.h"
    00030 #include <qsessionmanager.h>
    00031 #include <qobjectlist.h>
    00032 #include <qstyle.h>
    00033 #include <qlayout.h>
    00034 #include <qwidgetlist.h>
    00035 #include <qtimer.h>
    00036
    00037 #include <kaccel.h>
    00038 #include <kaction.h>
    00039 #include <kapplication.h>
    00040 #include <kconfig.h>
    00041 #include <kdebug.h>
    00042 #include <khelpmenu.h>
    00043 #include <kmenubar.h>
    00044 #include <kstatusbar.h>
    00045 #include <kwin.h>
    00046 #include <kedittoolbar.h>
    00047 #include <kmainwindow.h>
    00048
    00049 #include <klocale.h>
    00050 #include <kstandarddirs.h>
    00051 #include <kstaticdeleter.h>
    00052 #if defined Q_WS_X11
    00053 #include <netwm.h>
    00054 #endif
    00055
    00056 #include <stdlib.h>
    00057 #include <ctype.h>
    00058 #include <assert.h>
    00059
    00060 class KMainWindowPrivate {
    00061 public:
    00062     bool showHelpMenu:1;
    00063
    00064     bool autoSaveSettings:1;
    00065     bool settingsDirty:1;
    00066     bool autoSaveWindowSize:1;
    00067     bool care_about_geometry:1;
    00068     bool shuttingDown:1;
    00069     QString autoSaveGroup;
    00070     KAccel * kaccel;
    00071     KMainWindowInterface *m_interface;
    00072     KDEPrivate::ToolBarHandler *toolBarHandler;
    00073     QTimer* settingsTimer;
    00074     KToggleAction *showStatusBarAction;
    00075     QRect defaultWindowSize;
    00076     QPtrList<QDockWindow> hiddenDockWindows;
    00077 };
    00078
    00079 QPtrList<KMainWindow>* KMainWindow::memberList = 0L;
    00080 static bool no_query_exit = false;
    00081 static KMWSessionManaged* ksm = 0;
    00082 static KStaticDeleter<KMWSessionManaged> ksmd;
    00083
    00084 class KMWSessionManaged : public KSessionManaged
    00085 {
    00086 public:
    00087     KMWSessionManaged()
    00088     {
    00089     };
    00090     ~KMWSessionManaged()
    00091     {
    00092     }
    00093     bool saveState( QSessionManager& )
    00094     {
    00095         KConfig* config = KApplication::kApplication()->sessionConfig();
    00096         if ( KMainWindow::memberList->first() ){
    00097             // According to Jochen Wilhelmy <digisnap@cs.tu-berlin.de>, this
    00098             // hook is useful for better document orientation
    00099             KMainWindow::memberList->first()->saveGlobalProperties(config);
    00100         }
    00101
    00102         QPtrListIterator<KMainWindow> it(*KMainWindow::memberList);
    00103         int n = 0;
    00104         for (it.toFirst(); it.current(); ++it){
    00105             n++;
    00106             it.current()->savePropertiesInternal(config, n);
    00107         }
    00108         config->setGroup(QString::fromLatin1("Number"));
    00109         config->writeEntry(QString::fromLatin1("NumberOfWindows"), n );
    00110         return true;
    00111     }
    00112
    00113     bool commitData( QSessionManager& sm )
    00114     {
    00115         // not really a fast method but the only compatible one
    00116         if ( sm.allowsInteraction() ) {
    00117             bool canceled = false;
    00118             QPtrListIterator<KMainWindow> it(*KMainWindow::memberList);
    00119             ::no_query_exit = true;
    00120             for (it.toFirst(); it.current() && !canceled;){
    00121                 KMainWindow *window = *it;
    00122                 ++it; // Update now, the current window might get deleted
    00123                 if ( !window->testWState( Qt::WState_ForceHide ) ) {
    00124                     QCloseEvent e;
    00125                     QApplication::sendEvent( window, &e );
    00126                     canceled = !e.isAccepted();
    00127             /* Don't even think_about deleting widgets with
    00128              Qt::WDestructiveClose flag set at this point. We
    00129              are faking a close event, but we are *not*_
    00130              closing the window. The purpose of the faked
    00131              close event is to prepare the application so it
    00132              can safely be quit without the user losing data
    00133              (possibly showing a message box "do you want to
    00134              save this or that?"). It is possible that the
    00135              session manager quits the application later
    00136              (emitting QApplication::aboutToQuit() when this
    00137              happens), but it is also possible that the user
    00138              cancels the shutdown, so the application will
    00139              continue to run.
    00140              */
    00141                 }
    00142             }
    00143             ::no_query_exit = false;
    00144             if (canceled)
    00145                return false;
    00146
    00147             KMainWindow* last = 0;
    00148             for (it.toFirst(); it.current() && !canceled; ++it){
    00149                 KMainWindow *window = *it;
    00150                 if ( !window->testWState( Qt::WState_ForceHide ) ) {
    00151                     last = window;
    00152                 }
    00153             }
    00154             if ( last )
    00155                 return last->queryExit();
    00156             // else
    00157             return true;
    00158         }
    00159
    00160         // the user wants it, the user gets it
    00161         return true;
    00162     }
    00163 };
    00164
    00165 static bool being_first = true;
    00166
    00167 KMainWindow::KMainWindow( QWidget* parent, const char *name, WFlags f )
    00168     : QMainWindow( parent, name, f ), KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 )
    00169 {
    00170     initKMainWindow(name, 0);
    00171 }
    00172
    00173 KMainWindow::KMainWindow( int cflags, QWidget* parent, const char *name, WFlags f )
    00174     : QMainWindow( parent, name, f ), KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 )
    00175 {
    00176     initKMainWindow(name, cflags);
    00177 }
    00178
    00179 void KMainWindow::initKMainWindow(const char *name, int cflags)
    00180 {
    00181     KWhatsThisManager::init ();
    00182     setDockMenuEnabled( false );
    00183     mHelpMenu = 0;
    00184     kapp->setTopWidget( this );
    00185     actionCollection()->setWidget( this );
    00186     connect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown()));
    00187     if( !memberList )
    00188         memberList = new QPtrList<KMainWindow>;
    00189
    00190     if ( !ksm )
    00191         ksm = ksmd.setObject(ksm, new KMWSessionManaged());
    00192     // set a unique object name. Required by session management.
    00193     QCString objname;
    00194     QCString s;
    00195     int unusedNumber;
    00196     if ( !name )
    00197         { // no name given
    00198         objname = kapp->instanceName() + "-mainwindow#";
    00199         s = objname + '1'; // start adding number immediately
    00200         unusedNumber = 1;
    00201         }
    00202     else if( name[ strlen( name ) - 1 ] == '#' )
    00203         { // trailing # - always add a number
    00204         objname = name;
    00205         s = objname + '1'; // start adding number immediately
    00206         unusedNumber = 1;
    00207         }
    00208     else
    00209         {
    00210         objname = name;
    00211         s = objname;
    00212         unusedNumber = 0; // add numbers only when needed
    00213         }
    00214     for(;;) {
    00215         QWidgetList* list = kapp->topLevelWidgets();
    00216         QWidgetListIt it( *list );
    00217         bool found = false;
    00218         for( QWidget* w = it.current();
    00219              w != NULL;
    00220              ++it, w = it.current())
    00221             if( w != this && w->name() == s )
    00222                 {
    00223                 found = true;
    00224                 break;
    00225                 }
    00226         delete list;
    00227         if( !found )
    00228             break;
    00229         s.setNum( ++unusedNumber );
    00230         s = objname + s;
    00231     }
    00232     setName( s );
    00233
    00234     memberList->append( this );
    00235
    00236     d = new KMainWindowPrivate;
    00237     d->showHelpMenu = true;
    00238     d->settingsDirty = false;
    00239     d->autoSaveSettings = false;
    00240     d->autoSaveWindowSize = true; // for compatibility
    00241     d->kaccel = actionCollection()->kaccel();
    00242     d->toolBarHandler = 0;
    00243     d->settingsTimer = 0;
    00244     d->showStatusBarAction = NULL;
    00245     d->shuttingDown = false;
    00246     if ((d->care_about_geometry = being_first)) {
    00247         being_first = false;
    00248         if ( kapp->geometryArgument().isNull() ) // if there is no geometry, it doesn't mater
    00249             d->care_about_geometry = false;
    00250         else
    00251             parseGeometry(false);
    00252     }
    00253
    00254     setCaption( kapp->caption() );
    00255     if ( cflags & NoDCOPObject)
    00256         d->m_interface = 0;
    00257     else
    00258         d->m_interface = new KMainWindowInterface(this);
    00259
    00260     if (!kapp->authorize("movable_toolbars"))
    00261         setDockWindowsMovable(false);
    00262 }
    00263
    00264 KAction *KMainWindow::toolBarMenuAction()
    00265 {
    00266     if ( !d->toolBarHandler )
    00267     return 0;
    00268
    00269     return d->toolBarHandler->toolBarMenuAction();
    00270 }
    00271
    00272
    00273 void KMainWindow::setupToolbarMenuActions()
    00274 {
    00275     if ( d->toolBarHandler )
    00276         d->toolBarHandler->setupActions();
    00277 }
    00278
    00279 void KMainWindow::parseGeometry(bool parsewidth)
    00280 {
    00281     assert ( !kapp->geometryArgument().isNull() );
    00282     assert ( d->care_about_geometry );
    00283
    00284 #if defined Q_WS_X11
    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) )
    00292             w = width();
    00293         if ( !(m & HeightValue) )
    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) )
    00302             x = geometry().x();
    00303         if ( parsewidth && !(m & YValue) )
    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 ) {
    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 )
    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 ) {
    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)
    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
    00581     NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), 0 );
    00582     info.setName( caption.utf8().data() );
    00583 #endif
    00584 }
    00585
    00586 void KMainWindow::appHelpActivated( void )
    00587 {
    00588     if( !mHelpMenu ) {
    00589         mHelpMenu = new KHelpMenu( this );
    00590         if ( !mHelpMenu )
    00591             return;
    00592     }
    00593     mHelpMenu->appHelpActivated();
    00594 }
    00595
    00596 void KMainWindow::slotStateChanged(const QString &newstate)
    00597 {
    00598   stateChanged(newstate, KXMLGUIClient::StateNoReverse);
    00599 }
    00600
    00601 /*
    00602  * Get rid of this for KDE 4.0
    00603  */
    00604 void KMainWindow::slotStateChanged(const QString &newstate,
    00605                                    KXMLGUIClient::ReverseStateChange reverse)
    00606 {
    00607   stateChanged(newstate, reverse);
    00608 }
    00609
    00610 /*
    00611  * Enable this for KDE 4.0
    00612  */
    00613 // void KMainWindow::slotStateChanged(const QString &newstate,
    00614 //                                    bool reverse)
    00615 // {
    00616 //   stateChanged(newstate,
    00617 //                reverse ? KXMLGUIClient::StateReverse : KXMLGUIClient::StateNoReverse);
    00618 // }
    00619
    00620 void KMainWindow::closeEvent ( QCloseEvent *e )
    00621 {
    00622     // Save settings if auto-save is enabled, and settings have changed
    00623     if (d->settingsDirty && d->autoSaveSettings)
    00624         saveAutoSaveSettings();
    00625
    00626     if (queryClose()) {
    00627         e->accept();
    00628
    00629         int not_withdrawn = 0;
    00630         QPtrListIterator<KMainWindow> it(*KMainWindow::memberList);
    00631         for (it.toFirst(); it.current(); ++it){
    00632             if ( !it.current()->isHidden() && it.current()->isTopLevel() && it.current() != this )
    00633                 not_withdrawn++;
    00634         }
    00635
    00636         if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted?
    00637             if ( queryExit() && !kapp->sessionSaving() && !d->shuttingDown ) { // Yes, Quit app?
    00638                 // don't call queryExit() twice
    00639                 disconnect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown()));
    00640                 d->shuttingDown = true;
    00641                 kapp->deref();             // ...and quit application.
    00642             }  else {
    00643                 // cancel closing, it's stupid to end up with no windows at all....
    00644                 e->ignore();
    00645             }
    00646         }
    00647     }
    00648 }
    00649
    00650 bool KMainWindow::queryExit()
    00651 {
    00652     return true;
    00653 }
    00654
    00655 bool KMainWindow::queryClose()
    00656 {
    00657     return true;
    00658 }
    00659
    00660 void KMainWindow::saveGlobalProperties( KConfig*  )
    00661 {
    00662 }
    00663
    00664 void KMainWindow::readGlobalProperties( KConfig*  )
    00665 {
    00666 }
    00667
    00668 #if defined(KDE_COMPAT)
    00669 void KMainWindow::updateRects()
    00670 {
    00671 }
    00672 #endif
    00673
    00674 void KMainWindow::showAboutApplication()
    00675 {
    00676 }
    00677
    00678 void KMainWindow::savePropertiesInternal( KConfig *config, int number )
    00679 {
    00680     bool oldASWS = d->autoSaveWindowSize;
    00681     d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size
    00682
    00683     QString s;
    00684     s.setNum(number);
    00685     s.prepend(QString::fromLatin1("WindowProperties"));
    00686     config->setGroup(s);
    00687
    00688     // store objectName, className, Width and Height  for later restoring
    00689     // (Only useful for session management)
    00690     config->writeEntry(QString::fromLatin1("ObjectName"), name());
    00691     config->writeEntry(QString::fromLatin1("ClassName"), className());
    00692
    00693     saveMainWindowSettings(config); // Menubar, statusbar and Toolbar settings.
    00694
    00695     s.setNum(number);
    00696     config->setGroup(s);
    00697     saveProperties(config);
    00698
    00699     d->autoSaveWindowSize = oldASWS;
    00700 }
    00701
    00702 void KMainWindow::saveMainWindowSettings(KConfig *config, const QString &configGroup)
    00703 {
    00704     kdDebug(200) << "KMainWindow::saveMainWindowSettings " << configGroup << endl;
    00705     QString oldGroup;
    00706
    00707     if (!configGroup.isEmpty())
    00708     {
    00709        oldGroup = config->group();
    00710        config->setGroup(configGroup);
    00711     }
    00712
    00713     // Called by session management - or if we want to save the window size anyway
    00714     if ( d->autoSaveWindowSize )
    00715         saveWindowSize( config );
    00716
    00717     QStatusBar* sb = internalStatusBar();
    00718     if (sb) {
    00719        if(!config->hasDefault("StatusBar") && !sb->isHidden() )
    00720            config->revertToDefault("StatusBar");
    00721        else
    00722            config->writeEntry("StatusBar", sb->isHidden() ? "Disabled" : "Enabled");
    00723     }
    00724
    00725     QMenuBar* mb = internalMenuBar();
    00726     if (mb) {
    00727        QString MenuBar = QString::fromLatin1("MenuBar");
    00728        if(!config->hasDefault("MenuBar") && !mb->isHidden() )
    00729            config->revertToDefault("MenuBar");
    00730        else
    00731            config->writeEntry("MenuBar", mb->isHidden() ? "Disabled" : "Enabled");
    00732     }
    00733
    00734     int n = 1; // Toolbar counter. toolbars are counted from 1,
    00735     KToolBar *toolbar = 0;
    00736     QPtrListIterator<KToolBar> it( toolBarIterator() );
    00737     while ( ( toolbar = it.current() ) ) {
    00738         ++it;
    00739         QString group;
    00740         if (!configGroup.isEmpty())
    00741         {
    00742            // Give a number to the toolbar, but prefer a name if there is one,
    00743            // because there's no real guarantee on the ordering of toolbars
    00744            group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name());
    00745            group.prepend(" Toolbar");
    00746            group.prepend(configGroup);
    00747         }
    00748         toolbar->saveSettings(config, group);
    00749         n++;
    00750     }
    00751     if (!configGroup.isEmpty())
    00752        config->setGroup(oldGroup);
    00753 }
    00754
    00755 void KMainWindow::setStandardToolBarMenuEnabled( bool enable )
    00756 {
    00757     if ( enable ) {
    00758         if ( d->toolBarHandler )
    00759             return;
    00760
    00761     d->toolBarHandler = new KDEPrivate::ToolBarHandler( this );
    00762
    00763     if ( factory() )
    00764         factory()->addClient( d->toolBarHandler );
    00765     } else {
    00766         if ( !d->toolBarHandler )
    00767             return;
    00768
    00769         if ( factory() )
    00770             factory()->removeClient( d->toolBarHandler );
    00771
    00772         delete d->toolBarHandler;
    00773         d->toolBarHandler = 0;
    00774     }
    00775 }
    00776
    00777 bool KMainWindow::isStandardToolBarMenuEnabled() const
    00778 {
    00779     return ( d->toolBarHandler );
    00780 }
    00781
    00782 void KMainWindow::createStandardStatusBarAction(){
    00783   if(!d->showStatusBarAction){
    00784     d->showStatusBarAction = KStdAction::showStatusbar(this, SLOT(setSettingsDirty()), actionCollection());
    00785     KStatusBar *sb = statusBar(); // Creates statusbar if it doesn't exist already.
    00786     connect(d->showStatusBarAction, SIGNAL(toggled(bool)), sb, SLOT(setShown(bool)));
    00787     d->showStatusBarAction->setChecked(sb->isHidden());
    00788   }
    00789 }
    00790
    00791 bool KMainWindow::readPropertiesInternal( KConfig *config, int number )
    00792 {
    00793     if ( number == 1 )
    00794         readGlobalProperties( config );
    00795
    00796     // in order they are in toolbar list
    00797     QString s;
    00798     s.setNum(number);
    00799     s.prepend(QString::fromLatin1("WindowProperties"));
    00800
    00801     config->setGroup(s);
    00802
    00803     // restore the object name (window role)
    00804     if ( config->hasKey(QString::fromLatin1("ObjectName" )) )
    00805         setName( config->readEntry(QString::fromLatin1("ObjectName")).latin1()); // latin1 is right here
    00806
    00807     applyMainWindowSettings(config); // Menubar, statusbar and toolbar settings.
    00808
    00809     s.setNum(number);
    00810     config->setGroup(s);
    00811     readProperties(config);
    00812     return true;
    00813 }
    00814
    00815 void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup)
    00816 {
    00817     return applyMainWindowSettings(config,configGroup,false);
    00818 }
    00819
    00820 void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup,bool force)
    00821 {
    00822     kdDebug(200) << "KMainWindow::applyMainWindowSettings" << endl;
    00823
    00824     KConfigGroupSaver saver( config, configGroup.isEmpty() ? config->group() : configGroup );
    00825
    00826     restoreWindowSize(config);
    00827
    00828     QStatusBar* sb = internalStatusBar();
    00829     if (sb) {
    00830         QString entry = config->readEntry("StatusBar", "Enabled");
    00831         if ( entry == "Disabled" )
    00832            sb->hide();
    00833         else
    00834            sb->show();
    00835         if(d->showStatusBarAction)
    00836             d->showStatusBarAction->setChecked(!sb->isHidden());
    00837     }
    00838
    00839     QMenuBar* mb = internalMenuBar();
    00840     if (mb) {
    00841         QString entry = config->readEntry ("MenuBar", "Enabled");
    00842         if ( entry == "Disabled" )
    00843            mb->hide();
    00844         else
    00845            mb->show();
    00846     }
    00847
    00848     int n = 1; // Toolbar counter. toolbars are counted from 1,
    00849     KToolBar *toolbar;
    00850     QPtrListIterator<KToolBar> it( toolBarIterator() ); // must use own iterator
    00851
    00852     for ( ; it.current(); ++it) {
    00853         toolbar= it.current();
    00854         QString group;
    00855         if (!configGroup.isEmpty())
    00856         {
    00857            // Give a number to the toolbar, but prefer a name if there is one,
    00858            // because there's no real guarantee on the ordering of toolbars
    00859            group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name());
    00860            group.prepend(" Toolbar");
    00861            group.prepend(configGroup);
    00862         }
    00863         toolbar->applySettings(config, group, force);
    00864         n++;
    00865     }
    00866
    00867     finalizeGUI( true );
    00868 }
    00869
    00870 void KMainWindow::finalizeGUI( bool force )
    00871 {
    00872     //kdDebug(200) << "KMainWindow::finalizeGUI force=" << force << endl;
    00873     // The whole reason for this is that moveToolBar relies on the indexes
    00874     // of the other toolbars, so in theory it should be called only once per
    00875     // toolbar, but in increasing order of indexes.
    00876     // Since we can't do that immediately, we move them, and _then_
    00877     // we call positionYourself again for each of them, but this time
    00878     // the toolbariterator should give them in the proper order.
    00879     // Both the XMLGUI and applySettings call this, hence "force" for the latter.
    00880     QPtrListIterator<KToolBar> it( toolBarIterator() );
    00881     for ( ; it.current() ; ++it ) {
    00882         it.current()->positionYourself( force );
    00883     }
    00884
    00885     d->settingsDirty = false;
    00886 }
    00887
    00888 void KMainWindow::saveWindowSize( KConfig * config ) const
    00889 {
    00890   int scnum = QApplication::desktop()->screenNumber(parentWidget());
    00891   QRect desk = QApplication::desktop()->screenGeometry(scnum);
    00892   int w, h;
    00893 #if defined Q_WS_X11
    00894   // save maximalization as desktop size + 1 in that direction
    00895   KWin::WindowInfo info = KWin::windowInfo( winId(), NET::WMState );
    00896   w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width();
    00897   h = info.state() & NET::MaxVert ? desk.height() + 1 : height();
    00898 #else
    00899   if (isMaximized()) {
    00900     w = desk.width() + 1;
    00901     h = desk.height() + 1;
    00902   }
    00903   //TODO: add "Maximized" property instead "+1" hack
    00904 #endif
    00905   QRect size( desk.width(), w, desk.height(), h );
    00906   bool defaultSize = (size == d->defaultWindowSize);
    00907   QString widthString = QString::fromLatin1("Width %1").arg(desk.width());
    00908   QString heightString = QString::fromLatin1("Height %1").arg(desk.height());
    00909   if (!config->hasDefault(widthString) && defaultSize)
    00910      config->revertToDefault(widthString);
    00911   else
    00912      config->writeEntry(widthString, w );
    00913
    00914   if (!config->hasDefault(heightString) && defaultSize)
    00915      config->revertToDefault(heightString);
    00916   else
    00917      config->writeEntry(heightString, h );
    00918 }
    00919
    00920 void KMainWindow::restoreWindowSize( KConfig * config )
    00921 {
    00922     if (d->care_about_geometry) {
    00923         parseGeometry(true);
    00924     } else {
    00925         // restore the size
    00926         int scnum = QApplication::desktop()->screenNumber(parentWidget());
    00927         QRect desk = QApplication::desktop()->screenGeometry(scnum);
    00928         if ( d->defaultWindowSize.isNull() ) // only once
    00929           d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); // store default values
    00930         QSize size( config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ),
    00931                     config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) );
    00932         if (size.isEmpty()) {
    00933             // try the KDE 2.0 way
    00934             size = QSize( config->readNumEntry( QString::fromLatin1("Width"), 0 ),
    00935                           config->readNumEntry( QString::fromLatin1("Height"), 0 ) );
    00936             if (!size.isEmpty()) {
    00937                 // make sure the other resolutions don't get old settings
    00938                 config->writeEntry( QString::fromLatin1("Width"), 0 );
    00939                 config->writeEntry( QString::fromLatin1("Height"), 0 );
    00940             }
    00941         }
    00942         if ( !size.isEmpty() ) {
    00943 #ifdef Q_WS_X11
    00944             int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 )
    00945                         | ( size.height() > desk.height() ? NET::MaxVert : 0 );
    00946             if(( state & NET::Max ) == NET::Max )
    00947                 ; // no resize
    00948             else if(( state & NET::MaxHoriz ) == NET::MaxHoriz )
    00949                 resize( width(), size.height());
    00950             else if(( state & NET::MaxVert ) == NET::MaxVert )
    00951                 resize( size.width(), height());
    00952             else
    00953                 resize( size );
    00954             // QWidget::showMaximized() is both insufficient and broken
    00955             KWin::setState( winId(), state );
    00956 #else
    00957             if (size.width() > desk.width() || size.height() > desk.height())
    00958               setWindowState( WindowMaximized );
    00959             else
    00960               resize( size );
    00961 #endif
    00962         }
    00963     }
    00964 }
    00965
    00966 bool KMainWindow::initialGeometrySet() const
    00967 {
    00968     return d->care_about_geometry;
    00969 }
    00970
    00971 void KMainWindow::ignoreInitialGeometry()
    00972 {
    00973     d->care_about_geometry = false;
    00974 }
    00975
    00976 void KMainWindow::setSettingsDirty()
    00977 {
    00978     //kdDebug(200) << "KMainWindow::setSettingsDirty" << endl;
    00979     d->settingsDirty = true;
    00980     if ( d->autoSaveSettings )
    00981     {
    00982         // Use a timer to save "immediately" user-wise, but not too immediately
    00983         // (to compress calls and save only once, in case of multiple changes)
    00984         if ( !d->settingsTimer )
    00985         {
    00986            d->settingsTimer = new QTimer( this );
    00987            connect( d->settingsTimer, SIGNAL( timeout() ), SLOT( saveAutoSaveSettings() ) );
    00988         }
    00989         d->settingsTimer->start( 500, true );
    00990     }
    00991 }
    00992
    00993 bool KMainWindow::settingsDirty() const
    00994 {
    00995     return d->settingsDirty;
    00996 }
    00997
    00998 QString KMainWindow::settingsGroup() const
    00999 {
    01000     return d->autoSaveGroup;
    01001 }
    01002
    01003 void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize )
    01004 {
    01005     d->autoSaveSettings = true;
    01006     d->autoSaveGroup = groupName;
    01007     d->autoSaveWindowSize = saveWindowSize;
    01008     // Get notified when the user moves a toolbar around
    01009     disconnect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ),
    01010                 this, SLOT( setSettingsDirty() ) );
    01011     connect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ),
    01012              this, SLOT( setSettingsDirty() ) );
    01013
    01014     // Now read the previously saved settings
    01015     applyMainWindowSettings( KGlobal::config(), groupName );
    01016 }
    01017
    01018 void KMainWindow::resetAutoSaveSettings()
    01019 {
    01020     d->autoSaveSettings = false;
    01021     if ( d->settingsTimer )
    01022         d->settingsTimer->stop();
    01023 }
    01024
    01025 bool KMainWindow::autoSaveSettings() const
    01026 {
    01027     return d->autoSaveSettings;
    01028 }
    01029
    01030 QString KMainWindow::autoSaveGroup() const
    01031 {
    01032     return d->autoSaveGroup;
    01033 }
    01034
    01035 void KMainWindow::saveAutoSaveSettings()
    01036 {
    01037     Q_ASSERT( d->autoSaveSettings );
    01038     //kdDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings" << endl;
    01039     saveMainWindowSettings( KGlobal::config(), d->autoSaveGroup );
    01040     KGlobal::config()->sync();
    01041     d->settingsDirty = false;
    01042     if ( d->settingsTimer )
    01043         d->settingsTimer->stop();
    01044 }
    01045
    01046 void KMainWindow::resizeEvent( QResizeEvent * )
    01047 {
    01048     if ( d->autoSaveWindowSize )
    01049         setSettingsDirty();
    01050 }
    01051
    01052 bool KMainWindow::hasMenuBar()
    01053 {
    01054     return (internalMenuBar());
    01055 }
    01056
    01057 KMenuBar *KMainWindow::menuBar()
    01058 {
    01059     KMenuBar * mb = internalMenuBar();
    01060     if ( !mb ) {
    01061         mb = new KMenuBar( this );
    01062         // trigger a re-layout and trigger a call to the private
    01063         // setMenuBar method.
    01064         QMainWindow::menuBar();
    01065     }
    01066     return mb;
    01067 }
    01068
    01069 KStatusBar *KMainWindow::statusBar()
    01070 {
    01071     KStatusBar * sb = internalStatusBar();
    01072     if ( !sb ) {
    01073         sb = new KStatusBar( this );
    01074         // trigger a re-layout and trigger a call to the private
    01075         // setStatusBar method.
    01076         QMainWindow::statusBar();
    01077     }
    01078     return sb;
    01079 }
    01080
    01081 void KMainWindow::shuttingDown()
    01082 {
    01083     // Needed for Qt <= 3.0.3 at least to prevent reentrancy
    01084     // when queryExit() shows a dialog. Check before removing!
    01085     static bool reentrancy_protection = false;
    01086     if (!reentrancy_protection)
    01087     {
    01088        reentrancy_protection = true;
    01089        // call the virtual queryExit
    01090        queryExit();
    01091        reentrancy_protection = false;
    01092     }
    01093
    01094 }
    01095
    01096 KMenuBar *KMainWindow::internalMenuBar()
    01097 {
    01098     QObjectList *l = queryList( "KMenuBar", 0, false, false );
    01099     if ( !l || !l->first() ) {
    01100         delete l;
    01101         return 0;
    01102     }
    01103
    01104     KMenuBar *m = (KMenuBar*)l->first();
    01105     delete l;
    01106     return m;
    01107 }
    01108
    01109 KStatusBar *KMainWindow::internalStatusBar()
    01110 {
    01111     QObjectList *l = queryList( "KStatusBar", 0, false, false );
    01112     if ( !l || !l->first() ) {
    01113         delete l;
    01114         return 0;
    01115     }
    01116
    01117     KStatusBar *s = (KStatusBar*)l->first();
    01118     delete l;
    01119     return s;
    01120 }
    01121
    01122 void KMainWindow::childEvent( QChildEvent* e)
    01123 {
    01124     QMainWindow::childEvent( e );
    01125 }
    01126
    01127 KToolBar *KMainWindow::toolBar( const char * name )
    01128 {
    01129     if (!name)
    01130        name = "mainToolBar";
    01131     KToolBar *tb = (KToolBar*)child( name, "KToolBar" );
    01132     if ( tb )
    01133         return tb;
    01134     bool honor_mode = (name == "mainToolBar");
    01135
    01136     if ( builderClient() )
    01137         return new KToolBar(this, name, honor_mode); // XMLGUI constructor
    01138     else
    01139         return new KToolBar(this, DockTop, false, name, honor_mode ); // non-XMLGUI
    01140 }
    01141
    01142 QPtrListIterator<KToolBar> KMainWindow::toolBarIterator()
    01143 {
    01144     toolbarList.clear();
    01145     QPtrList<QToolBar> lst;
    01146     for ( int i = (int)QMainWindow::DockUnmanaged; i <= (int)DockMinimized; ++i ) {
    01147         lst = toolBars( (ToolBarDock)i );
    01148         for ( QToolBar *tb = lst.first(); tb; tb = lst.next() ) {
    01149             if ( !tb->inherits( "KToolBar" ) )
    01150                 continue;
    01151             toolbarList.append( (KToolBar*)tb );
    01152         }
    01153     }
    01154     return QPtrListIterator<KToolBar>( toolbarList );
    01155 }
    01156
    01157 KAccel * KMainWindow::accel()
    01158 {
    01159     if ( !d->kaccel )
    01160         d->kaccel = new KAccel( this, "kmw-kaccel" );
    01161     return d->kaccel;
    01162 }
    01163
    01164 void KMainWindow::paintEvent( QPaintEvent * pe )
    01165 {
    01166     QMainWindow::paintEvent(pe); //Upcall to handle SH_MainWindow_SpaceBelowMenuBar rendering
    01167 }
    01168
    01169 QSize KMainWindow::sizeForCentralWidgetSize(QSize size)
    01170 {
    01171     KToolBar *tb = (KToolBar*)child( "mainToolBar", "KToolBar" );
    01172     if (tb && !tb->isHidden()) {
    01173         switch( tb->barPos() )
    01174         {
    01175           case KToolBar::Top:
    01176           case KToolBar::Bottom:
    01177             size += QSize(0, tb->sizeHint().height());
    01178             break;
    01179
    01180           case KToolBar::Left:
    01181           case KToolBar::Right:
    01182             size += QSize(toolBar()->sizeHint().width(), 0);
    01183             break;
    01184
    01185           case KToolBar::Flat:
    01186             size += QSize(0, 3+kapp->style().pixelMetric( QStyle::PM_DockWindowHandleExtent ));
    01187             break;
    01188
    01189           default:
    01190             break;
    01191         }
    01192     }
    01193     KMenuBar *mb = internalMenuBar();
    01194     if (mb && !mb->isHidden()) {
    01195         size += QSize(0,mb->heightForWidth(size.width()));
    01196         if (style().styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, this))
    01197            size += QSize( 0, dockWindowsMovable() ? 1 : 2);
    01198     }
    01199     QStatusBar *sb = internalStatusBar();
    01200     if( sb && !sb->isHidden() )
    01201        size += QSize(0, sb->sizeHint().height());
    01202
    01203     return size;
    01204 }
    01205
    01206 #if KDE_IS_VERSION( 3, 9, 0 )
    01207 #ifdef __GNUC__
    01208 #warning Remove, should be in Qt
    01209 #endif
    01210 #endif
    01211 void KMainWindow::setIcon( const QPixmap& p )
    01212 {
    01213     QMainWindow::setIcon( p );
    01214 #ifdef Q_WS_X11
    01215     // Qt3 doesn't support _NET_WM_ICON, but KApplication::setTopWidget(), which
    01216     // is used by KMainWindow, sets it
    01217     KWin::setIcons( winId(), p, QPixmap());
    01218 #endif
    01219 }
    01220
    01221 QPtrList<KMainWindow>* KMainWindow::getMemberList() { return memberList; }
    01222
    01223 // why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI;
    01224 // DF: because they compile KDE much faster :)
    01225 void KMainWindow::finalizeGUI( KXMLGUIClient *client )
    01226 { KXMLGUIBuilder::finalizeGUI( client ); }
    01227
    01228 void KMainWindow::virtual_hook( int id, void* data )
    01229 { KXMLGUIBuilder::virtual_hook( id, data );
    01230   KXMLGUIClient::virtual_hook( id, data ); }
    01231
    01232
    01233
    01234 #include "kmainwindow.moc"
    01235

This file is part of the documentation for kdeui Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:20:18 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003