• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDEUI

kmainwindow.cpp

Go to the documentation of this file.
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      (C) 2005-2006 Hamish Rodda (rodda@kde.org)
00010      (C) 2000-2008 David Faure (faure@kde.org)
00011 
00012      This library is free software; you can redistribute it and/or
00013      modify it under the terms of the GNU Library General Public
00014      License version 2 as published by the Free Software Foundation.
00015 
00016      This library is distributed in the hope that it will be useful,
00017      but WITHOUT ANY WARRANTY; without even the implied warranty of
00018      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019      Library General Public License for more details.
00020 
00021      You should have received a copy of the GNU Library General Public License
00022      along with this library; see the file COPYING.LIB.  If not, write to
00023      the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00024      Boston, MA 02110-1301, USA.
00025  */
00026 
00027 #include "kmainwindow.h"
00028 #include "kmainwindow_p.h"
00029 #include "kmainwindowiface_p.h"
00030 #include "ktoolbarhandler_p.h"
00031 #include "kcmdlineargs.h"
00032 #include "ktoggleaction.h"
00033 #include "ksessionmanager.h"
00034 #include "kstandardaction.h"
00035 
00036 #include <QtCore/QList>
00037 #include <QtCore/QObject>
00038 #include <QtCore/QTimer>
00039 #include <QtGui/QCloseEvent>
00040 #include <QtGui/QDesktopWidget>
00041 #include <QtGui/QDockWidget>
00042 #include <QtGui/QLayout>
00043 #include <QtGui/QSessionManager>
00044 #include <QtGui/QStyle>
00045 #include <QtGui/QWidget>
00046 
00047 #include <kaction.h>
00048 #include <kapplication.h>
00049 #include <kauthorized.h>
00050 #include <kconfig.h>
00051 #include <kdebug.h>
00052 #include <kdialog.h>
00053 #include <khelpmenu.h>
00054 #include <klocale.h>
00055 #include <kmenubar.h>
00056 #include <kstandarddirs.h>
00057 #include <kstatusbar.h>
00058 #include <ktoolbar.h>
00059 #include <kwindowsystem.h>
00060 #include <kconfiggroup.h>
00061 #include <kglobalsettings.h>
00062 
00063 #if defined Q_WS_X11
00064 #include <qx11info_x11.h>
00065 #include <netwm.h>
00066 #endif
00067 
00068 #include <stdlib.h>
00069 #include <ctype.h>
00070 #include <assert.h>
00071 
00072 #include <config.h>
00073 
00074 static bool no_query_exit = false;
00075 
00076 static KMenuBar *internalMenuBar(KMainWindow *mw)
00077 {
00078     return KGlobal::findDirectChild<KMenuBar *>(mw);
00079 }
00080 
00081 static KStatusBar *internalStatusBar(KMainWindow *mw)
00082 {
00083     // Don't use qFindChild here, it's recursive!
00084     // (== slow, but also finds konqueror's per-view statusbars)
00085     return KGlobal::findDirectChild<KStatusBar *>(mw);
00086 }
00087 
00095 class DockResizeListener : public QObject
00096 {
00097 public:
00098     DockResizeListener(KMainWindow *win);
00099     virtual ~DockResizeListener();
00100     virtual bool eventFilter(QObject *watched, QEvent *event);
00101 
00102 private:
00103     KMainWindow *m_win;
00104 };
00105 
00106 DockResizeListener::DockResizeListener(KMainWindow *win) :
00107     QObject(win),
00108     m_win(win)
00109 {
00110 }
00111 
00112 DockResizeListener::~DockResizeListener()
00113 {
00114 }
00115 
00116 bool DockResizeListener::eventFilter(QObject *watched, QEvent *event)
00117 {
00118     switch( event->type() ) {
00119     case QEvent::Resize:
00120     case QEvent::Move:
00121     case QEvent::Hide:
00122         m_win->k_ptr->setSettingsDirty(KMainWindowPrivate::CompressCalls);
00123         break;
00124 
00125     default:
00126         break;
00127     }
00128 
00129     return QObject::eventFilter(watched, event);
00130 }
00131 
00132 class KMWSessionManager : public KSessionManager
00133 {
00134 public:
00135     KMWSessionManager()
00136     {
00137     }
00138     ~KMWSessionManager()
00139     {
00140     }
00141     bool dummyInit() { return true; }
00142     bool saveState( QSessionManager& )
00143     {
00144         KConfig* config = KApplication::kApplication()->sessionConfig();
00145         if ( KMainWindow::memberList().count() ){
00146             // According to Jochen Wilhelmy <digisnap@cs.tu-berlin.de>, this
00147             // hook is useful for better document orientation
00148             KMainWindow::memberList().first()->saveGlobalProperties(config);
00149         }
00150 
00151         int n = 0;
00152         foreach (KMainWindow* mw, KMainWindow::memberList()) {
00153             n++;
00154             mw->savePropertiesInternal(config, n);
00155         }
00156 
00157         KConfigGroup group( config, "Number" );
00158         group.writeEntry("NumberOfWindows", n );
00159         return true;
00160     }
00161 
00162     bool commitData( QSessionManager& sm )
00163     {
00164         // not really a fast method but the only compatible one
00165         if ( sm.allowsInteraction() ) {
00166             bool canceled = false;
00167             ::no_query_exit = true;
00168 
00169             foreach (KMainWindow *window, KMainWindow::memberList()) {
00170                 if ( !window->testAttribute( Qt::WA_WState_Hidden ) ) {
00171                     QCloseEvent e;
00172                     QApplication::sendEvent( window, &e );
00173                     canceled = !e.isAccepted();
00174                     if (canceled)
00175                         break;
00176                     /* Don't even think_about deleting widgets with
00177                        Qt::WDestructiveClose flag set at this point. We
00178                        are faking a close event, but we are *not*_
00179                        closing the window. The purpose of the faked
00180                        close event is to prepare the application so it
00181                        can safely be quit without the user losing data
00182                        (possibly showing a message box "do you want to
00183                        save this or that?"). It is possible that the
00184                        session manager quits the application later
00185                        (emitting QApplication::aboutToQuit() when this
00186                        happens), but it is also possible that the user
00187                        cancels the shutdown, so the application will
00188                        continue to run.
00189                     */
00190                 }
00191             }
00192             ::no_query_exit = false;
00193             if (canceled)
00194                return false;
00195 
00196             KMainWindow* last = 0;
00197             foreach (KMainWindow *window, KMainWindow::memberList()) {
00198                 if ( !window->testAttribute( Qt::WA_WState_Hidden ) ) {
00199                     last = window;
00200                 }
00201             }
00202             if ( last )
00203                 return last->queryExit();
00204             // else
00205             return true;
00206         }
00207 
00208         // the user wants it, the user gets it
00209         return true;
00210     }
00211 };
00212 
00213 K_GLOBAL_STATIC(KMWSessionManager, ksm)
00214 K_GLOBAL_STATIC(QList<KMainWindow*>, sMemberList)
00215 static bool being_first = true;
00216 
00217 KMainWindow::KMainWindow( QWidget* parent, Qt::WFlags f )
00218     : QMainWindow(parent, f), k_ptr(new KMainWindowPrivate)
00219 {
00220     k_ptr->init(this);
00221 }
00222 
00223 KMainWindow::KMainWindow(KMainWindowPrivate &dd, QWidget *parent, Qt::WFlags f)
00224     : QMainWindow(parent, f), k_ptr(&dd)
00225 {
00226     k_ptr->init(this);
00227 }
00228 
00229 void KMainWindowPrivate::init(KMainWindow *_q)
00230 {
00231     KGlobal::ref();
00232 
00233     // We set allow quit to true when the first mainwindow is created, so that when the refcounting
00234     // reaches 0 the application can quit. We don't want this to happen before the first mainwindow
00235     // is created, otherwise running a job in main would exit the app too early.
00236     KGlobal::setAllowQuit(true);
00237 
00238     q = _q;
00239 
00240     q->setAnimated(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects);
00241 
00242     q->setAttribute( Qt::WA_DeleteOnClose );
00243 
00244     // We handle this functionality (quitting the app) ourselves, with KGlobal::ref/deref.
00245     // This makes apps stay alive even if they only have a systray icon visible, or
00246     // a progress widget with "keep open" checked, for instance.
00247     // So don't let the default Qt mechanism allow any toplevel widget to just quit the app on us.
00248     // Setting WA_QuitOnClose to false for all KMainWindows is not enough, any progress widget
00249     // or dialog box would still quit the app...
00250     if (qApp)
00251         qApp->setQuitOnLastWindowClosed(false);
00252 
00253     helpMenu = 0;
00254 
00255     //actionCollection()->setWidget( this );
00256     QObject::connect(qApp, SIGNAL(aboutToQuit()), q, SLOT(_k_shuttingDown()));
00257     QObject::connect(KGlobalSettings::self(), SIGNAL(settingsChanged(int)),
00258                      q, SLOT(_k_slotSettingsChanged(int)));
00259 
00260     // force KMWSessionManager creation - someone a better idea?
00261     ksm->dummyInit();
00262 
00263     sMemberList->append( q );
00264 
00265     settingsDirty = false;
00266     autoSaveSettings = false;
00267     autoSaveWindowSize = true; // for compatibility
00268     //d->kaccel = actionCollection()->kaccel();
00269     settingsTimer = 0;
00270     sizeTimer = 0;
00271     shuttingDown = false;
00272     if ((care_about_geometry = being_first)) {
00273         being_first = false;
00274 
00275         QString geometry;
00276         KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
00277         if (args && args->isSet("geometry"))
00278             geometry = args->getOption("geometry");
00279 
00280         if ( geometry.isNull() ) // if there is no geometry, it doesn't matter
00281             care_about_geometry = false;
00282         else
00283             q->parseGeometry(false);
00284     }
00285 
00286     q->setWindowTitle( KGlobal::caption() );
00287 
00288     dockResizeListener = new DockResizeListener(_q);
00289     letDirtySettings = true;
00290 
00291     sizeApplied = false;
00292 }
00293 
00294 static bool endsWithHashNumber( const QString& s )
00295 {
00296     for( int i = s.length() - 1;
00297          i > 0;
00298          --i )
00299     {
00300         if( s[ i ] == '#' && i != s.length() - 1 )
00301             return true; // ok
00302         if( !s[ i ].isDigit())
00303             break;
00304     }
00305     return false;
00306 }
00307 
00308 static inline bool isValidDBusObjectPathCharacter(const QChar &c)
00309 {
00310     register ushort u = c.unicode();
00311     return (u >= 'a' && u <= 'z')
00312             || (u >= 'A' && u <= 'Z')
00313             || (u >= '0' && u <= '9')
00314             || (u == '_') || (u == '/');
00315 }
00316 
00317 void KMainWindowPrivate::polish(KMainWindow *q)
00318 {
00319     // Set a unique object name. Required by session management, window management, and for the dbus interface.
00320     QString objname;
00321     QString s;
00322     int unusedNumber = 1;
00323     const QString name = q->objectName();
00324     bool startNumberingImmediately = true;
00325     bool tryReuse = false;
00326     if ( name.isEmpty() )
00327     {   // no name given
00328         objname = "MainWindow#";
00329     }
00330     else if( name.endsWith( QLatin1Char( '#' ) ) )
00331     {   // trailing # - always add a number  - KWin uses this for better grouping
00332         objname = name;
00333     }
00334     else if( endsWithHashNumber( name ))
00335     {   // trailing # with a number - like above, try to use the given number first
00336         objname = name;
00337         tryReuse = true;
00338         startNumberingImmediately = false;
00339     }
00340     else
00341     {
00342         objname = name;
00343         startNumberingImmediately = false;
00344     }
00345 
00346     s = objname;
00347     if ( startNumberingImmediately )
00348         s += '1';
00349 
00350     for(;;) {
00351         const QList<QWidget*> list = qApp->topLevelWidgets();
00352         bool found = false;
00353         foreach ( QWidget* w, list ) {
00354             if( w != q && w->objectName() == s )
00355             {
00356                 found = true;
00357                 break;
00358             }
00359         }
00360         if( !found )
00361             break;
00362         if( tryReuse ) {
00363             objname = name.left( name.length() - 1 ); // lose the hash
00364             unusedNumber = 0; // start from 1 below
00365             tryReuse = false;
00366         }
00367         s.setNum( ++unusedNumber );
00368         s = objname + s;
00369     }
00370     q->setObjectName( s );
00371     q->winId(); // workaround for setWindowRole() crashing, and set also window role, just in case TT
00372     q->setWindowRole( s ); // will keep insisting that object name suddenly should not be used for window role
00373 
00374     dbusName = '/' + qApp->applicationName() + '/' + q->objectName().replace(QLatin1Char('/'), QLatin1Char('_'));
00375     // Clean up for dbus usage: any non-alphanumeric char should be turned into '_'
00376     const int len = dbusName.length();
00377     for ( int i = 0; i < len; ++i ) {
00378         if ( !isValidDBusObjectPathCharacter( dbusName[i] ) )
00379             dbusName[i] = QLatin1Char('_');
00380     }
00381 
00382     QDBusConnection::sessionBus().registerObject(dbusName, q, QDBusConnection::ExportScriptableSlots |
00383                                        QDBusConnection::ExportScriptableProperties |
00384                                        QDBusConnection::ExportNonScriptableSlots |
00385                                        QDBusConnection::ExportNonScriptableProperties |
00386                                        QDBusConnection::ExportAdaptors);
00387 }
00388 
00389 void KMainWindowPrivate::setSettingsDirty(CallCompression callCompression)
00390 {
00391     if (!letDirtySettings) {
00392         return;
00393     }
00394 
00395     settingsDirty = true;
00396     if (autoSaveSettings) {
00397         if (callCompression == CompressCalls) {
00398             if (!settingsTimer) {
00399                 settingsTimer = new QTimer(q);
00400                 settingsTimer->setInterval(500);
00401                 settingsTimer->setSingleShot(true);
00402                 QObject::connect(settingsTimer, SIGNAL(timeout()), q, SLOT(saveAutoSaveSettings()));
00403             }
00404             settingsTimer->start();
00405         } else {
00406             q->saveAutoSaveSettings();
00407         }
00408     }
00409 }
00410 
00411 void KMainWindowPrivate::setSizeDirty()
00412 {
00413     if (autoSaveWindowSize) {
00414         if (!sizeTimer) {
00415             sizeTimer = new QTimer(q);
00416             sizeTimer->setInterval(500);
00417             sizeTimer->setSingleShot(true);
00418             QObject::connect(sizeTimer, SIGNAL(timeout()), q, SLOT(_k_slotSaveAutoSaveSize()));
00419         }
00420         sizeTimer->start();
00421     }
00422 }
00423 
00424 void KMainWindow::parseGeometry(bool parsewidth)
00425 {
00426     K_D(KMainWindow);
00427     QString cmdlineGeometry;
00428     KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
00429     if (args->isSet("geometry"))
00430         cmdlineGeometry = args->getOption("geometry");
00431 
00432     assert ( !cmdlineGeometry.isNull() );
00433     assert ( d->care_about_geometry );
00434     Q_UNUSED(d); // fix compiler warning in release mode
00435 
00436 #if defined Q_WS_X11
00437     int x, y;
00438     int w, h;
00439     int m = XParseGeometry( cmdlineGeometry.toLatin1(), &x, &y, (unsigned int*)&w, (unsigned int*)&h);
00440     if (parsewidth) {
00441         const QSize minSize = minimumSize();
00442         const QSize maxSize = maximumSize();
00443         if ( !(m & WidthValue) )
00444             w = width();
00445         if ( !(m & HeightValue) )
00446             h = height();
00447          w = qMin(w,maxSize.width());
00448          h = qMin(h,maxSize.height());
00449          w = qMax(w,minSize.width());
00450          h = qMax(h,minSize.height());
00451          resize(w, h);
00452     } else {
00453         if ( (m & XNegative) )
00454             x = KApplication::desktop()->width()  + x - w;
00455         else if ( (m & XValue) )
00456             x = geometry().x();
00457         if ( (m & YNegative) )
00458             y = KApplication::desktop()->height() + y - h;
00459         else if ( (m & YValue) )
00460             y = geometry().y();
00461 
00462         move(x, y);
00463     }
00464 #endif
00465 }
00466 
00467 KMainWindow::~KMainWindow()
00468 {
00469     sMemberList->removeAll( this );
00470     delete static_cast<QObject *>(k_ptr->dockResizeListener);  //so we don't get anymore events after k_ptr is destroyed
00471     delete k_ptr;
00472     KGlobal::deref();
00473 }
00474 
00475 KMenu* KMainWindow::helpMenu( const QString &aboutAppText, bool showWhatsThis )
00476 {
00477     K_D(KMainWindow);
00478     if(!d->helpMenu) {
00479         if ( aboutAppText.isEmpty() )
00480             d->helpMenu = new KHelpMenu( this, KGlobal::mainComponent().aboutData(), showWhatsThis);
00481         else
00482             d->helpMenu = new KHelpMenu( this, aboutAppText, showWhatsThis );
00483 
00484         if (!d->helpMenu)
00485             return 0;
00486     }
00487 
00488     return d->helpMenu->menu();
00489 }
00490 
00491 KMenu* KMainWindow::customHelpMenu( bool showWhatsThis )
00492 {
00493     K_D(KMainWindow);
00494     if (!d->helpMenu) {
00495         d->helpMenu = new KHelpMenu( this, QString(), showWhatsThis );
00496         connect(d->helpMenu, SIGNAL( showAboutApplication()),
00497                 this, SLOT( showAboutApplication() ));
00498     }
00499 
00500     return d->helpMenu->menu();
00501 }
00502 
00503 bool KMainWindow::canBeRestored( int number )
00504 {
00505     if ( !qApp->isSessionRestored() )
00506         return false;
00507     KConfig *config = kapp->sessionConfig();
00508     if ( !config )
00509         return false;
00510 
00511     KConfigGroup group( config, "Number" );
00512     const int n = group.readEntry( "NumberOfWindows", 1 );
00513     return number >= 1 && number <= n;
00514 }
00515 
00516 const QString KMainWindow::classNameOfToplevel( int number )
00517 {
00518     if ( !qApp->isSessionRestored() )
00519         return QString();
00520     KConfig *config = kapp->sessionConfig();
00521     if ( !config )
00522         return QString();
00523     QString s;
00524     s.setNum( number );
00525     s.prepend( QLatin1String("WindowProperties") );
00526 
00527     KConfigGroup group( config, s );
00528     if ( !group.hasKey( "ClassName" ) )
00529         return QString();
00530     else
00531         return group.readEntry( "ClassName" );
00532 }
00533 
00534 bool KMainWindow::restore( int number, bool show )
00535 {
00536     if ( !canBeRestored( number ) )
00537         return false;
00538     KConfig *config = kapp->sessionConfig();
00539     if ( readPropertiesInternal( config, number ) ){
00540         if ( show )
00541             KMainWindow::show();
00542         return false;
00543     }
00544     return false;
00545 }
00546 
00547 void KMainWindow::setCaption( const QString &caption )
00548 {
00549     setPlainCaption( KDialog::makeStandardCaption( caption, this ) );
00550 }
00551 
00552 void KMainWindow::setCaption( const QString &caption, bool modified )
00553 {
00554     KDialog::CaptionFlags flags = KDialog::HIGCompliantCaption;
00555 
00556     if ( modified )
00557     {
00558         flags |= KDialog::ModifiedCaption;
00559     }
00560 
00561     setPlainCaption( KDialog::makeStandardCaption(caption, this, flags) );
00562 }
00563 
00564 void KMainWindow::setPlainCaption( const QString &caption )
00565 {
00566     setWindowTitle(caption);
00567 }
00568 
00569 void KMainWindow::appHelpActivated( void )
00570 {
00571     K_D(KMainWindow);
00572     if( !d->helpMenu ) {
00573         d->helpMenu = new KHelpMenu( this );
00574         if ( !d->helpMenu )
00575             return;
00576     }
00577     d->helpMenu->appHelpActivated();
00578 }
00579 
00580 void KMainWindow::closeEvent ( QCloseEvent *e )
00581 {
00582     K_D(KMainWindow);
00583 
00584     // Save settings if auto-save is enabled, and settings have changed
00585     if (d->settingsTimer && d->settingsTimer->isActive()) {
00586         d->settingsTimer->stop();
00587         saveAutoSaveSettings();
00588     }
00589     if (d->sizeTimer && d->sizeTimer->isActive()) {
00590         d->sizeTimer->stop();
00591         d->_k_slotSaveAutoSaveSize();
00592     }
00593 
00594     if (queryClose()) {
00595         e->accept();
00596 
00597         int not_withdrawn = 0;
00598         foreach (KMainWindow* mw, KMainWindow::memberList()) {
00599             if ( !mw->isHidden() && mw->isTopLevel() && mw != this )
00600                 not_withdrawn++;
00601         }
00602 
00603         if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted?
00604             if (!( queryExit() && ( !kapp || !kapp->sessionSaving() ) && !d->shuttingDown )) {
00605               // cancel closing, it's stupid to end up with no windows at all....
00606               e->ignore();
00607             }
00608         }
00609     } else e->ignore(); //if the window should not be closed, don't close it
00610 }
00611 
00612 bool KMainWindow::queryExit()
00613 {
00614     return true;
00615 }
00616 
00617 bool KMainWindow::queryClose()
00618 {
00619     return true;
00620 }
00621 
00622 void KMainWindow::saveGlobalProperties( KConfig*  )
00623 {
00624 }
00625 
00626 void KMainWindow::readGlobalProperties( KConfig*  )
00627 {
00628 }
00629 
00630 void KMainWindow::showAboutApplication()
00631 {
00632 }
00633 
00634 void KMainWindow::savePropertiesInternal( KConfig *config, int number )
00635 {
00636     K_D(KMainWindow);
00637     const bool oldASWS = d->autoSaveWindowSize;
00638     d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size
00639 
00640     QString s;
00641     s.setNum(number);
00642     s.prepend(QLatin1String("WindowProperties"));
00643     KConfigGroup cg(config, s);
00644 
00645     // store objectName, className, Width and Height  for later restoring
00646     // (Only useful for session management)
00647     cg.writeEntry(QLatin1String("ObjectName"), objectName());
00648     cg.writeEntry(QLatin1String("ClassName"), metaObject()->className());
00649 
00650     saveMainWindowSettings(cg); // Menubar, statusbar and Toolbar settings.
00651 
00652     s.setNum(number);
00653     cg = KConfigGroup(config, s);
00654     saveProperties(cg);
00655 
00656     d->autoSaveWindowSize = oldASWS;
00657 }
00658 
00659 void KMainWindow::saveMainWindowSettings(const KConfigGroup &_cg)
00660 {
00661     K_D(KMainWindow);
00662     //kDebug(200) << "KMainWindow::saveMainWindowSettings " << _cg.name();
00663 
00664     // Called by session management - or if we want to save the window size anyway
00665     if ( d->autoSaveWindowSize )
00666         saveWindowSize( _cg );
00667 
00668     KConfigGroup cg(_cg); // for saving
00669 
00670     // One day will need to save the version number, but for now, assume 0
00671     // Utilise the QMainWindow::saveState() functionality.
00672     const QByteArray state = saveState();
00673     cg.writeEntry(QString("State"), state.toBase64());
00674 
00675     QStatusBar* sb = internalStatusBar(this);
00676     if (sb) {
00677        if(!cg.hasDefault("StatusBar") && !sb->isHidden() )
00678            cg.revertToDefault("StatusBar");
00679        else
00680            cg.writeEntry("StatusBar", sb->isHidden() ? "Disabled" : "Enabled");
00681     }
00682 
00683     QMenuBar* mb = internalMenuBar(this);
00684     if (mb) {
00685        const QString MenuBar = QLatin1String("MenuBar");
00686        if(!cg.hasDefault("MenuBar") && !mb->isHidden() )
00687            cg.revertToDefault("MenuBar");
00688        else
00689            cg.writeEntry("MenuBar", mb->isHidden() ? "Disabled" : "Enabled");
00690     }
00691 
00692     if ( !autoSaveSettings() || cg.name() == autoSaveGroup() ) { // TODO should be cg == d->autoSaveGroup, to compare both kconfig and group name
00693         if(!cg.hasDefault("ToolBarsMovable") && !KToolBar::toolBarsLocked())
00694             cg.revertToDefault("ToolBarsMovable");
00695         else
00696             cg.writeEntry("ToolBarsMovable", KToolBar::toolBarsLocked() ? "Disabled" : "Enabled");
00697     }
00698 
00699     int n = 1; // Toolbar counter. toolbars are counted from 1,
00700     foreach (KToolBar* toolbar, toolBars()) {
00701         QString group("Toolbar");
00702         // Give a number to the toolbar, but prefer a name if there is one,
00703         // because there's no real guarantee on the ordering of toolbars
00704         group += (toolbar->objectName().isEmpty() ? QString::number(n) : QString(" ")+toolbar->objectName());
00705 
00706         KConfigGroup toolbarGroup(&cg, group);
00707         toolbar->saveSettings(toolbarGroup);
00708         n++;
00709     }
00710 }
00711 
00712 bool KMainWindow::readPropertiesInternal( KConfig *config, int number )
00713 {
00714     K_D(KMainWindow);
00715 
00716     const bool oldLetDirtySettings = d->letDirtySettings;
00717     d->letDirtySettings = false;
00718 
00719     if ( number == 1 )
00720         readGlobalProperties( config );
00721 
00722     // in order they are in toolbar list
00723     QString s;
00724     s.setNum(number);
00725     s.prepend(QLatin1String("WindowProperties"));
00726 
00727     KConfigGroup cg(config, s);
00728 
00729     // restore the object name (window role)
00730     if ( cg.hasKey(QLatin1String("ObjectName" )) )
00731         setObjectName( cg.readEntry("ObjectName").toLatin1()); // latin1 is right here
00732 
00733     d->sizeApplied = false; // since we are changing config file, reload the size of the window
00734                             // if necessary. Do it before the call to applyMainWindowSettings.
00735     applyMainWindowSettings(cg); // Menubar, statusbar and toolbar settings.
00736 
00737     s.setNum(number);
00738     KConfigGroup grp(config, s);
00739     readProperties(grp);
00740 
00741     d->letDirtySettings = oldLetDirtySettings;
00742 
00743     return true;
00744 }
00745 
00746 void KMainWindow::applyMainWindowSettings(const KConfigGroup &cg, bool force)
00747 {
00748     K_D(KMainWindow);
00749     kDebug(200) << "KMainWindow::applyMainWindowSettings " << cg.name();
00750 
00751     QWidget *focusedWidget = QApplication::focusWidget();
00752 
00753     const bool oldLetDirtySettings = d->letDirtySettings;
00754     d->letDirtySettings = false;
00755 
00756     if (!d->sizeApplied) {
00757         restoreWindowSize(cg);
00758         d->sizeApplied = true;
00759     }
00760 
00761     QStatusBar* sb = internalStatusBar(this);
00762     if (sb) {
00763         QString entry = cg.readEntry("StatusBar", "Enabled");
00764         if ( entry == "Disabled" )
00765            sb->hide();
00766         else
00767            sb->show();
00768     }
00769 
00770     QMenuBar* mb = internalMenuBar(this);
00771     if (mb) {
00772         QString entry = cg.readEntry ("MenuBar", "Enabled");
00773         if ( entry == "Disabled" )
00774            mb->hide();
00775         else
00776            mb->show();
00777     }
00778 
00779     if ( !autoSaveSettings() || cg.name() == autoSaveGroup() ) { // TODO should be cg == d->autoSaveGroup, to compare both kconfig and group name
00780         QString entry = cg.readEntry ("ToolBarsMovable", "Disabled");
00781         if ( entry == "Disabled" )
00782             KToolBar::setToolBarsLocked(true);
00783         else
00784             KToolBar::setToolBarsLocked(false);
00785     }
00786 
00787     int n = 1; // Toolbar counter. toolbars are counted from 1,
00788     foreach (KToolBar* toolbar, toolBars()) {
00789         QString group("Toolbar");
00790         // Give a number to the toolbar, but prefer a name if there is one,
00791         // because there's no real guarantee on the ordering of toolbars
00792         group += (toolbar->objectName().isEmpty() ? QString::number(n) : QString(" ")+toolbar->objectName());
00793 
00794         KConfigGroup toolbarGroup(&cg, group);
00795         toolbar->applySettings(toolbarGroup, force);
00796         n++;
00797     }
00798 
00799     QByteArray state;
00800     if (cg.hasKey("State")) {
00801         state = cg.readEntry("State", state);
00802         state = QByteArray::fromBase64(state);
00803         // One day will need to load the version number, but for now, assume 0
00804         restoreState(state);
00805     }
00806 
00807     if (focusedWidget) {
00808         focusedWidget->setFocus();
00809     }
00810 
00811     d->settingsDirty = false;
00812     d->letDirtySettings = oldLetDirtySettings;
00813 }
00814 
00815 #ifdef Q_WS_WIN
00816 
00817 /*
00818  The win32 implementation for restoring/savin windows size differs
00819  from the unix/max implementation in three topics:
00820 
00821 1. storing and restoring the position, which may not work on x11
00822     see http://doc.trolltech.com/4.3/geometry.html#x11-peculiarities
00823 2. using QWidget::saveGeometry() and QWidget::restoreGeometry()
00824     this would probably be usable on x11 and/or on mac, but I'm unable to
00825     check this on unix/mac, so I leave this fix to the x11/mac experts.
00826 3. store geometry separately for each resolution -> on unix/max the size
00827     and with of the window are already saved separately on non windows
00828     system although not using ...Geometry functions -> could also be
00829     fixed by x11/mac experts.
00830 */
00831 void KMainWindow::restoreWindowSize( const KConfigGroup & _cg )
00832 {
00833     K_D(KMainWindow);
00834 
00835     int scnum = QApplication::desktop()->screenNumber(parentWidget());
00836     QRect desk = QApplication::desktop()->screenGeometry(scnum);
00837 
00838     // if the desktop is virtual then use virtual screen size
00839     if (QApplication::desktop()->isVirtualDesktop())
00840       desk = QApplication::desktop()->screenGeometry(QApplication::desktop()->screen());
00841 
00842     QString geometryKey = QString::fromLatin1("geometry-%1-%2").arg(desk.width()).arg(desk.height());
00843     QByteArray geometry = _cg.readEntry( geometryKey, QByteArray() );
00844     // if first time run, center window
00845     if (!restoreGeometry( QByteArray::fromBase64(geometry) ))
00846         move( (desk.width()-width())/2, (desk.height()-height())/2 );
00847 }
00848 
00849 void KMainWindow::saveWindowSize( const KConfigGroup & _cg ) const
00850 {
00851     K_D(const KMainWindow);
00852     int scnum = QApplication::desktop()->screenNumber(parentWidget());
00853     QRect desk = QApplication::desktop()->screenGeometry(scnum);
00854 
00855     // if the desktop is virtual then use virtual screen size
00856     if (QApplication::desktop()->isVirtualDesktop())
00857         desk = QApplication::desktop()->screenGeometry(QApplication::desktop()->screen());
00858 
00859     // geometry is saved separately for each resolution
00860     QString geometryKey = QString::fromLatin1("geometry-%1-%2").arg(desk.width()).arg(desk.height());
00861     QByteArray geometry = saveGeometry();
00862     KConfigGroup cg(_cg);
00863     cg.writeEntry( geometryKey, geometry.toBase64() );
00864 }
00865 #else
00866 void KMainWindow::saveWindowSize( const KConfigGroup & _cg ) const
00867 {
00868     K_D(const KMainWindow);
00869     int scnum = QApplication::desktop()->screenNumber(parentWidget());
00870     QRect desk = QApplication::desktop()->screenGeometry(scnum);
00871 
00872     // if the desktop is virtual then use virtual screen size
00873     if (QApplication::desktop()->isVirtualDesktop())
00874         desk = QApplication::desktop()->screenGeometry(QApplication::desktop()->screen());
00875 
00876     int w, h;
00877 #if defined Q_WS_X11
00878     // save maximalization as desktop size + 1 in that direction
00879     KWindowInfo info = KWindowSystem::windowInfo( winId(), NET::WMState );
00880     w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width();
00881     h = info.state() & NET::MaxVert ? desk.height() + 1 : height();
00882 #else
00883     if (isMaximized()) {
00884         w = desk.width() + 1;
00885         h = desk.height() + 1;
00886     } else {
00887         w = width();
00888         h = height();
00889     }
00890     //TODO: add "Maximized" property instead "+1" hack
00891 #endif
00892     KConfigGroup cg(_cg);
00893 
00894     QRect size( desk.width(), w, desk.height(), h );
00895     bool defaultSize = (size == d->defaultWindowSize);
00896     QString widthString = QString::fromLatin1("Width %1").arg(desk.width());
00897     QString heightString = QString::fromLatin1("Height %1").arg(desk.height());
00898     if (!cg.hasDefault(widthString) && defaultSize)
00899         cg.revertToDefault(widthString);
00900     else
00901         cg.writeEntry(widthString, w );
00902 
00903     if (!cg.hasDefault(heightString) && defaultSize)
00904         cg.revertToDefault(heightString);
00905     else
00906         cg.writeEntry(heightString, h );
00907 }
00908 
00909 void KMainWindow::restoreWindowSize( const KConfigGroup & config )
00910 {
00911     K_D(KMainWindow);
00912     if (d->care_about_geometry) {
00913         parseGeometry(true);
00914     } else {
00915         // restore the size
00916         const int scnum = QApplication::desktop()->screenNumber(parentWidget());
00917         QRect desk = QApplication::desktop()->screenGeometry(scnum);
00918 
00919         // if the desktop is virtual then use virtual screen size
00920         if (QApplication::desktop()->isVirtualDesktop())
00921           desk = QApplication::desktop()->screenGeometry(QApplication::desktop()->screen());
00922 
00923         if ( d->defaultWindowSize.isNull() ) // only once
00924           d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); // store default values
00925         const QSize size( config.readEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ),
00926                     config.readEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) );
00927         if ( !size.isEmpty() ) {
00928 #ifdef Q_WS_X11
00929             int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 )
00930                         | ( size.height() > desk.height() ? NET::MaxVert : 0 );
00931             if(( state & NET::Max ) == NET::Max )
00932                 resize( desk.width(), desk.height() ); // WORKAROUND: this should not be needed. KWindowSystem::setState
00933                                                        //             should be enough for maximizing. (ereslibre)
00934             else if(( state & NET::MaxHoriz ) == NET::MaxHoriz )
00935                 resize( desk.width(), size.height() );
00936             else if(( state & NET::MaxVert ) == NET::MaxVert )
00937                 resize( size.width(), desk.height() );
00938             else
00939                 resize( size );
00940             // QWidget::showMaximized() is both insufficient and broken
00941             KWindowSystem::setState( winId(), state );
00942 #else
00943             if (size.width() > desk.width() || size.height() > desk.height())
00944               setWindowState( Qt::WindowMaximized );
00945             else
00946               resize( size );
00947 #endif
00948         }
00949     }
00950 }
00951 #endif
00952 
00953 bool KMainWindow::initialGeometrySet() const
00954 {
00955     K_D(const KMainWindow);
00956     return d->care_about_geometry;
00957 }
00958 
00959 void KMainWindow::ignoreInitialGeometry()
00960 {
00961     K_D(KMainWindow);
00962     d->care_about_geometry = false;
00963 }
00964 
00965 void KMainWindow::setSettingsDirty()
00966 {
00967     K_D(KMainWindow);
00968     d->setSettingsDirty();
00969 }
00970 
00971 bool KMainWindow::settingsDirty() const
00972 {
00973     K_D(const KMainWindow);
00974     return d->settingsDirty;
00975 }
00976 
00977 void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize )
00978 {
00979     setAutoSaveSettings(KConfigGroup(KGlobal::config(), groupName), saveWindowSize);
00980 }
00981 
00982 void KMainWindow::setAutoSaveSettings( const KConfigGroup & group,
00983                                        bool saveWindowSize )
00984 {
00985     K_D(KMainWindow);
00986     d->autoSaveSettings = true;
00987     d->autoSaveGroup = group;
00988     d->autoSaveWindowSize = saveWindowSize;
00989 
00990     if (!saveWindowSize && d->sizeTimer) {
00991         d->sizeTimer->stop();
00992     }
00993 
00994     // Now read the previously saved settings
00995     applyMainWindowSettings(d->autoSaveGroup);
00996 }
00997 
00998 void KMainWindow::resetAutoSaveSettings()
00999 {
01000     K_D(KMainWindow);
01001     d->autoSaveSettings = false;
01002     if (d->settingsTimer) {
01003         d->settingsTimer->stop();
01004     }
01005 }
01006 
01007 bool KMainWindow::autoSaveSettings() const
01008 {
01009     K_D(const KMainWindow);
01010     return d->autoSaveSettings;
01011 }
01012 
01013 QString KMainWindow::autoSaveGroup() const
01014 {
01015     K_D(const KMainWindow);
01016     return d->autoSaveSettings ? d->autoSaveGroup.name() : QString();
01017 }
01018 
01019 KConfigGroup KMainWindow::autoSaveConfigGroup() const
01020 {
01021     K_D(const KMainWindow);
01022     return d->autoSaveSettings ? d->autoSaveGroup : KConfigGroup();
01023 }
01024 
01025 void KMainWindow::saveAutoSaveSettings()
01026 {
01027     K_D(KMainWindow);
01028     Q_ASSERT( d->autoSaveSettings );
01029     //kDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings";
01030     saveMainWindowSettings(d->autoSaveGroup);
01031     d->autoSaveGroup.sync();
01032     d->settingsDirty = false;
01033 }
01034 
01035 bool KMainWindow::event( QEvent* ev )
01036 {
01037     K_D(KMainWindow);
01038     switch( ev->type() ) {
01039 #ifdef Q_WS_WIN
01040     case QEvent::Move:
01041 #endif
01042     case QEvent::Resize:
01043         d->setSizeDirty();
01044         break;
01045     case QEvent::Polish:
01046         d->polish(this);
01047         break;
01048     case QEvent::ChildPolished:
01049         {
01050             QChildEvent *event = static_cast<QChildEvent*>(ev);
01051             QDockWidget *dock = qobject_cast<QDockWidget*>(event->child());
01052             KToolBar *toolbar = qobject_cast<KToolBar*>(event->child());
01053             QMenuBar *menubar = qobject_cast<QMenuBar*>(event->child());
01054             if (dock) {
01055                 connect(dock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
01056                         this, SLOT(setSettingsDirty()));
01057                 connect(dock, SIGNAL(visibilityChanged(bool)),
01058                         this, SLOT(setSettingsDirty()), Qt::QueuedConnection);
01059                 connect(dock, SIGNAL(topLevelChanged(bool)),
01060                         this, SLOT(setSettingsDirty()));
01061 
01062                 // there is no signal emitted if the size of the dock changes,
01063                 // hence install an event filter instead
01064                 dock->installEventFilter(k_ptr->dockResizeListener);
01065             } else if (toolbar) {
01066                 // there is no signal emitted if the size of the toolbar changes,
01067                 // hence install an event filter instead
01068                 toolbar->installEventFilter(k_ptr->dockResizeListener);
01069             } else if (menubar) {
01070                 // there is no signal emitted if the size of the menubar changes,
01071                 // hence install an event filter instead
01072                 menubar->installEventFilter(k_ptr->dockResizeListener);
01073             }
01074         }
01075         break;
01076     case QEvent::ChildRemoved:
01077         {
01078             QChildEvent *event = static_cast<QChildEvent*>(ev);
01079             QDockWidget *dock = qobject_cast<QDockWidget*>(event->child());
01080             KToolBar *toolbar = qobject_cast<KToolBar*>(event->child());
01081             QMenuBar *menubar = qobject_cast<QMenuBar*>(event->child());
01082             if (dock) {
01083                 disconnect(dock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
01084                            this, SLOT(setSettingsDirty()));
01085                 disconnect(dock, SIGNAL(visibilityChanged(bool)),
01086                            this, SLOT(setSettingsDirty()));
01087                 disconnect(dock, SIGNAL(topLevelChanged(bool)),
01088                            this, SLOT(setSettingsDirty()));
01089                 dock->removeEventFilter(k_ptr->dockResizeListener);
01090             } else if (toolbar) {
01091                 toolbar->removeEventFilter(k_ptr->dockResizeListener);
01092             } else if (menubar) {
01093                 menubar->removeEventFilter(k_ptr->dockResizeListener);
01094             }
01095         }
01096         break;
01097     default:
01098         break;
01099     }
01100     return QMainWindow::event( ev );
01101 }
01102 
01103 bool KMainWindow::hasMenuBar()
01104 {
01105     return internalMenuBar(this);
01106 }
01107 
01108 KMenuBar *KMainWindow::menuBar()
01109 {
01110     KMenuBar * mb = internalMenuBar(this);
01111     if ( !mb ) {
01112         mb = new KMenuBar( this );
01113         // trigger a re-layout and trigger a call to the private
01114         // setMenuBar method.
01115         setMenuBar(mb);
01116     }
01117     return mb;
01118 }
01119 
01120 KStatusBar *KMainWindow::statusBar()
01121 {
01122     KStatusBar * sb = internalStatusBar(this);
01123     if ( !sb ) {
01124         sb = new KStatusBar( this );
01125         // trigger a re-layout and trigger a call to the private
01126         // setStatusBar method.
01127         setStatusBar(sb);
01128     }
01129     return sb;
01130 }
01131 
01132 void KMainWindowPrivate::_k_shuttingDown()
01133 {
01134     // Needed for Qt <= 3.0.3 at least to prevent reentrancy
01135     // when queryExit() shows a dialog. Check before removing!
01136     static bool reentrancy_protection = false;
01137     if (!reentrancy_protection)
01138     {
01139        reentrancy_protection = true;
01140        shuttingDown = true;
01141        // call the virtual queryExit
01142        q->queryExit();
01143        reentrancy_protection = false;
01144     }
01145 }
01146 
01147 void KMainWindowPrivate::_k_slotSettingsChanged(int category)
01148 {
01149     Q_UNUSED(category);
01150 
01151     // This slot will be called when the style KCM changes settings that need
01152     // to be set on the already running applications.
01153 
01154     // At this level (KMainWindow) the only thing we need to restore is the
01155     // animations setting (whether the user wants builtin animations or not).
01156 
01157     q->setAnimated(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects);
01158 }
01159 
01160 void KMainWindowPrivate::_k_slotSaveAutoSaveSize()
01161 {
01162     if (autoSaveGroup.isValid()) {
01163         q->saveWindowSize(autoSaveGroup);
01164     }
01165 }
01166 
01167 KToolBar *KMainWindow::toolBar( const QString& name )
01168 {
01169     QString childName = name;
01170     if (childName.isEmpty())
01171        childName = "mainToolBar";
01172 
01173     KToolBar *tb = findChild<KToolBar*>(childName);
01174     if ( tb )
01175         return tb;
01176 
01177     KToolBar* toolbar = new KToolBar(childName, this); // non-XMLGUI toolbar
01178     return toolbar;
01179 }
01180 
01181 QList<KToolBar*> KMainWindow::toolBars() const
01182 {
01183     QList<KToolBar*> ret;
01184 
01185     foreach (QObject* child, children())
01186         if (KToolBar* toolBar = qobject_cast<KToolBar*>(child))
01187             ret.append(toolBar);
01188 
01189     return ret;
01190 }
01191 
01192 QList<KMainWindow*> KMainWindow::memberList() { return *sMemberList; }
01193 
01194 QString KMainWindow::dbusName() const
01195 {
01196     return k_func()->dbusName;
01197 }
01198 
01199 #include "kmainwindow.moc"
01200 

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal