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

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
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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