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 "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 
KDE Logo
This file is part of the documentation for kdeui Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Jul 21 13:14:03 2006 by doxygen 1.4.0 written by Dimitri van Heesch, © 1997-2003