• Skip to content
  • Skip to link menu
KDE 4.1 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, so when the refcounting reaches 0 the application instance will
00230     // be exited. This has a similar purpose than setQuitOnLastWindowClosed (from
00231     // QApplication), but it honors (de)refing from KGlobal.
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     shuttingDown = false;
00269     if ((care_about_geometry = being_first)) {
00270         being_first = false;
00271 
00272         QString geometry;
00273         KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
00274         if (args && args->isSet("geometry"))
00275             geometry = args->getOption("geometry");
00276 
00277         if ( geometry.isNull() ) // if there is no geometry, it doesn't matter
00278             care_about_geometry = false;
00279         else
00280             q->parseGeometry(false);
00281     }
00282 
00283     q->setWindowTitle( KGlobal::caption() );
00284 
00285     dockResizeListener = new DockResizeListener(_q);
00286     letDirtySettings = true;
00287 
00288     sizeApplied = false;
00289 }
00290 
00291 static bool endsWithHashNumber( const QString& s )
00292 {
00293     for( int i = s.length() - 1;
00294          i > 0;
00295          --i )
00296     {
00297         if( s[ i ] == '#' && i != s.length() - 1 )
00298             return true; // ok
00299         if( !s[ i ].isDigit())
00300             break;
00301     }
00302     return false;
00303 }
00304 
00305 void KMainWindowPrivate::polish(KMainWindow *q)
00306 {
00307     // Set a unique object name. Required by session management, window management, and for the dbus interface.
00308     QString objname;
00309     QString s;
00310     int unusedNumber = 1;
00311     const QString name = q->objectName();
00312     bool startNumberingImmediately = true;
00313     bool tryReuse = false;
00314     if ( name.isEmpty() )
00315     {   // no name given
00316         objname = "MainWindow#";
00317     }
00318     else if( name.endsWith( QLatin1Char( '#' ) ) )
00319     {   // trailing # - always add a number  - KWin uses this for better grouping
00320         objname = name;
00321     }
00322     else if( endsWithHashNumber( name ))
00323     {   // trailing # with a number - like above, try to use the given number first
00324         objname = name;
00325         tryReuse = true;
00326         startNumberingImmediately = false;
00327     }
00328     else
00329     {
00330         objname = name;
00331         startNumberingImmediately = false;
00332     }
00333 
00334     s = objname;
00335     if ( startNumberingImmediately )
00336         s += '1';
00337 
00338     for(;;) {
00339         QList<QWidget*> list = qApp->topLevelWidgets();
00340         bool found = false;
00341         foreach ( QWidget* w, list ) {
00342             if( w != q && w->objectName() == s )
00343             {
00344                 found = true;
00345                 break;
00346             }
00347         }
00348         if( !found )
00349             break;
00350         if( tryReuse ) {
00351             objname = name.left( name.length() - 1 ); // lose the hash
00352             unusedNumber = 0; // start from 1 below
00353             tryReuse = false;
00354         }
00355         s.setNum( ++unusedNumber );
00356         s = objname + s;
00357     }
00358     q->setObjectName( s );
00359     q->winId(); // workaround for setWindowRole() crashing, and set also window role, just in case TT
00360     q->setWindowRole( s ); // will keep insisting that object name suddenly should not be used for window role
00361 
00362     QString pathname = q->objectName();
00363     // Clean up for dbus usage: any non-alphanumeric char should be turned into '_'
00364     const int len = pathname.length();
00365     for ( int i = 0; i < len; ++i ) {
00366         if ( !pathname[i].isLetterOrNumber() )
00367             pathname[i] = QLatin1Char('_');
00368     }
00369     pathname = '/' + qApp->applicationName() + '/' + pathname;
00370 
00371     dbusName = pathname;
00372     QDBusConnection::sessionBus().registerObject(dbusName, q, QDBusConnection::ExportScriptableSlots |
00373                                        QDBusConnection::ExportScriptableProperties |
00374                                        QDBusConnection::ExportNonScriptableSlots |
00375                                        QDBusConnection::ExportNonScriptableProperties |
00376                                        QDBusConnection::ExportAdaptors);
00377 }
00378 
00379 void KMainWindowPrivate::setSettingsDirty(CallCompression callCompression)
00380 {
00381     if (!letDirtySettings) {
00382         return;
00383     }
00384 
00385     settingsDirty = true;
00386     if (autoSaveSettings) {
00387         if (callCompression == CompressCalls) {
00388             if (!settingsTimer) {
00389                 settingsTimer = new QTimer(q);
00390                 settingsTimer->setInterval(500);
00391                 settingsTimer->setSingleShot(true);
00392                 QObject::connect(settingsTimer, SIGNAL(timeout()), q, SLOT(saveAutoSaveSettings()));
00393             }
00394             settingsTimer->start();
00395         } else {
00396             q->saveAutoSaveSettings();
00397         }
00398     }
00399 }
00400 
00401 void KMainWindow::parseGeometry(bool parsewidth)
00402 {
00403     K_D(KMainWindow);
00404     QString cmdlineGeometry;
00405     KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
00406     if (args->isSet("geometry"))
00407         cmdlineGeometry = args->getOption("geometry");
00408 
00409     assert ( !cmdlineGeometry.isNull() );
00410     assert ( d->care_about_geometry );
00411 
00412 #if defined Q_WS_X11
00413     int x, y;
00414     int w, h;
00415     int m = XParseGeometry( cmdlineGeometry.toLatin1(), &x, &y, (unsigned int*)&w, (unsigned int*)&h);
00416     if (parsewidth) {
00417         QSize minSize = minimumSize();
00418         QSize maxSize = maximumSize();
00419         if ( !(m & WidthValue) )
00420             w = width();
00421         if ( !(m & HeightValue) )
00422             h = height();
00423          w = qMin(w,maxSize.width());
00424          h = qMin(h,maxSize.height());
00425          w = qMax(w,minSize.width());
00426          h = qMax(h,minSize.height());
00427          resize(w, h);
00428     } else {
00429         if ( (m & XNegative) )
00430             x = KApplication::desktop()->width()  + x - w;
00431         else if ( (m & XValue) )
00432             x = geometry().x();
00433         if ( (m & YNegative) )
00434             y = KApplication::desktop()->height() + y - h;
00435         else if ( (m & YValue) )
00436             y = geometry().y();
00437 
00438         move(x, y);
00439     }
00440 #endif
00441 }
00442 
00443 KMainWindow::~KMainWindow()
00444 {
00445     sMemberList->removeAll( this );
00446     delete k_ptr;
00447     KGlobal::deref();
00448 }
00449 
00450 KMenu* KMainWindow::helpMenu( const QString &aboutAppText, bool showWhatsThis )
00451 {
00452     K_D(KMainWindow);
00453     if(!d->helpMenu) {
00454         if ( aboutAppText.isEmpty() )
00455             d->helpMenu = new KHelpMenu( this, KGlobal::mainComponent().aboutData(), showWhatsThis);
00456         else
00457             d->helpMenu = new KHelpMenu( this, aboutAppText, showWhatsThis );
00458 
00459         if (!d->helpMenu)
00460             return 0;
00461     }
00462 
00463     return d->helpMenu->menu();
00464 }
00465 
00466 KMenu* KMainWindow::customHelpMenu( bool showWhatsThis )
00467 {
00468     K_D(KMainWindow);
00469     if (!d->helpMenu) {
00470         d->helpMenu = new KHelpMenu( this, QString(), showWhatsThis );
00471         connect(d->helpMenu, SIGNAL( showAboutApplication()),
00472                 this, SLOT( showAboutApplication() ));
00473     }
00474 
00475     return d->helpMenu->menu();
00476 }
00477 
00478 bool KMainWindow::canBeRestored( int number )
00479 {
00480     if ( !qApp->isSessionRestored() )
00481         return false;
00482     KConfig *config = kapp->sessionConfig();
00483     if ( !config )
00484         return false;
00485 
00486     KConfigGroup group( config, "Number" );
00487     int n = group.readEntry( "NumberOfWindows", 1 );
00488     return number >= 1 && number <= n;
00489 }
00490 
00491 const QString KMainWindow::classNameOfToplevel( int number )
00492 {
00493     if ( !qApp->isSessionRestored() )
00494         return QString();
00495     KConfig *config = kapp->sessionConfig();
00496     if ( !config )
00497         return QString();
00498     QString s;
00499     s.setNum( number );
00500     s.prepend( QLatin1String("WindowProperties") );
00501 
00502     KConfigGroup group( config, s );
00503     if ( !group.hasKey( "ClassName" ) )
00504         return QString();
00505     else
00506         return group.readEntry( "ClassName" );
00507 }
00508 
00509 bool KMainWindow::restore( int number, bool show )
00510 {
00511     if ( !canBeRestored( number ) )
00512         return false;
00513     KConfig *config = kapp->sessionConfig();
00514     if ( readPropertiesInternal( config, number ) ){
00515         if ( show )
00516             KMainWindow::show();
00517         return false;
00518     }
00519     return false;
00520 }
00521 
00522 void KMainWindow::setCaption( const QString &caption )
00523 {
00524     setPlainCaption( KDialog::makeStandardCaption( caption, this ) );
00525 }
00526 
00527 void KMainWindow::setCaption( const QString &caption, bool modified )
00528 {
00529     KDialog::CaptionFlags flags = KDialog::HIGCompliantCaption;
00530 
00531     if ( modified )
00532     {
00533         flags |= KDialog::ModifiedCaption;
00534     }
00535 
00536     setPlainCaption( KDialog::makeStandardCaption(caption, this, flags) );
00537 }
00538 
00539 void KMainWindow::setPlainCaption( const QString &caption )
00540 {
00541     setWindowTitle(caption);
00542 }
00543 
00544 void KMainWindow::appHelpActivated( void )
00545 {
00546     K_D(KMainWindow);
00547     if( !d->helpMenu ) {
00548         d->helpMenu = new KHelpMenu( this );
00549         if ( !d->helpMenu )
00550             return;
00551     }
00552     d->helpMenu->appHelpActivated();
00553 }
00554 
00555 void KMainWindow::closeEvent ( QCloseEvent *e )
00556 {
00557     K_D(KMainWindow);
00558     // Save settings if auto-save is enabled, and settings have changed
00559     if (d->settingsDirty && d->autoSaveSettings)
00560         saveAutoSaveSettings();
00561 
00562     if (queryClose()) {
00563         e->accept();
00564 
00565         int not_withdrawn = 0;
00566         foreach (KMainWindow* mw, KMainWindow::memberList()) {
00567             if ( !mw->isHidden() && mw->isTopLevel() && mw != this )
00568                 not_withdrawn++;
00569         }
00570 
00571         if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted?
00572             if (!( queryExit() && ( !kapp || !kapp->sessionSaving() ) && !d->shuttingDown )) {
00573               // cancel closing, it's stupid to end up with no windows at all....
00574               e->ignore();
00575             }
00576         }
00577     } else e->ignore(); //if the window should not be closed, don't close it
00578 }
00579 
00580 bool KMainWindow::queryExit()
00581 {
00582     return true;
00583 }
00584 
00585 bool KMainWindow::queryClose()
00586 {
00587     return true;
00588 }
00589 
00590 void KMainWindow::saveGlobalProperties( KConfig*  )
00591 {
00592 }
00593 
00594 void KMainWindow::readGlobalProperties( KConfig*  )
00595 {
00596 }
00597 
00598 void KMainWindow::showAboutApplication()
00599 {
00600 }
00601 
00602 void KMainWindow::savePropertiesInternal( KConfig *config, int number )
00603 {
00604     K_D(KMainWindow);
00605     bool oldASWS = d->autoSaveWindowSize;
00606     d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size
00607 
00608     QString s;
00609     s.setNum(number);
00610     s.prepend(QLatin1String("WindowProperties"));
00611     KConfigGroup cg(config, s);
00612 
00613     // store objectName, className, Width and Height  for later restoring
00614     // (Only useful for session management)
00615     cg.writeEntry(QLatin1String("ObjectName"), objectName());
00616     cg.writeEntry(QLatin1String("ClassName"), metaObject()->className());
00617 
00618     saveMainWindowSettings(cg); // Menubar, statusbar and Toolbar settings.
00619 
00620     s.setNum(number);
00621     cg = KConfigGroup(config, s);
00622     saveProperties(cg);
00623 
00624     d->autoSaveWindowSize = oldASWS;
00625 }
00626 
00627 void KMainWindow::saveMainWindowSettings(const KConfigGroup &_cg)
00628 {
00629     K_D(KMainWindow);
00630     kDebug(200) << "KMainWindow::saveMainWindowSettings " << _cg.name();
00631 
00632     // Called by session management - or if we want to save the window size anyway
00633     if ( d->autoSaveWindowSize )
00634         saveWindowSize( _cg );
00635 
00636     KConfigGroup cg(_cg); // for saving
00637 
00638     // One day will need to save the version number, but for now, assume 0
00639     // Utilise the QMainWindow::saveState() functionality.
00640     QByteArray state = saveState();
00641     cg.writeEntry(QString("State"), state.toBase64());
00642 
00643     QStatusBar* sb = internalStatusBar(this);
00644     if (sb) {
00645        if(!cg.hasDefault("StatusBar") && !sb->isHidden() )
00646            cg.revertToDefault("StatusBar");
00647        else
00648            cg.writeEntry("StatusBar", sb->isHidden() ? "Disabled" : "Enabled");
00649     }
00650 
00651     QMenuBar* mb = internalMenuBar(this);
00652     if (mb) {
00653        QString MenuBar = QLatin1String("MenuBar");
00654        if(!cg.hasDefault("MenuBar") && !mb->isHidden() )
00655            cg.revertToDefault("MenuBar");
00656        else
00657            cg.writeEntry("MenuBar", mb->isHidden() ? "Disabled" : "Enabled");
00658     }
00659 
00660     if ( !autoSaveSettings() || cg.name() == autoSaveGroup() ) { // TODO should be cg == d->autoSaveGroup, to compare both kconfig and group name
00661         if(!cg.hasDefault("ToolBarsMovable") && !KToolBar::toolBarsLocked())
00662             cg.revertToDefault("ToolBarsMovable");
00663         else
00664             cg.writeEntry("ToolBarsMovable", KToolBar::toolBarsLocked() ? "Disabled" : "Enabled");
00665     }
00666 
00667     int n = 1; // Toolbar counter. toolbars are counted from 1,
00668     foreach (KToolBar* toolbar, toolBars()) {
00669         QString group("Toolbar");
00670         // Give a number to the toolbar, but prefer a name if there is one,
00671         // because there's no real guarantee on the ordering of toolbars
00672         group += (toolbar->objectName().isEmpty() ? QString::number(n) : QString(" ")+toolbar->objectName());
00673 
00674         KConfigGroup toolbarGroup(&cg, group);
00675         toolbar->saveSettings(toolbarGroup);
00676         n++;
00677     }
00678 }
00679 
00680 bool KMainWindow::readPropertiesInternal( KConfig *config, int number )
00681 {
00682     K_D(KMainWindow);
00683 
00684     if ( number == 1 )
00685         readGlobalProperties( config );
00686 
00687     // in order they are in toolbar list
00688     QString s;
00689     s.setNum(number);
00690     s.prepend(QLatin1String("WindowProperties"));
00691 
00692     KConfigGroup cg(config, s);
00693 
00694     // restore the object name (window role)
00695     if ( cg.hasKey(QLatin1String("ObjectName" )) )
00696         setObjectName( cg.readEntry("ObjectName").toLatin1()); // latin1 is right here
00697 
00698     d->sizeApplied = false; // since we are changing config file, reload the size of the window
00699                             // if necessary. Do it before the call to applyMainWindowSettings.
00700     applyMainWindowSettings(cg); // Menubar, statusbar and toolbar settings.
00701 
00702     s.setNum(number);
00703     KConfigGroup grp(config, s);
00704     readProperties(grp);
00705     return true;
00706 }
00707 
00708 void KMainWindow::applyMainWindowSettings(const KConfigGroup &cg, bool force)
00709 {
00710     K_D(KMainWindow);
00711     kDebug(200) << "KMainWindow::applyMainWindowSettings " << cg.name();
00712 
00713     QWidget *focusedWidget = QApplication::focusWidget();
00714 
00715     d->letDirtySettings = false;
00716 
00717     if (!d->sizeApplied) {
00718         restoreWindowSize(cg);
00719         d->sizeApplied = true;
00720     }
00721 
00722     QStatusBar* sb = internalStatusBar(this);
00723     if (sb) {
00724         QString entry = cg.readEntry("StatusBar", "Enabled");
00725         if ( entry == "Disabled" )
00726            sb->hide();
00727         else
00728            sb->show();
00729     }
00730 
00731     QMenuBar* mb = internalMenuBar(this);
00732     if (mb) {
00733         QString entry = cg.readEntry ("MenuBar", "Enabled");
00734         if ( entry == "Disabled" )
00735            mb->hide();
00736         else
00737            mb->show();
00738     }
00739 
00740     if ( !autoSaveSettings() || cg.name() == autoSaveGroup() ) { // TODO should be cg == d->autoSaveGroup, to compare both kconfig and group name
00741         QString entry = cg.readEntry ("ToolBarsMovable", "Enabled");
00742         if ( entry == "Disabled" )
00743             KToolBar::setToolBarsLocked(true);
00744         else
00745             KToolBar::setToolBarsLocked(false);
00746     }
00747 
00748     int n = 1; // Toolbar counter. toolbars are counted from 1,
00749     foreach (KToolBar* toolbar, toolBars()) {
00750         QString group("Toolbar");
00751         // Give a number to the toolbar, but prefer a name if there is one,
00752         // because there's no real guarantee on the ordering of toolbars
00753         group += (toolbar->objectName().isEmpty() ? QString::number(n) : QString(" ")+toolbar->objectName());
00754 
00755         KConfigGroup toolbarGroup(&cg, group);
00756         toolbar->applySettings(toolbarGroup, force);
00757         n++;
00758     }
00759 
00760     QByteArray state;
00761     if (cg.hasKey("State")) {
00762         state = cg.readEntry("State", state);
00763         state = QByteArray::fromBase64(state);
00764         // One day will need to load the version number, but for now, assume 0
00765         restoreState(state);
00766     }
00767 
00768     if (focusedWidget) {
00769         focusedWidget->setFocus();
00770     }
00771 
00772     d->settingsDirty = false;
00773     d->letDirtySettings = true;
00774 }
00775 
00776 #ifdef Q_WS_WIN
00777 
00778 /*
00779  The win32 implementation for restoring/savin windows size differs
00780  from the unix/max implementation in three topics:
00781 
00782 1. storing and restoring the position, which may not work on x11
00783     see http://doc.trolltech.com/4.3/geometry.html#x11-peculiarities
00784 2. using QWidget::saveGeometry() and QWidget::restoreGeometry()
00785     this would probably be usable on x11 and/or on mac, but I'm unable to
00786     check this on unix/mac, so I leave this fix to the x11/mac experts.
00787 3. store geometry separately for each resolution -> on unix/max the size
00788     and with of the window are already saved separately on non windows
00789     system although not using ...Geometry functions -> could also be
00790     fixed by x11/mac experts.
00791 */
00792 void KMainWindow::restoreWindowSize( const KConfigGroup & _cg )
00793 {
00794     K_D(KMainWindow);
00795 
00796     int scnum = QApplication::desktop()->screenNumber(parentWidget());
00797     QRect desk = QApplication::desktop()->screenGeometry(scnum);
00798 
00799     // if the desktop is virtual then use virtual screen size
00800     if (QApplication::desktop()->isVirtualDesktop())
00801       desk = QApplication::desktop()->screenGeometry(QApplication::desktop()->screen());
00802 
00803     QString geometryKey = QString::fromLatin1("geometry-%1-%2").arg(desk.width()).arg(desk.height());
00804     QByteArray geometry = _cg.readEntry( geometryKey, QByteArray() );
00805     // if first time run, center window
00806     if (!restoreGeometry( QByteArray::fromBase64(geometry) ))
00807         move( (desk.width()-width())/2, (desk.height()-height())/2 );
00808 }
00809 
00810 void KMainWindow::saveWindowSize( const KConfigGroup & _cg ) const
00811 {
00812     K_D(const KMainWindow);
00813     int scnum = QApplication::desktop()->screenNumber(parentWidget());
00814     QRect desk = QApplication::desktop()->screenGeometry(scnum);
00815 
00816     // if the desktop is virtual then use virtual screen size
00817     if (QApplication::desktop()->isVirtualDesktop())
00818         desk = QApplication::desktop()->screenGeometry(QApplication::desktop()->screen());
00819 
00820     // geometry is saved separately for each resolution
00821     QString geometryKey = QString::fromLatin1("geometry-%1-%2").arg(desk.width()).arg(desk.height());
00822     QByteArray geometry = saveGeometry();
00823     KConfigGroup cg(_cg);
00824     cg.writeEntry( geometryKey, geometry.toBase64() );
00825 }
00826 #else
00827 void KMainWindow::saveWindowSize( const KConfigGroup & _cg ) const
00828 {
00829     K_D(const KMainWindow);
00830     int scnum = QApplication::desktop()->screenNumber(parentWidget());
00831     QRect desk = QApplication::desktop()->screenGeometry(scnum);
00832 
00833     // if the desktop is virtual then use virtual screen size
00834     if (QApplication::desktop()->isVirtualDesktop())
00835         desk = QApplication::desktop()->screenGeometry(QApplication::desktop()->screen());
00836 
00837     int w, h;
00838 #if defined Q_WS_X11
00839     // save maximalization as desktop size + 1 in that direction
00840     KWindowInfo info = KWindowSystem::windowInfo( winId(), NET::WMState );
00841     w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width();
00842     h = info.state() & NET::MaxVert ? desk.height() + 1 : height();
00843 #else
00844     if (isMaximized()) {
00845         w = desk.width() + 1;
00846         h = desk.height() + 1;
00847     } else {
00848         w = width();
00849         h = height();
00850     }
00851     //TODO: add "Maximized" property instead "+1" hack
00852 #endif
00853     KConfigGroup cg(_cg);
00854 
00855     QRect size( desk.width(), w, desk.height(), h );
00856     bool defaultSize = (size == d->defaultWindowSize);
00857     QString widthString = QString::fromLatin1("Width %1").arg(desk.width());
00858     QString heightString = QString::fromLatin1("Height %1").arg(desk.height());
00859     if (!cg.hasDefault(widthString) && defaultSize)
00860         cg.revertToDefault(widthString);
00861     else
00862         cg.writeEntry(widthString, w );
00863 
00864     if (!cg.hasDefault(heightString) && defaultSize)
00865         cg.revertToDefault(heightString);
00866     else
00867         cg.writeEntry(heightString, h );
00868 }
00869 
00870 void KMainWindow::restoreWindowSize( const KConfigGroup & config )
00871 {
00872     K_D(KMainWindow);
00873     if (d->care_about_geometry) {
00874         parseGeometry(true);
00875     } else {
00876         // restore the size
00877         const int scnum = QApplication::desktop()->screenNumber(parentWidget());
00878         QRect desk = QApplication::desktop()->screenGeometry(scnum);
00879 
00880         // if the desktop is virtual then use virtual screen size
00881         if (QApplication::desktop()->isVirtualDesktop())
00882           desk = QApplication::desktop()->screenGeometry(QApplication::desktop()->screen());
00883 
00884         if ( d->defaultWindowSize.isNull() ) // only once
00885           d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); // store default values
00886         const QSize size( config.readEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ),
00887                     config.readEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) );
00888         if ( !size.isEmpty() ) {
00889 #ifdef Q_WS_X11
00890             int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 )
00891                         | ( size.height() > desk.height() ? NET::MaxVert : 0 );
00892             if(( state & NET::Max ) == NET::Max )
00893                 ; // no resize
00894             else if(( state & NET::MaxHoriz ) == NET::MaxHoriz )
00895                 resize( width(), size.height());
00896             else if(( state & NET::MaxVert ) == NET::MaxVert )
00897                 resize( size.width(), height());
00898             else
00899                 resize( size );
00900             // QWidget::showMaximized() is both insufficient and broken
00901             KWindowSystem::setState( winId(), state );
00902 #else
00903             if (size.width() > desk.width() || size.height() > desk.height())
00904               setWindowState( Qt::WindowMaximized );
00905             else
00906               resize( size );
00907 #endif
00908         }
00909     }
00910 }
00911 #endif
00912 
00913 bool KMainWindow::initialGeometrySet() const
00914 {
00915     K_D(const KMainWindow);
00916     return d->care_about_geometry;
00917 }
00918 
00919 void KMainWindow::ignoreInitialGeometry()
00920 {
00921     K_D(KMainWindow);
00922     d->care_about_geometry = false;
00923 }
00924 
00925 void KMainWindow::setSettingsDirty()
00926 {
00927     K_D(KMainWindow);
00928     //kDebug(200) << "KMainWindow::setSettingsDirty";
00929 
00930     if (!d->letDirtySettings) {
00931         return;
00932     }
00933 
00934     d->settingsDirty = true;
00935     if ( d->autoSaveSettings )
00936     {
00937         // Saving directly is safe here. Calls that will be donen very often in a short period of
00938         // time will call to the private version of this method, that is KMainWindowPrivate::setSettingsDirty(CompressCalls).
00939         // When working with toolbars, and restore/saveState mechanism from Qt is esential to save
00940         // at the very moment, so no toolbars are removed and no information is lost/changed (like
00941         // sizes of toolbars), in case we were compressing calls here (having a timer). (ereslibre)
00942         saveAutoSaveSettings();
00943     }
00944 }
00945 
00946 bool KMainWindow::settingsDirty() const
00947 {
00948     K_D(const KMainWindow);
00949     return d->settingsDirty;
00950 }
00951 
00952 void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize )
00953 {
00954     setAutoSaveSettings(KConfigGroup(KGlobal::config(), groupName), saveWindowSize);
00955 }
00956 
00957 void KMainWindow::setAutoSaveSettings( const KConfigGroup & group,
00958                                        bool saveWindowSize )
00959 {
00960     K_D(KMainWindow);
00961     d->autoSaveSettings = true;
00962     d->autoSaveGroup = group;
00963     d->autoSaveWindowSize = saveWindowSize;
00964 
00965     // Now read the previously saved settings
00966     applyMainWindowSettings(d->autoSaveGroup);
00967 }
00968 
00969 void KMainWindow::resetAutoSaveSettings()
00970 {
00971     K_D(KMainWindow);
00972     d->autoSaveSettings = false;
00973     if (d->settingsTimer) {
00974         d->settingsTimer->stop();
00975     }
00976 }
00977 
00978 bool KMainWindow::autoSaveSettings() const
00979 {
00980     K_D(const KMainWindow);
00981     return d->autoSaveSettings;
00982 }
00983 
00984 QString KMainWindow::autoSaveGroup() const
00985 {
00986     K_D(const KMainWindow);
00987     return d->autoSaveSettings ? d->autoSaveGroup.name() : QString();
00988 }
00989 
00990 KConfigGroup KMainWindow::autoSaveConfigGroup() const
00991 {
00992     K_D(const KMainWindow);
00993     return d->autoSaveSettings ? d->autoSaveGroup : KConfigGroup();
00994 }
00995 
00996 void KMainWindow::saveAutoSaveSettings()
00997 {
00998     K_D(KMainWindow);
00999     Q_ASSERT( d->autoSaveSettings );
01000     //kDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings";
01001     saveMainWindowSettings(d->autoSaveGroup);
01002     d->autoSaveGroup.sync();
01003     d->settingsDirty = false;
01004 }
01005 
01006 bool KMainWindow::event( QEvent* ev )
01007 {
01008     K_D(KMainWindow);
01009     switch( ev->type() ) {
01010 #ifdef Q_WS_WIN
01011     case QEvent::Move:
01012 #endif
01013     case QEvent::Resize:
01014         if ( d->autoSaveWindowSize )
01015         d->setSettingsDirty(KMainWindowPrivate::CompressCalls);
01016         break;
01017     case QEvent::Polish:
01018         d->polish(this);
01019         break;
01020     case QEvent::ChildPolished:
01021         {
01022             QChildEvent *event = static_cast<QChildEvent*>(ev);
01023             QDockWidget *dock = qobject_cast<QDockWidget*>(event->child());
01024             KToolBar *toolbar = qobject_cast<KToolBar*>(event->child());
01025             if (dock) {
01026                 connect(dock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
01027                         this, SLOT(setSettingsDirty()));
01028                 connect(dock, SIGNAL(visibilityChanged(bool)),
01029                         this, SLOT(setSettingsDirty()));
01030                 connect(dock, SIGNAL(topLevelChanged(bool)),
01031                         this, SLOT(setSettingsDirty()));
01032 
01033                 // there is no signal emitted if the size of the dock changes,
01034                 // hence install an event filter instead
01035                 dock->installEventFilter(k_ptr->dockResizeListener);
01036             } else if (toolbar) {
01037                 connect(toolbar, SIGNAL(iconSizeChanged(QSize)),
01038                         this, SLOT(setSettingsDirty()));
01039                 connect(toolbar, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
01040                         this, SLOT(setSettingsDirty()));
01041 
01042                 // there is no signal emitted if the size of the dock changes,
01043                 // hence install an event filter instead
01044                 toolbar->installEventFilter(k_ptr->dockResizeListener);
01045             }
01046         }
01047         break;
01048     case QEvent::ChildRemoved:
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             if (dock) {
01054                 disconnect(dock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
01055                            this, SLOT(setSettingsDirty()));
01056                 disconnect(dock, SIGNAL(visibilityChanged(bool)),
01057                            this, SLOT(setSettingsDirty()));
01058                 disconnect(dock, SIGNAL(topLevelChanged(bool)),
01059                            this, SLOT(setSettingsDirty()));
01060                 dock->removeEventFilter(k_ptr->dockResizeListener);
01061             } else if (toolbar) {
01062                 disconnect(toolbar, SIGNAL(iconSizeChanged(QSize)),
01063                            this, SLOT(setSettingsDirty()));
01064                 disconnect(toolbar, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
01065                            this, SLOT(setSettingsDirty()));
01066                 toolbar->removeEventFilter(k_ptr->dockResizeListener);
01067             }
01068         }
01069         break;
01070     default:
01071         break;
01072     }
01073     return QMainWindow::event( ev );
01074 }
01075 
01076 bool KMainWindow::hasMenuBar()
01077 {
01078     return internalMenuBar(this);
01079 }
01080 
01081 KMenuBar *KMainWindow::menuBar()
01082 {
01083     KMenuBar * mb = internalMenuBar(this);
01084     if ( !mb ) {
01085         mb = new KMenuBar( this );
01086         // trigger a re-layout and trigger a call to the private
01087         // setMenuBar method.
01088         setMenuBar(mb);
01089     }
01090     return mb;
01091 }
01092 
01093 KStatusBar *KMainWindow::statusBar()
01094 {
01095     KStatusBar * sb = internalStatusBar(this);
01096     if ( !sb ) {
01097         sb = new KStatusBar( this );
01098         // trigger a re-layout and trigger a call to the private
01099         // setStatusBar method.
01100         setStatusBar(sb);
01101     }
01102     return sb;
01103 }
01104 
01105 void KMainWindowPrivate::_k_shuttingDown()
01106 {
01107     // Needed for Qt <= 3.0.3 at least to prevent reentrancy
01108     // when queryExit() shows a dialog. Check before removing!
01109     static bool reentrancy_protection = false;
01110     if (!reentrancy_protection)
01111     {
01112        reentrancy_protection = true;
01113        shuttingDown = true;
01114        // call the virtual queryExit
01115        q->queryExit();
01116        reentrancy_protection = false;
01117     }
01118 }
01119 
01120 void KMainWindowPrivate::_k_slotSettingsChanged(int category)
01121 {
01122     Q_UNUSED(category);
01123 
01124     // This slot will be called when the style KCM changes settings that need
01125     // to be set on the already running applications.
01126 
01127     // At this level (KMainWindow) the only thing we need to restore is the
01128     // animations setting (whether the user wants builtin animations or not).
01129 
01130     q->setAnimated(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects);
01131 }
01132 
01133 KToolBar *KMainWindow::toolBar( const QString& name )
01134 {
01135     QString childName = name;
01136     if (childName.isEmpty())
01137        childName = "mainToolBar";
01138 
01139     KToolBar *tb = findChild<KToolBar*>(childName);
01140     if ( tb )
01141         return tb;
01142     bool honor_mode = name != "mainToolBar";
01143 
01144     KToolBar* toolbar = new KToolBar(this, honor_mode ); // non-XMLGUI
01145 
01146     toolbar->setObjectName(childName);
01147     addToolBar(toolbar);
01148 
01149     return toolbar;
01150 }
01151 
01152 QList<KToolBar*> KMainWindow::toolBars() const
01153 {
01154     QList<KToolBar*> ret;
01155 
01156     foreach (QObject* child, children())
01157         if (KToolBar* toolBar = qobject_cast<KToolBar*>(child))
01158             ret.append(toolBar);
01159 
01160     return ret;
01161 }
01162 
01163 QList<KMainWindow*> KMainWindow::memberList() { return *sMemberList; }
01164 
01165 QString KMainWindow::dbusName() const
01166 {
01167     return k_func()->dbusName;
01168 }
01169 
01170 #include "kmainwindow.moc"
01171 

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
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.6
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