• 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     KGlobal::deref();
00418 }
00419 
00420 KMenu* KMainWindow::helpMenu( const QString &aboutAppText, bool showWhatsThis )
00421 {
00422     K_D(KMainWindow);
00423     if(!d->helpMenu) {
00424         if ( aboutAppText.isEmpty() )
00425             d->helpMenu = new KHelpMenu( this, KGlobal::mainComponent().aboutData(), showWhatsThis);
00426         else
00427             d->helpMenu = new KHelpMenu( this, aboutAppText, showWhatsThis );
00428 
00429         if (!d->helpMenu)
00430             return 0;
00431     }
00432 
00433     return d->helpMenu->menu();
00434 }
00435 
00436 KMenu* KMainWindow::customHelpMenu( bool showWhatsThis )
00437 {
00438     K_D(KMainWindow);
00439     if (!d->helpMenu) {
00440         d->helpMenu = new KHelpMenu( this, QString(), showWhatsThis );
00441         connect(d->helpMenu, SIGNAL( showAboutApplication()),
00442                 this, SLOT( showAboutApplication() ));
00443     }
00444 
00445     return d->helpMenu->menu();
00446 }
00447 
00448 bool KMainWindow::canBeRestored( int number )
00449 {
00450     if ( !qApp->isSessionRestored() )
00451         return false;
00452     KConfig *config = kapp->sessionConfig();
00453     if ( !config )
00454         return false;
00455 
00456     KConfigGroup group( config, "Number" );
00457     int n = group.readEntry( "NumberOfWindows", 1 );
00458     return number >= 1 && number <= n;
00459 }
00460 
00461 const QString KMainWindow::classNameOfToplevel( int number )
00462 {
00463     if ( !qApp->isSessionRestored() )
00464         return QString();
00465     KConfig *config = kapp->sessionConfig();
00466     if ( !config )
00467         return QString();
00468     QString s;
00469     s.setNum( number );
00470     s.prepend( QLatin1String("WindowProperties") );
00471 
00472     KConfigGroup group( config, s );
00473     if ( !group.hasKey( "ClassName" ) )
00474         return QString();
00475     else
00476         return group.readEntry( "ClassName" );
00477 }
00478 
00479 bool KMainWindow::restore( int number, bool show )
00480 {
00481     if ( !canBeRestored( number ) )
00482         return false;
00483     KConfig *config = kapp->sessionConfig();
00484     if ( readPropertiesInternal( config, number ) ){
00485         if ( show )
00486             KMainWindow::show();
00487         return false;
00488     }
00489     return false;
00490 }
00491 
00492 void KMainWindow::setCaption( const QString &caption )
00493 {
00494     setPlainCaption( KDialog::makeStandardCaption( caption, this ) );
00495 }
00496 
00497 void KMainWindow::setCaption( const QString &caption, bool modified )
00498 {
00499     KDialog::CaptionFlags flags = KDialog::HIGCompliantCaption;
00500 
00501     if ( modified )
00502     {
00503         flags |= KDialog::ModifiedCaption;
00504     }
00505 
00506     setPlainCaption( KDialog::makeStandardCaption(caption, this, flags) );
00507 }
00508 
00509 void KMainWindow::setPlainCaption( const QString &caption )
00510 {
00511     setWindowTitle(caption);
00512 }
00513 
00514 void KMainWindow::appHelpActivated( void )
00515 {
00516     K_D(KMainWindow);
00517     if( !d->helpMenu ) {
00518         d->helpMenu = new KHelpMenu( this );
00519         if ( !d->helpMenu )
00520             return;
00521     }
00522     d->helpMenu->appHelpActivated();
00523 }
00524 
00525 void KMainWindow::closeEvent ( QCloseEvent *e )
00526 {
00527     K_D(KMainWindow);
00528     // Save settings if auto-save is enabled, and settings have changed
00529     if (d->settingsDirty && d->autoSaveSettings)
00530         saveAutoSaveSettings();
00531 
00532     if (queryClose()) {
00533         e->accept();
00534 
00535         int not_withdrawn = 0;
00536         foreach (KMainWindow* mw, KMainWindow::memberList()) {
00537             if ( !mw->isHidden() && mw->isTopLevel() && mw != this )
00538                 not_withdrawn++;
00539         }
00540 
00541         if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted?
00542             if ( queryExit() && ( !kapp || !kapp->sessionSaving() ) && !d->shuttingDown ) { // Yes, Quit app?
00543                 // don't call queryExit() twice
00544                 disconnect(qApp, SIGNAL(aboutToQuit()), this, SLOT(_k_shuttingDown()));
00545                 d->shuttingDown = true;
00546             }  else {
00547                 // cancel closing, it's stupid to end up with no windows at all....
00548                 e->ignore();
00549             }
00550         }
00551     } else e->ignore(); //if the window should not be closed, don't close it
00552 }
00553 
00554 bool KMainWindow::queryExit()
00555 {
00556     return true;
00557 }
00558 
00559 bool KMainWindow::queryClose()
00560 {
00561     return true;
00562 }
00563 
00564 void KMainWindow::saveGlobalProperties( KConfig*  )
00565 {
00566 }
00567 
00568 void KMainWindow::readGlobalProperties( KConfig*  )
00569 {
00570 }
00571 
00572 void KMainWindow::showAboutApplication()
00573 {
00574 }
00575 
00576 void KMainWindow::savePropertiesInternal( KConfig *config, int number )
00577 {
00578     K_D(KMainWindow);
00579     bool oldASWS = d->autoSaveWindowSize;
00580     d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size
00581 
00582     QString s;
00583     s.setNum(number);
00584     s.prepend(QLatin1String("WindowProperties"));
00585     KConfigGroup cg(config, s);
00586 
00587     // store objectName, className, Width and Height  for later restoring
00588     // (Only useful for session management)
00589     cg.writeEntry(QLatin1String("ObjectName"), objectName());
00590     cg.writeEntry(QLatin1String("ClassName"), metaObject()->className());
00591 
00592     saveMainWindowSettings(cg); // Menubar, statusbar and Toolbar settings.
00593 
00594     s.setNum(number);
00595     cg = KConfigGroup(config, s);
00596     saveProperties(cg);
00597 
00598     d->autoSaveWindowSize = oldASWS;
00599 }
00600 
00601 void KMainWindow::saveMainWindowSettings(const KConfigGroup &_cg)
00602 {
00603     K_D(KMainWindow);
00604     kDebug(200) << "KMainWindow::saveMainWindowSettings " << _cg.name();
00605 
00606     // Called by session management - or if we want to save the window size anyway
00607     if ( d->autoSaveWindowSize )
00608         saveWindowSize( _cg );
00609 
00610     KConfigGroup cg(_cg); // for saving
00611 
00612     QStatusBar* sb = internalStatusBar(this);
00613     if (sb) {
00614        if(!cg.hasDefault("StatusBar") && !sb->isHidden() )
00615            cg.revertToDefault("StatusBar");
00616        else
00617            cg.writeEntry("StatusBar", sb->isHidden() ? "Disabled" : "Enabled");
00618     }
00619 
00620     QMenuBar* mb = internalMenuBar(this);
00621     if (mb) {
00622        QString MenuBar = QLatin1String("MenuBar");
00623        if(!cg.hasDefault("MenuBar") && !mb->isHidden() )
00624            cg.revertToDefault("MenuBar");
00625        else
00626            cg.writeEntry("MenuBar", mb->isHidden() ? "Disabled" : "Enabled");
00627     }
00628 
00629     // Utilise the QMainWindow::saveState() functionality
00630     QByteArray state = saveState();
00631     cg.writeEntry("State", state.toBase64());
00632     // One day will need to save the version number, but for now, assume 0
00633 
00634     if ( !autoSaveSettings() || cg.name() == autoSaveGroup() ) { // TODO should be cg == d->autoSaveGroup, to compare both kconfig and group name
00635         if(!cg.hasDefault("ToolBarsMovable") && !KToolBar::toolBarsLocked())
00636             cg.revertToDefault("ToolBarsMovable");
00637         else
00638             cg.writeEntry("ToolBarsMovable", KToolBar::toolBarsLocked() ? "Disabled" : "Enabled");
00639     }
00640 
00641     int n = 1; // Toolbar counter. toolbars are counted from 1,
00642     foreach (KToolBar* toolbar, toolBars()) {
00643         QString group("Toolbar");
00644         // Give a number to the toolbar, but prefer a name if there is one,
00645         // because there's no real guarantee on the ordering of toolbars
00646         group += (toolbar->objectName().isEmpty() ? QString::number(n) : QString(" ")+toolbar->objectName());
00647 
00648         KConfigGroup toolbarGroup(&cg, group);
00649         toolbar->saveSettings(toolbarGroup);
00650         n++;
00651     }
00652 }
00653 
00654 bool KMainWindow::readPropertiesInternal( KConfig *config, int number )
00655 {
00656     if ( number == 1 )
00657         readGlobalProperties( config );
00658 
00659     // in order they are in toolbar list
00660     QString s;
00661     s.setNum(number);
00662     s.prepend(QLatin1String("WindowProperties"));
00663 
00664     KConfigGroup cg(config, s);
00665 
00666     // restore the object name (window role)
00667     if ( cg.hasKey(QLatin1String("ObjectName" )) )
00668         setObjectName( cg.readEntry("ObjectName").toLatin1()); // latin1 is right here
00669 
00670     applyMainWindowSettings(cg); // Menubar, statusbar and toolbar settings.
00671 
00672     s.setNum(number);
00673     KConfigGroup grp(config, s);
00674     readProperties(grp);
00675     return true;
00676 }
00677 
00678 void KMainWindow::applyMainWindowSettings(const KConfigGroup &cg, bool force)
00679 {
00680     K_D(KMainWindow);
00681     kDebug(200) << "KMainWindow::applyMainWindowSettings " << cg.name();
00682 
00683     restoreWindowSize(cg);
00684 
00685     QStatusBar* sb = internalStatusBar(this);
00686     if (sb) {
00687         QString entry = cg.readEntry("StatusBar", "Enabled");
00688         if ( entry == "Disabled" )
00689            sb->hide();
00690         else
00691            sb->show();
00692     }
00693 
00694     QMenuBar* mb = internalMenuBar(this);
00695     if (mb) {
00696         QString entry = cg.readEntry ("MenuBar", "Enabled");
00697         if ( entry == "Disabled" )
00698            mb->hide();
00699         else
00700            mb->show();
00701     }
00702 
00703     // Utilise the QMainWindow::restoreState() functionality
00704     if (cg.hasKey("State")) {
00705         QByteArray state;
00706         state = cg.readEntry("State", state);
00707         state = QByteArray::fromBase64(state);
00708         // One day will need to load the version number, but for now, assume 0
00709         restoreState(state);
00710     }
00711 
00712     if ( !autoSaveSettings() || cg.name() == autoSaveGroup() ) { // TODO should be cg == d->autoSaveGroup, to compare both kconfig and group name
00713         QString entry = cg.readEntry ("ToolBarsMovable", "Enabled");
00714         if ( entry == "Disabled" )
00715             KToolBar::setToolBarsLocked(true);
00716         else
00717             KToolBar::setToolBarsLocked(false);
00718     }
00719 
00720     int n = 1; // Toolbar counter. toolbars are counted from 1,
00721     foreach (KToolBar* toolbar, toolBars()) {
00722         QString group("Toolbar");
00723         // Give a number to the toolbar, but prefer a name if there is one,
00724         // because there's no real guarantee on the ordering of toolbars
00725         group += (toolbar->objectName().isEmpty() ? QString::number(n) : QString(" ")+toolbar->objectName());
00726 
00727         KConfigGroup toolbarGroup(&cg, group);
00728         toolbar->applySettings(toolbarGroup, force);
00729         n++;
00730     }
00731 
00732     d->settingsDirty = false;
00733 }
00734 
00735 #ifdef Q_WS_WIN
00736 
00737 /*
00738  The win32 implementation for restoring/savin windows size differs
00739  from the unix/max implementation in three topics:
00740 
00741 1. storing and restoring the position, which may not work on x11
00742     see http://doc.trolltech.com/4.3/geometry.html#x11-peculiarities
00743 2. using QWidget::saveGeometry() and QWidget::restoreGeometry()
00744     this would probably be usable on x11 and/or on mac, but I'm unable to
00745     check this on unix/mac, so I leave this fix to the x11/mac experts.
00746 3. store geometry separately for each resolution -> on unix/max the size
00747     and with of the window are already saved separately on non windows
00748     system although not using ...Geometry functions -> could also be
00749     fixed by x11/mac experts.
00750 */
00751 void KMainWindow::restoreWindowSize( const KConfigGroup & _cg )
00752 {
00753     K_D(KMainWindow);
00754 
00755     int scnum = QApplication::desktop()->screenNumber(parentWidget());
00756     QRect desk = QApplication::desktop()->screenGeometry(scnum);
00757 
00758     // if the desktop is virtual then use virtual screen size
00759     if (QApplication::desktop()->isVirtualDesktop())
00760       desk = QApplication::desktop()->screenGeometry(QApplication::desktop()->screen());
00761 
00762     QString geometryKey = QString::fromLatin1("geometry-%1-%2").arg(desk.width()).arg(desk.height());
00763     QByteArray geometry = _cg.readEntry( geometryKey, QByteArray() );
00764     // if first time run, center window
00765     if (!restoreGeometry( QByteArray::fromBase64(geometry) ))
00766         move( (desk.width()-width())/2, (desk.height()-height())/2 );
00767 }
00768 
00769 void KMainWindow::saveWindowSize( const KConfigGroup & _cg ) const
00770 {
00771     K_D(const KMainWindow);
00772     int scnum = QApplication::desktop()->screenNumber(parentWidget());
00773     QRect desk = QApplication::desktop()->screenGeometry(scnum);
00774 
00775     // if the desktop is virtual then use virtual screen size
00776     if (QApplication::desktop()->isVirtualDesktop())
00777         desk = QApplication::desktop()->screenGeometry(QApplication::desktop()->screen());
00778 
00779     // geometry is saved separately for each resolution
00780     QString geometryKey = QString::fromLatin1("geometry-%1-%2").arg(desk.width()).arg(desk.height());
00781     QByteArray geometry = saveGeometry();
00782     KConfigGroup cg(_cg);
00783     cg.writeEntry( geometryKey, geometry.toBase64() );
00784 }
00785 #else
00786 void KMainWindow::saveWindowSize( const KConfigGroup & _cg ) const
00787 {
00788     K_D(const KMainWindow);
00789     int scnum = QApplication::desktop()->screenNumber(parentWidget());
00790     QRect desk = QApplication::desktop()->screenGeometry(scnum);
00791 
00792     // if the desktop is virtual then use virtual screen size
00793     if (QApplication::desktop()->isVirtualDesktop())
00794         desk = QApplication::desktop()->screenGeometry(QApplication::desktop()->screen());
00795 
00796     int w, h;
00797 #if defined Q_WS_X11
00798     // save maximalization as desktop size + 1 in that direction
00799     KWindowInfo info = KWindowSystem::windowInfo( winId(), NET::WMState );
00800     w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width();
00801     h = info.state() & NET::MaxVert ? desk.height() + 1 : height();
00802 #else
00803     if (isMaximized()) {
00804         w = desk.width() + 1;
00805         h = desk.height() + 1;
00806     } else {
00807         w = width();
00808         h = height();
00809     }
00810     //TODO: add "Maximized" property instead "+1" hack
00811 #endif
00812     KConfigGroup cg(_cg);
00813 
00814     QRect size( desk.width(), w, desk.height(), h );
00815     bool defaultSize = (size == d->defaultWindowSize);
00816     QString widthString = QString::fromLatin1("Width %1").arg(desk.width());
00817     QString heightString = QString::fromLatin1("Height %1").arg(desk.height());
00818     if (!cg.hasDefault(widthString) && defaultSize)
00819         cg.revertToDefault(widthString);
00820     else
00821         cg.writeEntry(widthString, w );
00822 
00823     if (!cg.hasDefault(heightString) && defaultSize)
00824         cg.revertToDefault(heightString);
00825     else
00826         cg.writeEntry(heightString, h );
00827 }
00828 
00829 void KMainWindow::restoreWindowSize( const KConfigGroup & config )
00830 {
00831     K_D(KMainWindow);
00832     if (d->care_about_geometry) {
00833         parseGeometry(true);
00834     } else {
00835         // restore the size
00836         const int scnum = QApplication::desktop()->screenNumber(parentWidget());
00837         QRect desk = QApplication::desktop()->screenGeometry(scnum);
00838 
00839         // if the desktop is virtual then use virtual screen size
00840         if (QApplication::desktop()->isVirtualDesktop())
00841           desk = QApplication::desktop()->screenGeometry(QApplication::desktop()->screen());
00842 
00843         if ( d->defaultWindowSize.isNull() ) // only once
00844           d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); // store default values
00845         const QSize size( config.readEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ),
00846                     config.readEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) );
00847         if ( !size.isEmpty() ) {
00848 #ifdef Q_WS_X11
00849             int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 )
00850                         | ( size.height() > desk.height() ? NET::MaxVert : 0 );
00851             if(( state & NET::Max ) == NET::Max )
00852                 ; // no resize
00853             else if(( state & NET::MaxHoriz ) == NET::MaxHoriz )
00854                 resize( width(), size.height());
00855             else if(( state & NET::MaxVert ) == NET::MaxVert )
00856                 resize( size.width(), height());
00857             else
00858                 resize( size );
00859             // QWidget::showMaximized() is both insufficient and broken
00860             KWindowSystem::setState( winId(), state );
00861 #else
00862             if (size.width() > desk.width() || size.height() > desk.height())
00863               setWindowState( Qt::WindowMaximized );
00864             else
00865               resize( size );
00866 #endif
00867         }
00868     }
00869 }
00870 #endif
00871 
00872 bool KMainWindow::initialGeometrySet() const
00873 {
00874     K_D(const KMainWindow);
00875     return d->care_about_geometry;
00876 }
00877 
00878 void KMainWindow::ignoreInitialGeometry()
00879 {
00880     K_D(KMainWindow);
00881     d->care_about_geometry = false;
00882 }
00883 
00884 void KMainWindow::setSettingsDirty()
00885 {
00886     K_D(KMainWindow);
00887     //kDebug(200) << "KMainWindow::setSettingsDirty";
00888     d->settingsDirty = true;
00889     if ( d->autoSaveSettings )
00890     {
00891         // Use a timer to save "immediately" user-wise, but not too immediately
00892         // (to compress calls and save only once, in case of multiple changes)
00893         if ( !d->settingsTimer )
00894         {
00895            d->settingsTimer = new QTimer( this );
00896            connect( d->settingsTimer, SIGNAL( timeout() ), SLOT( saveAutoSaveSettings() ) );
00897         }
00898         d->settingsTimer->setInterval(5000);
00899         d->settingsTimer->setSingleShot(true);
00900         d->settingsTimer->start();
00901     }
00902 }
00903 
00904 bool KMainWindow::settingsDirty() const
00905 {
00906     K_D(const KMainWindow);
00907     return d->settingsDirty;
00908 }
00909 
00910 void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize )
00911 {
00912     setAutoSaveSettings(KConfigGroup(KGlobal::config(), groupName), saveWindowSize);
00913 }
00914 
00915 void KMainWindow::setAutoSaveSettings( const KConfigGroup & group,
00916                                        bool saveWindowSize )
00917 {
00918     K_D(KMainWindow);
00919     d->autoSaveSettings = true;
00920     d->autoSaveGroup = group;
00921     d->autoSaveWindowSize = saveWindowSize;
00922 
00923     // Now read the previously saved settings
00924     applyMainWindowSettings(d->autoSaveGroup);
00925 }
00926 
00927 void KMainWindow::resetAutoSaveSettings()
00928 {
00929     K_D(KMainWindow);
00930     d->autoSaveSettings = false;
00931     if ( d->settingsTimer )
00932         d->settingsTimer->stop();
00933 }
00934 
00935 bool KMainWindow::autoSaveSettings() const
00936 {
00937     K_D(const KMainWindow);
00938     return d->autoSaveSettings;
00939 }
00940 
00941 QString KMainWindow::autoSaveGroup() const
00942 {
00943     K_D(const KMainWindow);
00944     return d->autoSaveSettings ? d->autoSaveGroup.name() : QString();
00945 }
00946 
00947 KConfigGroup KMainWindow::autoSaveConfigGroup() const
00948 {
00949     K_D(const KMainWindow);
00950     return d->autoSaveSettings ? d->autoSaveGroup : KConfigGroup();
00951 }
00952 
00953 void KMainWindow::saveAutoSaveSettings()
00954 {
00955     K_D(KMainWindow);
00956     Q_ASSERT( d->autoSaveSettings );
00957     //kDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings";
00958     saveMainWindowSettings(d->autoSaveGroup);
00959     d->autoSaveGroup.sync();
00960     d->settingsDirty = false;
00961     if ( d->settingsTimer )
00962         d->settingsTimer->stop();
00963 }
00964 
00965 bool KMainWindow::event( QEvent* ev )
00966 {
00967     K_D(KMainWindow);
00968     switch( ev->type() ) {
00969 #ifdef Q_WS_WIN
00970     case QEvent::Move:
00971 #endif
00972     case QEvent::Resize:
00973         if ( d->autoSaveWindowSize )
00974             setSettingsDirty();
00975         break;
00976     case QEvent::Polish:
00977         d->polish(this);
00978         break;
00979     case QEvent::ChildPolished:
00980         {
00981             QChildEvent *event = static_cast<QChildEvent*>(ev);
00982             QDockWidget *dock = qobject_cast<QDockWidget*>(event->child());
00983             if (dock) {
00984                 connect(dock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
00985                         this, SLOT(setSettingsDirty()));
00986                 connect(dock, SIGNAL(visibilityChanged(bool)),
00987                         this, SLOT(setSettingsDirty()));
00988                 connect(dock, SIGNAL(topLevelChanged(bool)),
00989                         this, SLOT(setSettingsDirty()));
00990 
00991                 // there is no signal emitted if the size of the dock changes,
00992                 // hence install an event filter instead
00993                 dock->installEventFilter(k_ptr->dockResizeListener);
00994             }
00995         }
00996         break;
00997     case QEvent::ChildRemoved:
00998         {
00999             QChildEvent *event = static_cast<QChildEvent*>(ev);
01000             QDockWidget *dock = qobject_cast<QDockWidget*>(event->child());
01001             if (dock) {
01002                 disconnect(dock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
01003                            this, SLOT(setSettingsDirty()));
01004                 disconnect(dock, SIGNAL(visibilityChanged(bool)),
01005                            this, SLOT(setSettingsDirty()));
01006                 disconnect(dock, SIGNAL(topLevelChanged(bool)),
01007                            this, SLOT(setSettingsDirty()));
01008                 dock->removeEventFilter(k_ptr->dockResizeListener);
01009             }
01010         }
01011         break;
01012     default:
01013         break;
01014     }
01015     return QMainWindow::event( ev );
01016 }
01017 
01018 bool KMainWindow::hasMenuBar()
01019 {
01020     return internalMenuBar(this);
01021 }
01022 
01023 KMenuBar *KMainWindow::menuBar()
01024 {
01025     KMenuBar * mb = internalMenuBar(this);
01026     if ( !mb ) {
01027         mb = new KMenuBar( this );
01028         // trigger a re-layout and trigger a call to the private
01029         // setMenuBar method.
01030         setMenuBar(mb);
01031     }
01032     return mb;
01033 }
01034 
01035 KStatusBar *KMainWindow::statusBar()
01036 {
01037     KStatusBar * sb = internalStatusBar(this);
01038     if ( !sb ) {
01039         sb = new KStatusBar( this );
01040         // trigger a re-layout and trigger a call to the private
01041         // setStatusBar method.
01042         setStatusBar(sb);
01043     }
01044     return sb;
01045 }
01046 
01047 void KMainWindowPrivate::_k_shuttingDown()
01048 {
01049     // Needed for Qt <= 3.0.3 at least to prevent reentrancy
01050     // when queryExit() shows a dialog. Check before removing!
01051     static bool reentrancy_protection = false;
01052     if (!reentrancy_protection)
01053     {
01054        reentrancy_protection = true;
01055        // call the virtual queryExit
01056        q->queryExit();
01057        reentrancy_protection = false;
01058     }
01059 }
01060 
01061 void KMainWindowPrivate::_k_slotSettingsChanged(int category)
01062 {
01063     Q_UNUSED(category);
01064 
01065     // This slot will be called when the style KCM changes settings that need
01066     // to be set on the already running applications.
01067 
01068     // At this level (KMainWindow) the only thing we need to restore is the
01069     // animations setting (whether the user wants builtin animations or not).
01070 
01071     q->setAnimated(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects);
01072 }
01073 
01074 KToolBar *KMainWindow::toolBar( const QString& name )
01075 {
01076     QString childName = name;
01077     if (childName.isEmpty())
01078        childName = "mainToolBar";
01079 
01080     KToolBar *tb = findChild<KToolBar*>(childName);
01081     if ( tb )
01082         return tb;
01083     bool honor_mode = name != "mainToolBar";
01084 
01085     KToolBar* toolbar = new KToolBar(this, honor_mode ); // non-XMLGUI
01086 
01087     toolbar->setObjectName(childName);
01088     addToolBar(toolbar);
01089 
01090     return toolbar;
01091 }
01092 
01093 QList<KToolBar*> KMainWindow::toolBars() const
01094 {
01095     QList<KToolBar*> ret;
01096 
01097     foreach (QObject* child, children())
01098         if (KToolBar* toolBar = qobject_cast<KToolBar*>(child))
01099             ret.append(toolBar);
01100 
01101     return ret;
01102 }
01103 
01104 QList<KMainWindow*> KMainWindow::memberList() { return *sMemberList; }
01105 
01106 QString KMainWindow::dbusName() const
01107 {
01108     return k_func()->dbusName;
01109 }
01110 
01111 #include "kmainwindow.moc"
01112 

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.4
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