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

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