summaryrefslogtreecommitdiffstats
path: root/kdeui/kmainwindow.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch)
tree5ac38a06f3dde268dc7927dc155896926aaf7012 /kdeui/kmainwindow.cpp
downloadtdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz
tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kdeui/kmainwindow.cpp')
-rw-r--r--kdeui/kmainwindow.cpp1249
1 files changed, 1249 insertions, 0 deletions
diff --git a/kdeui/kmainwindow.cpp b/kdeui/kmainwindow.cpp
new file mode 100644
index 000000000..119ff4a7e
--- /dev/null
+++ b/kdeui/kmainwindow.cpp
@@ -0,0 +1,1249 @@
+ /* This file is part of the KDE libraries
+ Copyright
+ (C) 2000 Reginald Stadlbauer (reggie@kde.org)
+ (C) 1997 Stephan Kulow (coolo@kde.org)
+ (C) 1997-2000 Sven Radej (radej@kde.org)
+ (C) 1997-2000 Matthias Ettrich (ettrich@kde.org)
+ (C) 1999 Chris Schlaeger (cs@kde.org)
+ (C) 2002 Joseph Wenninger (jowenn@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+#include "config.h"
+
+#include "kmainwindow.h"
+#include "kmainwindowiface.h"
+#include "ktoolbarhandler.h"
+#include "kwhatsthismanager_p.h"
+#include <qsessionmanager.h>
+#include <qobjectlist.h>
+#include <qstyle.h>
+#include <qlayout.h>
+#include <qwidgetlist.h>
+#include <qtimer.h>
+
+#include <kaccel.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <khelpmenu.h>
+#include <kmenubar.h>
+#include <kstatusbar.h>
+#include <kwin.h>
+#include <kedittoolbar.h>
+#include <kmainwindow.h>
+
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kstaticdeleter.h>
+#if defined Q_WS_X11
+#include <netwm.h>
+#endif
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <assert.h>
+
+class KMainWindowPrivate {
+public:
+ bool showHelpMenu:1;
+
+ bool autoSaveSettings:1;
+ bool settingsDirty:1;
+ bool autoSaveWindowSize:1;
+ bool care_about_geometry:1;
+ bool shuttingDown:1;
+ QString autoSaveGroup;
+ KAccel * kaccel;
+ KMainWindowInterface *m_interface;
+ KDEPrivate::ToolBarHandler *toolBarHandler;
+ QTimer* settingsTimer;
+ KToggleAction *showStatusBarAction;
+ QRect defaultWindowSize;
+ QPtrList<QDockWindow> hiddenDockWindows;
+};
+
+QPtrList<KMainWindow>* KMainWindow::memberList = 0L;
+static bool no_query_exit = false;
+static KMWSessionManaged* ksm = 0;
+static KStaticDeleter<KMWSessionManaged> ksmd;
+
+class KMWSessionManaged : public KSessionManaged
+{
+public:
+ KMWSessionManaged()
+ {
+ }
+ ~KMWSessionManaged()
+ {
+ }
+ bool saveState( QSessionManager& )
+ {
+ KConfig* config = KApplication::kApplication()->sessionConfig();
+ if ( KMainWindow::memberList->first() ){
+ // According to Jochen Wilhelmy <digisnap@cs.tu-berlin.de>, this
+ // hook is useful for better document orientation
+ KMainWindow::memberList->first()->saveGlobalProperties(config);
+ }
+
+ QPtrListIterator<KMainWindow> it(*KMainWindow::memberList);
+ int n = 0;
+ for (it.toFirst(); it.current(); ++it){
+ n++;
+ it.current()->savePropertiesInternal(config, n);
+ }
+ config->setGroup(QString::fromLatin1("Number"));
+ config->writeEntry(QString::fromLatin1("NumberOfWindows"), n );
+ return true;
+ }
+
+ bool commitData( QSessionManager& sm )
+ {
+ // not really a fast method but the only compatible one
+ if ( sm.allowsInteraction() ) {
+ bool canceled = false;
+ QPtrListIterator<KMainWindow> it(*KMainWindow::memberList);
+ ::no_query_exit = true;
+ for (it.toFirst(); it.current() && !canceled;){
+ KMainWindow *window = *it;
+ ++it; // Update now, the current window might get deleted
+ if ( !window->testWState( Qt::WState_ForceHide ) ) {
+ QCloseEvent e;
+ QApplication::sendEvent( window, &e );
+ canceled = !e.isAccepted();
+ /* Don't even think_about deleting widgets with
+ Qt::WDestructiveClose flag set at this point. We
+ are faking a close event, but we are *not*_
+ closing the window. The purpose of the faked
+ close event is to prepare the application so it
+ can safely be quit without the user losing data
+ (possibly showing a message box "do you want to
+ save this or that?"). It is possible that the
+ session manager quits the application later
+ (emitting QApplication::aboutToQuit() when this
+ happens), but it is also possible that the user
+ cancels the shutdown, so the application will
+ continue to run.
+ */
+ }
+ }
+ ::no_query_exit = false;
+ if (canceled)
+ return false;
+
+ KMainWindow* last = 0;
+ for (it.toFirst(); it.current() && !canceled; ++it){
+ KMainWindow *window = *it;
+ if ( !window->testWState( Qt::WState_ForceHide ) ) {
+ last = window;
+ }
+ }
+ if ( last )
+ return last->queryExit();
+ // else
+ return true;
+ }
+
+ // the user wants it, the user gets it
+ return true;
+ }
+};
+
+static bool being_first = true;
+
+KMainWindow::KMainWindow( QWidget* parent, const char *name, WFlags f )
+ : QMainWindow( parent, name, f ), KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 )
+{
+ initKMainWindow(name, 0);
+}
+
+KMainWindow::KMainWindow( int cflags, QWidget* parent, const char *name, WFlags f )
+ : QMainWindow( parent, name, f ), KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 )
+{
+ initKMainWindow(name, cflags);
+}
+
+void KMainWindow::initKMainWindow(const char *name, int cflags)
+{
+ KWhatsThisManager::init ();
+ setDockMenuEnabled( false );
+ mHelpMenu = 0;
+ kapp->setTopWidget( this );
+ actionCollection()->setWidget( this );
+ connect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown()));
+ if( !memberList )
+ memberList = new QPtrList<KMainWindow>;
+
+ if ( !ksm )
+ ksm = ksmd.setObject(ksm, new KMWSessionManaged());
+ // set a unique object name. Required by session management.
+ QCString objname;
+ QCString s;
+ int unusedNumber;
+ if ( !name )
+ { // no name given
+ objname = kapp->instanceName() + "-mainwindow#";
+ s = objname + '1'; // start adding number immediately
+ unusedNumber = 1;
+ }
+ else if( name[0] != '\0' && name[ strlen( name ) - 1 ] == '#' )
+ { // trailing # - always add a number
+ objname = name;
+ s = objname + '1'; // start adding number immediately
+ unusedNumber = 1;
+ }
+ else
+ {
+ objname = name;
+ s = objname;
+ unusedNumber = 0; // add numbers only when needed
+ }
+ for(;;) {
+ QWidgetList* list = kapp->topLevelWidgets();
+ QWidgetListIt it( *list );
+ bool found = false;
+ for( QWidget* w = it.current();
+ w != NULL;
+ ++it, w = it.current())
+ if( w != this && w->name() == s )
+ {
+ found = true;
+ break;
+ }
+ delete list;
+ if( !found )
+ break;
+ s.setNum( ++unusedNumber );
+ s = objname + s;
+ }
+ setName( s );
+
+ memberList->append( this );
+
+ d = new KMainWindowPrivate;
+ d->showHelpMenu = true;
+ d->settingsDirty = false;
+ d->autoSaveSettings = false;
+ d->autoSaveWindowSize = true; // for compatibility
+ d->kaccel = actionCollection()->kaccel();
+ d->toolBarHandler = 0;
+ d->settingsTimer = 0;
+ d->showStatusBarAction = NULL;
+ d->shuttingDown = false;
+ if ((d->care_about_geometry = being_first)) {
+ being_first = false;
+ if ( kapp->geometryArgument().isNull() ) // if there is no geometry, it doesn't mater
+ d->care_about_geometry = false;
+ else
+ parseGeometry(false);
+ }
+
+ setCaption( kapp->caption() );
+ if ( cflags & NoDCOPObject)
+ d->m_interface = 0;
+ else
+ d->m_interface = new KMainWindowInterface(this);
+
+ if (!kapp->authorize("movable_toolbars"))
+ setDockWindowsMovable(false);
+}
+
+KAction *KMainWindow::toolBarMenuAction()
+{
+ if ( !d->toolBarHandler )
+ return 0;
+
+ return d->toolBarHandler->toolBarMenuAction();
+}
+
+
+void KMainWindow::setupToolbarMenuActions()
+{
+ if ( d->toolBarHandler )
+ d->toolBarHandler->setupActions();
+}
+
+void KMainWindow::parseGeometry(bool parsewidth)
+{
+ assert ( !kapp->geometryArgument().isNull() );
+ assert ( d->care_about_geometry );
+
+#if defined Q_WS_X11
+ int x, y;
+ int w, h;
+ int m = XParseGeometry( kapp->geometryArgument().latin1(), &x, &y, (unsigned int*)&w, (unsigned int*)&h);
+ if (parsewidth) {
+ QSize minSize = minimumSize();
+ QSize maxSize = maximumSize();
+ if ( !(m & WidthValue) )
+ w = width();
+ if ( !(m & HeightValue) )
+ h = height();
+ w = QMIN(w,maxSize.width());
+ h = QMIN(h,maxSize.height());
+ w = QMAX(w,minSize.width());
+ h = QMAX(h,minSize.height());
+ resize(w, h);
+ } else {
+ if ( parsewidth && !(m & XValue) )
+ x = geometry().x();
+ if ( parsewidth && !(m & YValue) )
+ y = geometry().y();
+ if ( (m & XNegative) )
+ x = KApplication::desktop()->width() + x - w;
+ if ( (m & YNegative) )
+ y = KApplication::desktop()->height() + y - h;
+ move(x, y);
+ }
+#endif
+}
+
+KMainWindow::~KMainWindow()
+{
+ delete d->settingsTimer;
+ QMenuBar* mb = internalMenuBar();
+ delete mb;
+ delete d->m_interface;
+ delete d;
+ memberList->remove( this );
+}
+
+KPopupMenu* KMainWindow::helpMenu( const QString &aboutAppText, bool showWhatsThis )
+{
+ if( !mHelpMenu ) {
+ if ( aboutAppText.isEmpty() )
+ mHelpMenu = new KHelpMenu( this, instance()->aboutData(), showWhatsThis);
+ else
+ mHelpMenu = new KHelpMenu( this, aboutAppText, showWhatsThis );
+
+ if ( !mHelpMenu )
+ return 0;
+ connect( mHelpMenu, SIGNAL( showAboutApplication() ),
+ this, SLOT( showAboutApplication() ) );
+ }
+
+ return mHelpMenu->menu();
+}
+
+KPopupMenu* KMainWindow::customHelpMenu( bool showWhatsThis )
+{
+ if( !mHelpMenu ) {
+ mHelpMenu = new KHelpMenu( this, QString::null, showWhatsThis );
+ connect( mHelpMenu, SIGNAL( showAboutApplication() ),
+ this, SLOT( showAboutApplication() ) );
+ }
+
+ return mHelpMenu->menu();
+}
+
+bool KMainWindow::canBeRestored( int number )
+{
+ if ( !kapp->isRestored() )
+ return false;
+ KConfig *config = kapp->sessionConfig();
+ if ( !config )
+ return false;
+ config->setGroup( QString::fromLatin1("Number") );
+ int n = config->readNumEntry( QString::fromLatin1("NumberOfWindows") , 1 );
+ return number >= 1 && number <= n;
+}
+
+const QString KMainWindow::classNameOfToplevel( int number )
+{
+ if ( !kapp->isRestored() )
+ return QString::null;
+ KConfig *config = kapp->sessionConfig();
+ if ( !config )
+ return QString::null;
+ QString s;
+ s.setNum( number );
+ s.prepend( QString::fromLatin1("WindowProperties") );
+ config->setGroup( s );
+ if ( !config->hasKey( QString::fromLatin1("ClassName") ) )
+ return QString::null;
+ else
+ return config->readEntry( QString::fromLatin1("ClassName") );
+}
+
+void KMainWindow::show()
+{
+ QMainWindow::show();
+
+ for ( QPtrListIterator<QDockWindow> it( d->hiddenDockWindows ); it.current(); ++it )
+ it.current()->show();
+
+ d->hiddenDockWindows.clear();
+}
+
+void KMainWindow::hide()
+{
+ if ( isVisible() ) {
+
+ d->hiddenDockWindows.clear();
+
+ QObjectList *list = queryList( "QDockWindow" );
+ for( QObjectListIt it( *list ); it.current(); ++it ) {
+ QDockWindow *dw = (QDockWindow*)it.current();
+ if ( dw->isTopLevel() && dw->isVisible() ) {
+ d->hiddenDockWindows.append( dw );
+ dw->hide();
+ }
+ }
+ delete list;
+ }
+
+ QWidget::hide();
+}
+
+bool KMainWindow::restore( int number, bool show )
+{
+ if ( !canBeRestored( number ) )
+ return false;
+ KConfig *config = kapp->sessionConfig();
+ if ( readPropertiesInternal( config, number ) ){
+ if ( show )
+ KMainWindow::show();
+ return false;
+ }
+ return false;
+}
+
+KXMLGUIFactory *KMainWindow::guiFactory()
+{
+ if ( !factory_ )
+ factory_ = new KXMLGUIFactory( this, this, "guifactory" );
+ return factory_;
+}
+
+int KMainWindow::configureToolbars()
+{
+ saveMainWindowSettings(KGlobal::config());
+ KEditToolbar dlg(actionCollection(), xmlFile(), true, this);
+ connect(&dlg, SIGNAL(newToolbarConfig()), SLOT(saveNewToolbarConfig()));
+ return dlg.exec();
+}
+
+void KMainWindow::saveNewToolbarConfig()
+{
+ createGUI(xmlFile());
+ applyMainWindowSettings( KGlobal::config() );
+}
+
+void KMainWindow::setupGUI( int options, const QString & xmlfile ) {
+ setupGUI(QSize(), options, xmlfile);
+}
+
+void KMainWindow::setupGUI( QSize defaultSize, int options, const QString & xmlfile ) {
+ if( options & Keys ){
+ KStdAction::keyBindings(guiFactory(),
+ SLOT(configureShortcuts()), actionCollection());
+ }
+
+ if( (options & StatusBar) && internalStatusBar() ){
+ createStandardStatusBarAction();
+ }
+
+ if( options & ToolBar ){
+ setStandardToolBarMenuEnabled( true );
+ KStdAction::configureToolbars(this,
+ SLOT(configureToolbars() ), actionCollection());
+ }
+
+ if( options & Create ){
+ createGUI(xmlfile,false);
+ }
+
+ if( options & Save ){
+ // setupGUI() is typically called in the constructor before show(),
+ // so the default window size will be incorrect unless the application
+ // hard coded the size which they should try not to do (i.e. use
+ // size hints).
+ if(initialGeometrySet())
+ {
+ // Do nothing...
+ }
+ else if(defaultSize.isValid())
+ {
+ resize(defaultSize);
+ }
+ else if(!isShown())
+ {
+ adjustSize();
+ }
+ setAutoSaveSettings();
+ }
+
+}
+
+void KMainWindow::createGUI( const QString &xmlfile, bool _conserveMemory )
+{
+ // disabling the updates prevents unnecessary redraws
+ setUpdatesEnabled( false );
+
+ // just in case we are rebuilding, let's remove our old client
+ guiFactory()->removeClient( this );
+
+ // make sure to have an empty GUI
+ QMenuBar* mb = internalMenuBar();
+ if ( mb )
+ mb->clear();
+
+ (void)toolBarIterator(); // make sure toolbarList is most-up-to-date
+ toolbarList.setAutoDelete( true );
+ toolbarList.clear();
+ toolbarList.setAutoDelete( false );
+
+ // don't build a help menu unless the user ask for it
+ if (d->showHelpMenu) {
+ // we always want a help menu
+ if (!helpMenu2)
+ helpMenu2 = new KHelpMenu(this, instance()->aboutData(), true,
+ actionCollection());
+ }
+
+ // we always want to load in our global standards file
+ setXMLFile( locate( "config", "ui/ui_standards.rc", instance() ) );
+
+ // now, merge in our local xml file. if this is null, then that
+ // means that we will be only using the global file
+ if ( !xmlfile.isNull() ) {
+ setXMLFile( xmlfile, true );
+ } else {
+ QString auto_file(instance()->instanceName() + "ui.rc");
+ setXMLFile( auto_file, true );
+ }
+
+ // make sure we don't have any state saved already
+ setXMLGUIBuildDocument( QDomDocument() );
+
+ // do the actual GUI building
+ guiFactory()->addClient( this );
+
+ // try and get back *some* of our memory
+ if ( _conserveMemory )
+ {
+ // before freeing the memory allocated by the DOM document we also
+ // free all memory allocated internally in the KXMLGUIFactory for
+ // the menubar and the toolbars . This however implies that we
+ // have to take care of deleting those widgets ourselves. For
+ // destruction this is no problem, but when rebuilding we have
+ // to take care of that (and we want to rebuild the GUI when
+ // using stuff like the toolbar editor ).
+ // In addition we have to take care of not removing containers
+ // like popupmenus, defined in the XML document.
+ // this code should probably go into a separate method in KMainWindow.
+ // there's just one problem: I'm bad in finding names ;-) , so
+ // I skipped this ;-)
+
+ QDomDocument doc = domDocument();
+
+ for( QDomNode n = doc.documentElement().firstChild();
+ !n.isNull(); n = n.nextSibling())
+ {
+ QDomElement e = n.toElement();
+
+ if ( e.tagName().lower() == "toolbar" )
+ factory_->resetContainer( e.attribute( "name" ) );
+ else if ( e.tagName().lower() == "menubar" )
+ factory_->resetContainer( e.tagName(), true );
+ }
+
+ conserveMemory();
+ }
+
+ setUpdatesEnabled( true );
+ updateGeometry();
+}
+
+void KMainWindow::setHelpMenuEnabled(bool showHelpMenu)
+{
+ d->showHelpMenu = showHelpMenu;
+}
+
+bool KMainWindow::isHelpMenuEnabled()
+{
+ return d->showHelpMenu;
+}
+
+void KMainWindow::setCaption( const QString &caption )
+{
+ setPlainCaption( kapp->makeStdCaption(caption) );
+}
+
+void KMainWindow::setCaption( const QString &caption, bool modified )
+{
+ setPlainCaption( kapp->makeStdCaption(caption, true, modified) );
+}
+
+void KMainWindow::setPlainCaption( const QString &caption )
+{
+ QMainWindow::setCaption( caption );
+#if defined Q_WS_X11
+ NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), 0 );
+ info.setName( caption.utf8().data() );
+#endif
+}
+
+void KMainWindow::appHelpActivated( void )
+{
+ if( !mHelpMenu ) {
+ mHelpMenu = new KHelpMenu( this );
+ if ( !mHelpMenu )
+ return;
+ }
+ mHelpMenu->appHelpActivated();
+}
+
+void KMainWindow::slotStateChanged(const QString &newstate)
+{
+ stateChanged(newstate, KXMLGUIClient::StateNoReverse);
+}
+
+/*
+ * Get rid of this for KDE 4.0
+ */
+void KMainWindow::slotStateChanged(const QString &newstate,
+ KXMLGUIClient::ReverseStateChange reverse)
+{
+ stateChanged(newstate, reverse);
+}
+
+/*
+ * Enable this for KDE 4.0
+ */
+// void KMainWindow::slotStateChanged(const QString &newstate,
+// bool reverse)
+// {
+// stateChanged(newstate,
+// reverse ? KXMLGUIClient::StateReverse : KXMLGUIClient::StateNoReverse);
+// }
+
+void KMainWindow::closeEvent ( QCloseEvent *e )
+{
+ // Save settings if auto-save is enabled, and settings have changed
+ if (d->settingsDirty && d->autoSaveSettings)
+ saveAutoSaveSettings();
+
+ if (queryClose()) {
+ e->accept();
+
+ int not_withdrawn = 0;
+ QPtrListIterator<KMainWindow> it(*KMainWindow::memberList);
+ for (it.toFirst(); it.current(); ++it){
+ if ( !it.current()->isHidden() && it.current()->isTopLevel() && it.current() != this )
+ not_withdrawn++;
+ }
+
+ if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted?
+ if ( queryExit() && !kapp->sessionSaving() && !d->shuttingDown ) { // Yes, Quit app?
+ // don't call queryExit() twice
+ disconnect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown()));
+ d->shuttingDown = true;
+ kapp->deref(); // ...and quit application.
+ } else {
+ // cancel closing, it's stupid to end up with no windows at all....
+ e->ignore();
+ }
+ }
+ }
+}
+
+bool KMainWindow::queryExit()
+{
+ return true;
+}
+
+bool KMainWindow::queryClose()
+{
+ return true;
+}
+
+void KMainWindow::saveGlobalProperties( KConfig* )
+{
+}
+
+void KMainWindow::readGlobalProperties( KConfig* )
+{
+}
+
+#if defined(KDE_COMPAT)
+void KMainWindow::updateRects()
+{
+}
+#endif
+
+void KMainWindow::showAboutApplication()
+{
+}
+
+void KMainWindow::savePropertiesInternal( KConfig *config, int number )
+{
+ bool oldASWS = d->autoSaveWindowSize;
+ d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size
+
+ QString s;
+ s.setNum(number);
+ s.prepend(QString::fromLatin1("WindowProperties"));
+ config->setGroup(s);
+
+ // store objectName, className, Width and Height for later restoring
+ // (Only useful for session management)
+ config->writeEntry(QString::fromLatin1("ObjectName"), name());
+ config->writeEntry(QString::fromLatin1("ClassName"), className());
+
+ saveMainWindowSettings(config); // Menubar, statusbar and Toolbar settings.
+
+ s.setNum(number);
+ config->setGroup(s);
+ saveProperties(config);
+
+ d->autoSaveWindowSize = oldASWS;
+}
+
+void KMainWindow::saveMainWindowSettings(KConfig *config, const QString &configGroup)
+{
+ kdDebug(200) << "KMainWindow::saveMainWindowSettings " << configGroup << endl;
+ QString oldGroup;
+
+ if (!configGroup.isEmpty())
+ {
+ oldGroup = config->group();
+ config->setGroup(configGroup);
+ }
+
+ // Called by session management - or if we want to save the window size anyway
+ if ( d->autoSaveWindowSize )
+ saveWindowSize( config );
+
+ QStatusBar* sb = internalStatusBar();
+ if (sb) {
+ if(!config->hasDefault("StatusBar") && !sb->isHidden() )
+ config->revertToDefault("StatusBar");
+ else
+ config->writeEntry("StatusBar", sb->isHidden() ? "Disabled" : "Enabled");
+ }
+
+ QMenuBar* mb = internalMenuBar();
+ if (mb) {
+ QString MenuBar = QString::fromLatin1("MenuBar");
+ if(!config->hasDefault("MenuBar") && !mb->isHidden() )
+ config->revertToDefault("MenuBar");
+ else
+ config->writeEntry("MenuBar", mb->isHidden() ? "Disabled" : "Enabled");
+ }
+
+ int n = 1; // Toolbar counter. toolbars are counted from 1,
+ KToolBar *toolbar = 0;
+ QPtrListIterator<KToolBar> it( toolBarIterator() );
+ while ( ( toolbar = it.current() ) ) {
+ ++it;
+ QString group;
+ if (!configGroup.isEmpty())
+ {
+ // Give a number to the toolbar, but prefer a name if there is one,
+ // because there's no real guarantee on the ordering of toolbars
+ group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name());
+ group.prepend(" Toolbar");
+ group.prepend(configGroup);
+ }
+ toolbar->saveSettings(config, group);
+ n++;
+ }
+ if (!configGroup.isEmpty())
+ config->setGroup(oldGroup);
+}
+
+void KMainWindow::setStandardToolBarMenuEnabled( bool enable )
+{
+ if ( enable ) {
+ if ( d->toolBarHandler )
+ return;
+
+ d->toolBarHandler = new KDEPrivate::ToolBarHandler( this );
+
+ if ( factory() )
+ factory()->addClient( d->toolBarHandler );
+ } else {
+ if ( !d->toolBarHandler )
+ return;
+
+ if ( factory() )
+ factory()->removeClient( d->toolBarHandler );
+
+ delete d->toolBarHandler;
+ d->toolBarHandler = 0;
+ }
+}
+
+bool KMainWindow::isStandardToolBarMenuEnabled() const
+{
+ return ( d->toolBarHandler );
+}
+
+void KMainWindow::createStandardStatusBarAction(){
+ if(!d->showStatusBarAction){
+ d->showStatusBarAction = KStdAction::showStatusbar(this, SLOT(setSettingsDirty()), actionCollection());
+ KStatusBar *sb = statusBar(); // Creates statusbar if it doesn't exist already.
+ connect(d->showStatusBarAction, SIGNAL(toggled(bool)), sb, SLOT(setShown(bool)));
+ d->showStatusBarAction->setChecked(sb->isHidden());
+ }
+}
+
+bool KMainWindow::readPropertiesInternal( KConfig *config, int number )
+{
+ if ( number == 1 )
+ readGlobalProperties( config );
+
+ // in order they are in toolbar list
+ QString s;
+ s.setNum(number);
+ s.prepend(QString::fromLatin1("WindowProperties"));
+
+ config->setGroup(s);
+
+ // restore the object name (window role)
+ if ( config->hasKey(QString::fromLatin1("ObjectName" )) )
+ setName( config->readEntry(QString::fromLatin1("ObjectName")).latin1()); // latin1 is right here
+
+ applyMainWindowSettings(config); // Menubar, statusbar and toolbar settings.
+
+ s.setNum(number);
+ config->setGroup(s);
+ readProperties(config);
+ return true;
+}
+
+void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup)
+{
+ return applyMainWindowSettings(config,configGroup,false);
+}
+
+void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup,bool force)
+{
+ kdDebug(200) << "KMainWindow::applyMainWindowSettings" << endl;
+
+ KConfigGroupSaver saver( config, configGroup.isEmpty() ? config->group() : configGroup );
+
+ restoreWindowSize(config);
+
+ QStatusBar* sb = internalStatusBar();
+ if (sb) {
+ QString entry = config->readEntry("StatusBar", "Enabled");
+ if ( entry == "Disabled" )
+ sb->hide();
+ else
+ sb->show();
+ if(d->showStatusBarAction)
+ d->showStatusBarAction->setChecked(!sb->isHidden());
+ }
+
+ QMenuBar* mb = internalMenuBar();
+ if (mb) {
+ QString entry = config->readEntry ("MenuBar", "Enabled");
+ if ( entry == "Disabled" )
+ mb->hide();
+ else
+ mb->show();
+ }
+
+ int n = 1; // Toolbar counter. toolbars are counted from 1,
+ KToolBar *toolbar;
+ QPtrListIterator<KToolBar> it( toolBarIterator() ); // must use own iterator
+
+ for ( ; it.current(); ++it) {
+ toolbar= it.current();
+ QString group;
+ if (!configGroup.isEmpty())
+ {
+ // Give a number to the toolbar, but prefer a name if there is one,
+ // because there's no real guarantee on the ordering of toolbars
+ group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name());
+ group.prepend(" Toolbar");
+ group.prepend(configGroup);
+ }
+ toolbar->applySettings(config, group, force);
+ n++;
+ }
+
+ finalizeGUI( true );
+}
+
+void KMainWindow::finalizeGUI( bool force )
+{
+ //kdDebug(200) << "KMainWindow::finalizeGUI force=" << force << endl;
+ // The whole reason for this is that moveToolBar relies on the indexes
+ // of the other toolbars, so in theory it should be called only once per
+ // toolbar, but in increasing order of indexes.
+ // Since we can't do that immediately, we move them, and _then_
+ // we call positionYourself again for each of them, but this time
+ // the toolbariterator should give them in the proper order.
+ // Both the XMLGUI and applySettings call this, hence "force" for the latter.
+ QPtrListIterator<KToolBar> it( toolBarIterator() );
+ for ( ; it.current() ; ++it ) {
+ it.current()->positionYourself( force );
+ }
+
+ d->settingsDirty = false;
+}
+
+void KMainWindow::saveWindowSize( KConfig * config ) const
+{
+ int scnum = QApplication::desktop()->screenNumber(parentWidget());
+ QRect desk = QApplication::desktop()->screenGeometry(scnum);
+ int w, h;
+#if defined Q_WS_X11
+ // save maximalization as desktop size + 1 in that direction
+ KWin::WindowInfo info = KWin::windowInfo( winId(), NET::WMState );
+ w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width();
+ h = info.state() & NET::MaxVert ? desk.height() + 1 : height();
+#else
+ if (isMaximized()) {
+ w = desk.width() + 1;
+ h = desk.height() + 1;
+ }
+ //TODO: add "Maximized" property instead "+1" hack
+#endif
+ QRect size( desk.width(), w, desk.height(), h );
+ bool defaultSize = (size == d->defaultWindowSize);
+ QString widthString = QString::fromLatin1("Width %1").arg(desk.width());
+ QString heightString = QString::fromLatin1("Height %1").arg(desk.height());
+ if (!config->hasDefault(widthString) && defaultSize)
+ config->revertToDefault(widthString);
+ else
+ config->writeEntry(widthString, w );
+
+ if (!config->hasDefault(heightString) && defaultSize)
+ config->revertToDefault(heightString);
+ else
+ config->writeEntry(heightString, h );
+}
+
+void KMainWindow::restoreWindowSize( KConfig * config )
+{
+ if (d->care_about_geometry) {
+ parseGeometry(true);
+ } else {
+ // restore the size
+ int scnum = QApplication::desktop()->screenNumber(parentWidget());
+ QRect desk = QApplication::desktop()->screenGeometry(scnum);
+ if ( d->defaultWindowSize.isNull() ) // only once
+ d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); // store default values
+ QSize size( config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ),
+ config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) );
+ if (size.isEmpty()) {
+ // try the KDE 2.0 way
+ size = QSize( config->readNumEntry( QString::fromLatin1("Width"), 0 ),
+ config->readNumEntry( QString::fromLatin1("Height"), 0 ) );
+ if (!size.isEmpty()) {
+ // make sure the other resolutions don't get old settings
+ config->writeEntry( QString::fromLatin1("Width"), 0 );
+ config->writeEntry( QString::fromLatin1("Height"), 0 );
+ }
+ }
+ if ( !size.isEmpty() ) {
+#ifdef Q_WS_X11
+ int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 )
+ | ( size.height() > desk.height() ? NET::MaxVert : 0 );
+ if(( state & NET::Max ) == NET::Max )
+ ; // no resize
+ else if(( state & NET::MaxHoriz ) == NET::MaxHoriz )
+ resize( width(), size.height());
+ else if(( state & NET::MaxVert ) == NET::MaxVert )
+ resize( size.width(), height());
+ else
+ resize( size );
+ // QWidget::showMaximized() is both insufficient and broken
+ KWin::setState( winId(), state );
+#else
+ if (size.width() > desk.width() || size.height() > desk.height())
+ setWindowState( WindowMaximized );
+ else
+ resize( size );
+#endif
+ }
+ }
+}
+
+bool KMainWindow::initialGeometrySet() const
+{
+ return d->care_about_geometry;
+}
+
+void KMainWindow::ignoreInitialGeometry()
+{
+ d->care_about_geometry = false;
+}
+
+void KMainWindow::setSettingsDirty()
+{
+ //kdDebug(200) << "KMainWindow::setSettingsDirty" << endl;
+ d->settingsDirty = true;
+ if ( d->autoSaveSettings )
+ {
+ // Use a timer to save "immediately" user-wise, but not too immediately
+ // (to compress calls and save only once, in case of multiple changes)
+ if ( !d->settingsTimer )
+ {
+ d->settingsTimer = new QTimer( this );
+ connect( d->settingsTimer, SIGNAL( timeout() ), SLOT( saveAutoSaveSettings() ) );
+ }
+ d->settingsTimer->start( 500, true );
+ }
+}
+
+bool KMainWindow::settingsDirty() const
+{
+ return d->settingsDirty;
+}
+
+QString KMainWindow::settingsGroup() const
+{
+ return d->autoSaveGroup;
+}
+
+void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize )
+{
+ d->autoSaveSettings = true;
+ d->autoSaveGroup = groupName;
+ d->autoSaveWindowSize = saveWindowSize;
+ // Get notified when the user moves a toolbar around
+ disconnect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ),
+ this, SLOT( setSettingsDirty() ) );
+ connect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ),
+ this, SLOT( setSettingsDirty() ) );
+
+ // Now read the previously saved settings
+ applyMainWindowSettings( KGlobal::config(), groupName );
+}
+
+void KMainWindow::resetAutoSaveSettings()
+{
+ d->autoSaveSettings = false;
+ if ( d->settingsTimer )
+ d->settingsTimer->stop();
+}
+
+bool KMainWindow::autoSaveSettings() const
+{
+ return d->autoSaveSettings;
+}
+
+QString KMainWindow::autoSaveGroup() const
+{
+ return d->autoSaveGroup;
+}
+
+void KMainWindow::saveAutoSaveSettings()
+{
+ Q_ASSERT( d->autoSaveSettings );
+ //kdDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings" << endl;
+ saveMainWindowSettings( KGlobal::config(), d->autoSaveGroup );
+ KGlobal::config()->sync();
+ d->settingsDirty = false;
+ if ( d->settingsTimer )
+ d->settingsTimer->stop();
+}
+
+void KMainWindow::resizeEvent( QResizeEvent * )
+{
+ if ( d->autoSaveWindowSize )
+ setSettingsDirty();
+}
+
+bool KMainWindow::hasMenuBar()
+{
+ return (internalMenuBar());
+}
+
+KMenuBar *KMainWindow::menuBar()
+{
+ KMenuBar * mb = internalMenuBar();
+ if ( !mb ) {
+ mb = new KMenuBar( this );
+ // trigger a re-layout and trigger a call to the private
+ // setMenuBar method.
+ QMainWindow::menuBar();
+ }
+ return mb;
+}
+
+KStatusBar *KMainWindow::statusBar()
+{
+ KStatusBar * sb = internalStatusBar();
+ if ( !sb ) {
+ sb = new KStatusBar( this );
+ // trigger a re-layout and trigger a call to the private
+ // setStatusBar method.
+ QMainWindow::statusBar();
+ }
+ return sb;
+}
+
+void KMainWindow::shuttingDown()
+{
+ // Needed for Qt <= 3.0.3 at least to prevent reentrancy
+ // when queryExit() shows a dialog. Check before removing!
+ static bool reentrancy_protection = false;
+ if (!reentrancy_protection)
+ {
+ reentrancy_protection = true;
+ // call the virtual queryExit
+ queryExit();
+ reentrancy_protection = false;
+ }
+
+}
+
+KMenuBar *KMainWindow::internalMenuBar()
+{
+ QObjectList *l = queryList( "KMenuBar", 0, false, false );
+ if ( !l || !l->first() ) {
+ delete l;
+ return 0;
+ }
+
+ KMenuBar *m = (KMenuBar*)l->first();
+ delete l;
+ return m;
+}
+
+KStatusBar *KMainWindow::internalStatusBar()
+{
+ QObjectList *l = queryList( "KStatusBar", 0, false, false );
+ if ( !l || !l->first() ) {
+ delete l;
+ return 0;
+ }
+
+ KStatusBar *s = (KStatusBar*)l->first();
+ delete l;
+ return s;
+}
+
+void KMainWindow::childEvent( QChildEvent* e)
+{
+ QMainWindow::childEvent( e );
+}
+
+KToolBar *KMainWindow::toolBar( const char * name )
+{
+ if (!name)
+ name = "mainToolBar";
+ KToolBar *tb = (KToolBar*)child( name, "KToolBar" );
+ if ( tb )
+ return tb;
+ bool honor_mode = (!strcmp(name, "mainToolBar"));
+
+ if ( builderClient() )
+ return new KToolBar(this, name, honor_mode); // XMLGUI constructor
+ else
+ return new KToolBar(this, DockTop, false, name, honor_mode ); // non-XMLGUI
+}
+
+QPtrListIterator<KToolBar> KMainWindow::toolBarIterator()
+{
+ toolbarList.clear();
+ QPtrList<QToolBar> lst;
+ for ( int i = (int)QMainWindow::DockUnmanaged; i <= (int)DockMinimized; ++i ) {
+ lst = toolBars( (ToolBarDock)i );
+ for ( QToolBar *tb = lst.first(); tb; tb = lst.next() ) {
+ if ( !tb->inherits( "KToolBar" ) )
+ continue;
+ toolbarList.append( (KToolBar*)tb );
+ }
+ }
+ return QPtrListIterator<KToolBar>( toolbarList );
+}
+
+KAccel * KMainWindow::accel()
+{
+ if ( !d->kaccel )
+ d->kaccel = new KAccel( this, "kmw-kaccel" );
+ return d->kaccel;
+}
+
+void KMainWindow::paintEvent( QPaintEvent * pe )
+{
+ QMainWindow::paintEvent(pe); //Upcall to handle SH_MainWindow_SpaceBelowMenuBar rendering
+}
+
+QSize KMainWindow::sizeForCentralWidgetSize(QSize size)
+{
+ KToolBar *tb = (KToolBar*)child( "mainToolBar", "KToolBar" );
+ if (tb && !tb->isHidden()) {
+ switch( tb->barPos() )
+ {
+ case KToolBar::Top:
+ case KToolBar::Bottom:
+ size += QSize(0, tb->sizeHint().height());
+ break;
+
+ case KToolBar::Left:
+ case KToolBar::Right:
+ size += QSize(toolBar()->sizeHint().width(), 0);
+ break;
+
+ case KToolBar::Flat:
+ size += QSize(0, 3+kapp->style().pixelMetric( QStyle::PM_DockWindowHandleExtent ));
+ break;
+
+ default:
+ break;
+ }
+ }
+ KMenuBar *mb = internalMenuBar();
+ if (mb && !mb->isHidden()) {
+ size += QSize(0,mb->heightForWidth(size.width()));
+ if (style().styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, this))
+ size += QSize( 0, dockWindowsMovable() ? 1 : 2);
+ }
+ QStatusBar *sb = internalStatusBar();
+ if( sb && !sb->isHidden() )
+ size += QSize(0, sb->sizeHint().height());
+
+ return size;
+}
+
+#if KDE_IS_VERSION( 3, 9, 0 )
+#ifdef __GNUC__
+#warning Remove, should be in Qt
+#endif
+#endif
+void KMainWindow::setIcon( const QPixmap& p )
+{
+ QMainWindow::setIcon( p );
+#ifdef Q_WS_X11
+ // Qt3 doesn't support _NET_WM_ICON, but KApplication::setTopWidget(), which
+ // is used by KMainWindow, sets it
+ KWin::setIcons( winId(), p, QPixmap());
+#endif
+}
+
+QPtrList<KMainWindow>* KMainWindow::getMemberList() { return memberList; }
+
+// why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI;
+// DF: because they compile KDE much faster :)
+void KMainWindow::finalizeGUI( KXMLGUIClient *client )
+{ KXMLGUIBuilder::finalizeGUI( client ); }
+
+void KMainWindow::virtual_hook( int id, void* data )
+{ KXMLGUIBuilder::virtual_hook( id, data );
+ KXMLGUIClient::virtual_hook( id, data ); }
+
+
+
+#include "kmainwindow.moc"
+