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

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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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