fix tricky regression noticed by Vyacheslav Tokarev on Google Reader.
[kdelibs.git] / kdeui / xmlgui / kxmlguiwindow.cpp
blobfc5d793b145e11eb79046edbe458ce030592c0b0
1 /* This file is part of the KDE libraries
2 Copyright
3 (C) 2000 Reginald Stadlbauer (reggie@kde.org)
4 (C) 1997 Stephan Kulow (coolo@kde.org)
5 (C) 1997-2000 Sven Radej (radej@kde.org)
6 (C) 1997-2000 Matthias Ettrich (ettrich@kde.org)
7 (C) 1999 Chris Schlaeger (cs@kde.org)
8 (C) 2002 Joseph Wenninger (jowenn@kde.org)
9 (C) 2005-2006 Hamish Rodda (rodda@kde.org)
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Library General Public
13 License version 2 as published by the Free Software Foundation.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
20 You should have received a copy of the GNU Library General Public License
21 along with this library; see the file COPYING.LIB. If not, write to
22 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 Boston, MA 02110-1301, USA.
26 #include "kxmlguiwindow.h"
27 #include "kmainwindow_p.h"
28 #include "kactioncollection.h"
29 #include "kmainwindowiface_p.h"
30 #include "ktoolbarhandler.h"
31 #include "kwhatsthismanager_p.h"
32 #include "kxmlguifactory.h"
33 #include "kcmdlineargs.h"
34 #include "ktoggleaction.h"
35 #include "ksessionmanager.h"
36 #include "kstandardaction.h"
38 #include <config.h>
40 #include <QCloseEvent>
41 #include <QDesktopWidget>
42 #include <QDockWidget>
43 #include <QtXml/QDomDocument>
44 #include <QtGui/QLayout>
45 #include <QtCore/QObject>
46 #include <QtGui/QSessionManager>
47 #include <QtGui/QStyle>
48 #include <QtCore/QTimer>
49 #include <QtGui/QWidget>
50 #include <QtCore/QList>
51 #include <kaction.h>
52 #include <kapplication.h>
53 #include <kauthorized.h>
54 #include <kconfig.h>
55 #include <kdebug.h>
56 #include <kedittoolbar.h>
57 #include <khelpmenu.h>
58 #include <klocale.h>
59 #include <kmenubar.h>
60 #include <kstandarddirs.h>
61 #include <kstatusbar.h>
62 #include <ktoolbar.h>
63 #include <kwindowsystem.h>
64 #include <kconfiggroup.h>
66 #if defined Q_WS_X11
67 #include <qx11info_x11.h>
68 #include <netwm.h>
69 #include <kstartupinfo.h>
70 #endif
72 #include <stdlib.h>
73 #include <ctype.h>
74 #include <assert.h>
76 class KXmlGuiWindowPrivate : public KMainWindowPrivate {
77 public:
78 void _k_slotFactoryMakingChanges(bool b)
80 // While the GUI factory is adding/removing clients,
81 // don't let KMainWindow think those are changes made by the user
82 // #105525
83 letDirtySettings = !b;
86 bool showHelpMenu:1;
87 QSize defaultSize;
89 KDEPrivate::ToolBarHandler *toolBarHandler;
90 KToggleAction *showStatusBarAction;
91 QPointer<KEditToolBar> toolBarEditor;
92 KXMLGUIFactory *factory;
95 KXmlGuiWindow::KXmlGuiWindow( QWidget* parent, Qt::WFlags f )
96 : KMainWindow(*new KXmlGuiWindowPrivate, parent, f), KXMLGUIBuilder( this )
98 K_D(KXmlGuiWindow);
99 d->showHelpMenu = true;
100 d->toolBarHandler = 0;
101 d->showStatusBarAction = 0;
102 d->factory = 0;
103 new KMainWindowInterface(this);
107 QAction *KXmlGuiWindow::toolBarMenuAction()
109 K_D(KXmlGuiWindow);
110 if ( !d->toolBarHandler )
111 return 0;
113 return d->toolBarHandler->toolBarMenuAction();
117 void KXmlGuiWindow::setupToolbarMenuActions()
119 K_D(KXmlGuiWindow);
120 if ( d->toolBarHandler )
121 d->toolBarHandler->setupActions();
125 KXmlGuiWindow::~KXmlGuiWindow()
129 bool KXmlGuiWindow::event( QEvent* ev )
131 bool ret = KMainWindow::event(ev);
132 if (ev->type()==QEvent::Polish) {
133 QDBusConnection::sessionBus().registerObject(dbusName() + "/actions", actionCollection(),
134 QDBusConnection::ExportScriptableSlots |
135 QDBusConnection::ExportScriptableProperties |
136 QDBusConnection::ExportNonScriptableSlots |
137 QDBusConnection::ExportNonScriptableProperties |
138 QDBusConnection::ExportChildObjects);
140 return ret;
143 void KXmlGuiWindow::setHelpMenuEnabled(bool showHelpMenu)
145 K_D(KXmlGuiWindow);
146 d->showHelpMenu = showHelpMenu;
149 bool KXmlGuiWindow::isHelpMenuEnabled() const
151 K_D(const KXmlGuiWindow);
152 return d->showHelpMenu;
155 KXMLGUIFactory *KXmlGuiWindow::guiFactory()
157 K_D(KXmlGuiWindow);
158 if (!d->factory) {
159 d->factory = new KXMLGUIFactory( this, this );
160 connect(d->factory, SIGNAL(makingChanges(bool)),
161 this, SLOT(_k_slotFactoryMakingChanges(bool)));
163 return d->factory;
166 void KXmlGuiWindow::configureToolbars()
168 K_D(KXmlGuiWindow);
169 KConfigGroup cg(KGlobal::config(), QString());
170 saveMainWindowSettings(cg);
171 if (!d->toolBarEditor) {
172 d->toolBarEditor = new KEditToolBar(guiFactory(), this);
173 d->toolBarEditor->setAttribute(Qt::WA_DeleteOnClose);
174 connect(d->toolBarEditor, SIGNAL(newToolBarConfig()), SLOT(saveNewToolbarConfig()));
176 d->toolBarEditor->show();
179 void KXmlGuiWindow::saveNewToolbarConfig()
181 // createGUI(xmlFile()); // this loses any plugged-in guiclients, so we use remove+add instead.
183 guiFactory()->removeClient(this);
184 guiFactory()->addClient(this);
186 KConfigGroup cg(KGlobal::config(), QString());
187 applyMainWindowSettings(cg);
190 void KXmlGuiWindow::setupGUI( StandardWindowOptions options, const QString & xmlfile ) {
191 setupGUI(QSize(), options, xmlfile);
194 void KXmlGuiWindow::setupGUI( const QSize & defaultSize, StandardWindowOptions options, const QString & xmlfile ) {
195 K_D(KXmlGuiWindow);
197 if( options & Keys ){
198 KStandardAction::keyBindings(guiFactory(),
199 SLOT(configureShortcuts()), actionCollection());
202 if( (options & StatusBar) && statusBar() ){
203 createStandardStatusBarAction();
206 if( options & ToolBar ){
207 setStandardToolBarMenuEnabled( true );
208 KStandardAction::configureToolbars(this,
209 SLOT(configureToolbars() ), actionCollection());
212 d->defaultSize = defaultSize;
214 if( options & Create ){
215 createGUI(xmlfile);
218 if (initialGeometrySet()) {
219 // Do nothing...
221 else if (d->defaultSize.isValid()) {
222 resize(d->defaultSize);
224 else if (isHidden()) {
225 adjustSize();
228 if( options & Save ){
229 const KConfigGroup cg(autoSaveConfigGroup());
230 if (cg.isValid()) {
231 setAutoSaveSettings(cg);
232 } else {
233 setAutoSaveSettings();
237 void KXmlGuiWindow::createGUI( const QString &xmlfile )
239 K_D(KXmlGuiWindow);
240 // disabling the updates prevents unnecessary redraws
241 //setUpdatesEnabled( false );
243 // just in case we are rebuilding, let's remove our old client
244 guiFactory()->removeClient( this );
246 // make sure to have an empty GUI
247 QMenuBar* mb = menuBar();
248 if ( mb )
249 mb->clear();
251 qDeleteAll( toolBars() ); // delete all toolbars
253 // don't build a help menu unless the user ask for it
254 if (d->showHelpMenu) {
255 delete d->helpMenu;
256 // we always want a help menu
257 d->helpMenu = new KHelpMenu(this, componentData().aboutData(), true, actionCollection());
260 const QString windowXmlFile = xmlfile.isNull() ? componentData().componentName() + "ui.rc" : xmlfile;
262 // Help beginners who call setXMLFile and then setupGUI...
263 if (!xmlFile().isEmpty() && xmlFile() != windowXmlFile) {
264 kWarning() << "You called setXMLFile(" << xmlFile() << ") and then createGUI or setupGUI,"
265 << "which also calls setXMLFile and will overwrite the file you have previously set.\n"
266 << "You should call createGUI("<<xmlFile()<<") or setupGUI(<options>,"<<xmlFile()<<") instead.";
269 // we always want to load in our global standards file
270 setXMLFile(KStandardDirs::locate("config", "ui/ui_standards.rc", componentData()));
272 // now, merge in our local xml file.
273 setXMLFile(windowXmlFile, true);
275 // make sure we don't have any state saved already
276 setXMLGUIBuildDocument( QDomDocument() );
278 // do the actual GUI building
279 guiFactory()->addClient( this );
281 // setUpdatesEnabled( true );
284 void KXmlGuiWindow::slotStateChanged(const QString &newstate)
286 stateChanged(newstate, KXMLGUIClient::StateNoReverse);
289 void KXmlGuiWindow::slotStateChanged(const QString &newstate,
290 bool reverse)
292 stateChanged(newstate,
293 reverse ? KXMLGUIClient::StateReverse : KXMLGUIClient::StateNoReverse);
296 void KXmlGuiWindow::setStandardToolBarMenuEnabled( bool enable )
298 K_D(KXmlGuiWindow);
299 if ( enable ) {
300 if ( d->toolBarHandler )
301 return;
303 d->toolBarHandler = new KDEPrivate::ToolBarHandler( this );
305 if ( factory() )
306 factory()->addClient( d->toolBarHandler );
307 } else {
308 if ( !d->toolBarHandler )
309 return;
311 if ( factory() )
312 factory()->removeClient( d->toolBarHandler );
314 delete d->toolBarHandler;
315 d->toolBarHandler = 0;
319 bool KXmlGuiWindow::isStandardToolBarMenuEnabled() const
321 K_D(const KXmlGuiWindow);
322 return ( d->toolBarHandler );
325 void KXmlGuiWindow::createStandardStatusBarAction(){
326 K_D(KXmlGuiWindow);
327 if(!d->showStatusBarAction){
328 d->showStatusBarAction = KStandardAction::showStatusbar(this, SLOT(setSettingsDirty()), actionCollection());
329 KStatusBar *sb = statusBar(); // Creates statusbar if it doesn't exist already.
330 connect(d->showStatusBarAction, SIGNAL(toggled(bool)), sb, SLOT(setVisible(bool)));
331 d->showStatusBarAction->setChecked(sb->isHidden());
332 } else {
333 // If the language has changed, we'll need to grab the new text and whatsThis
334 KAction *tmpStatusBar = KStandardAction::showStatusbar(NULL, NULL, NULL);
335 d->showStatusBarAction->setText(tmpStatusBar->text());
336 d->showStatusBarAction->setWhatsThis(tmpStatusBar->whatsThis());
337 delete tmpStatusBar;
341 void KXmlGuiWindow::finalizeGUI( bool /*force*/ )
343 // FIXME: this really needs to be removed with a code more like the one we had on KDE3.
344 // what we need to do here is to position correctly toolbars so they don't overlap.
345 // Also, take in count plugins could provide their own toolbars and those also need to
346 // be restored.
347 if (autoSaveSettings() && autoSaveConfigGroup().isValid()) {
348 applyMainWindowSettings(autoSaveConfigGroup());
352 void KXmlGuiWindow::applyMainWindowSettings(const KConfigGroup &config, bool force)
354 K_D(KXmlGuiWindow);
355 KMainWindow::applyMainWindowSettings(config, force);
356 KStatusBar *sb = qFindChild<KStatusBar *>(this);
357 if (sb && d->showStatusBarAction)
358 d->showStatusBarAction->setChecked(!sb->isHidden());
361 // KDE5 TODO: change it to "using KXMLGUIBuilder::finalizeGUI;" in the header
362 // and remove the reimplementation
363 void KXmlGuiWindow::finalizeGUI( KXMLGUIClient *client )
364 { KXMLGUIBuilder::finalizeGUI( client ); }
366 #include "kxmlguiwindow.moc"