Fix crash if key bindings specified in profile cannot be found. Improve
[personal-kdebase.git] / apps / konqueror / src / konqclosedwindowsmanager.cpp
blobe8873b30b5f39300f313dae0f6fb6c5c33c3653b
1 /* This file is part of the KDE project
2 Copyright 2007 David Faure <faure@kde.org>
3 Copyright 2007 Eduardo Robles Elvira <edulix@gmail.com>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 #include "konqclosedwindowsmanager.h"
22 #include "konqsettingsxt.h"
23 #include "konqmisc.h"
24 #include "konqcloseditem.h"
25 #include "konqclosedwindowsmanageradaptor.h"
26 #include "konqclosedwindowsmanager_interface.h"
27 #include <kio/fileundomanager.h>
28 #include <QDirIterator>
29 #include <QMetaType>
30 #include <QtDBus/QtDBus>
31 #include <kglobal.h>
32 #include <klocale.h>
33 #include <kstandarddirs.h>
34 #include <kconfig.h>
35 #include <unistd.h> // getpid
37 Q_DECLARE_METATYPE(QList<QVariant>)
39 class KonqClosedWindowsManagerPrivate
41 public:
42 KonqClosedWindowsManager instance;
43 int m_maxNumClosedItems;
46 K_GLOBAL_STATIC(KonqClosedWindowsManagerPrivate, myKonqClosedWindowsManagerPrivate)
48 KonqClosedWindowsManager::KonqClosedWindowsManager()
50 //qDBusRegisterMetaType<QList<QVariant> >();
52 new KonqClosedWindowsManagerAdaptor ( this );
54 const QString dbusPath = "/KonqUndoManager";
55 const QString dbusInterface = "org.kde.Konqueror.UndoManager";
57 QDBusConnection dbus = QDBusConnection::sessionBus();
58 dbus.registerObject( dbusPath, this );
59 dbus.connect(QString(), dbusPath, dbusInterface, "notifyClosedWindowItem", this, SLOT(slotNotifyClosedWindowItem(QString,int,QString,QString,QDBusMessage)));
60 dbus.connect(QString(), dbusPath, dbusInterface, "notifyRemove", this, SLOT(slotNotifyRemove(QString,QString,QDBusMessage)));
62 QString filename = "closeditems/" + KonqMisc::encodeFilename(dbus.baseService());
63 QString file = KStandardDirs::locateLocal("tmp", filename);
64 QFile::remove(file);
66 KConfigGroup configGroup(KGlobal::config(), "Undo");
67 m_numUndoClosedItems = configGroup.readEntry("Number of Closed Windows", 0);
69 m_konqClosedItemsConfig = 0L;
70 m_blockClosedItems = false;
73 KonqClosedWindowsManager::~KonqClosedWindowsManager()
75 // Do some file cleaning
76 removeClosedItemsConfigFiles();
78 delete m_konqClosedItemsConfig;
81 KConfig* KonqClosedWindowsManager::config()
83 readConfig();
84 return m_konqClosedItemsConfig;
87 KonqClosedWindowsManager *KonqClosedWindowsManager::self()
89 return &myKonqClosedWindowsManagerPrivate->instance;
92 void KonqClosedWindowsManager::addClosedWindowItem(KonqUndoManager
93 *real_sender, KonqClosedWindowItem *closedWindowItem, bool propagate)
95 readConfig();
96 // If we are off the limit, remove the last closed window item
97 if(m_closedWindowItemList.size() >=
98 KonqSettings::maxNumClosedItems())
100 KonqClosedWindowItem* last = m_closedWindowItemList.last();
102 emit removeWindowInOtherInstances(0L, last);
103 emitNotifyRemove(last);
105 m_closedWindowItemList.removeLast();
106 delete last;
109 if(!m_blockClosedItems)
111 m_numUndoClosedItems++;
112 emit addWindowInOtherInstances(real_sender, closedWindowItem);
115 // The prepend goes after emit addWindowInOtherInstances() because otherwise
116 // the first time addWindowInOtherInstances() is emitted, KonqUndoManager
117 // will catch it and it will call to its private populate() function which
118 // will add to the undo list closedWindowItem, and then it will add it again
119 // but we want it to be added only once.
120 m_closedWindowItemList.prepend(closedWindowItem);
122 if(propagate)
124 // if it needs to be propagated means that it's a local window and thus
125 // we need to call to saveConfig() to keep updated the kconfig file, so
126 // that new konqueror instances can read it correctly updated.
127 saveConfig();
129 // Once saved, tell to other konqi processes
130 emitNotifyClosedWindowItem(closedWindowItem);
134 void KonqClosedWindowsManager::removeClosedWindowItem(KonqUndoManager
135 *real_sender, const KonqClosedWindowItem *closedWindowItem, bool propagate)
137 readConfig();
138 QList<KonqClosedWindowItem *>::iterator it = qFind(m_closedWindowItemList.begin(),
139 m_closedWindowItemList.end(), closedWindowItem);
141 // If the item was found, remove it from the list
142 if(it != m_closedWindowItemList.end()) {
143 m_closedWindowItemList.erase(it);
144 m_numUndoClosedItems--;
146 emit removeWindowInOtherInstances(real_sender, closedWindowItem);
148 if(propagate)
149 emitNotifyRemove(closedWindowItem);
152 const QList<KonqClosedWindowItem *>& KonqClosedWindowsManager::closedWindowItemList()
154 readConfig();
155 return m_closedWindowItemList;
158 void KonqClosedWindowsManager::readSettings()
160 readConfig();
165 static QString dbusService()
167 return QDBusConnection::sessionBus().baseService();
171 * Returns whether the DBUS call we are handling was a call from us self
173 bool isSenderOfSignal( const QDBusMessage& msg )
175 return dbusService() == msg.service();
178 bool isSenderOfSignal( const QString& service )
180 return dbusService() == service;
183 void KonqClosedWindowsManager::emitNotifyClosedWindowItem(
184 const KonqClosedWindowItem *closedWindowItem)
186 emit notifyClosedWindowItem( closedWindowItem->title(),
187 closedWindowItem->numTabs(),
188 closedWindowItem->configGroup().config()->name(),
189 closedWindowItem->configGroup().name() );
192 void KonqClosedWindowsManager::emitNotifyRemove(
193 const KonqClosedWindowItem *closedWindowItem)
195 const KonqClosedRemoteWindowItem* closedRemoteWindowItem =
196 dynamic_cast<const KonqClosedRemoteWindowItem *>(closedWindowItem);
198 // Here we do this because there's no need to call to configGroup() if it's
199 // a remote window item, and it would be error prone to be so, because
200 // it could give us a null pointer and konqueror would crash
201 if(closedRemoteWindowItem)
202 emit notifyRemove( closedRemoteWindowItem->remoteConfigFileName(),
203 closedRemoteWindowItem->remoteGroupName() );
204 else
205 emit notifyRemove( closedWindowItem->configGroup().config()->name(),
206 closedWindowItem->configGroup().name() );
209 void KonqClosedWindowsManager::slotNotifyClosedWindowItem(
210 const QString& title, const int& numTabs, const QString& configFileName,
211 const QString& configGroup, const QString& service )
213 if ( isSenderOfSignal( service ) )
214 return;
216 // Create a new ClosedWindowItem and add it to the list
217 KonqClosedWindowItem* closedWindowItem = new KonqClosedRemoteWindowItem(
218 title, configGroup, configFileName,
219 KIO::FileUndoManager::self()->newCommandSerialNumber(), numTabs,
220 service);
222 // Add it to all the windows but don't propagate over dbus,
223 // as it already comes from dbus)
224 addClosedWindowItem(0L, closedWindowItem, false);
227 void KonqClosedWindowsManager::slotNotifyClosedWindowItem(
228 const QString& title, const int& numTabs, const QString& configFileName,
229 const QString& configGroup, const QDBusMessage& msg )
231 slotNotifyClosedWindowItem(title, numTabs, configFileName, configGroup,
232 msg.service() );
235 void KonqClosedWindowsManager::slotNotifyRemove(
236 const QString& configFileName, const QString& configGroup,
237 const QDBusMessage& msg )
239 if ( isSenderOfSignal( msg ) )
240 return;
242 // Find the window item. It can be either remote or local
243 KonqClosedWindowItem* closedWindowItem =
244 findClosedRemoteWindowItem(configFileName, configGroup);
245 if(!closedWindowItem)
247 closedWindowItem = findClosedLocalWindowItem(configFileName, configGroup);
248 if(!closedWindowItem)
249 return;
252 // Remove it in all the windows but don't propagate over dbus,
253 // as it already comes from dbus)
254 removeClosedWindowItem(0L, closedWindowItem, false);
257 KonqClosedRemoteWindowItem* KonqClosedWindowsManager::findClosedRemoteWindowItem(
258 const QString& configFileName,
259 const QString& configGroup)
261 readConfig();
263 KonqClosedRemoteWindowItem* closedRemoteWindowItem = 0L;
264 for (QList<KonqClosedWindowItem *>::const_iterator it = m_closedWindowItemList.constBegin();
265 it != m_closedWindowItemList.constEnd(); ++it)
267 closedRemoteWindowItem = dynamic_cast<KonqClosedRemoteWindowItem *>(*it);
269 if(closedRemoteWindowItem &&
270 closedRemoteWindowItem->equalsTo(configFileName, configGroup))
271 return closedRemoteWindowItem;
274 return closedRemoteWindowItem;
277 KonqClosedWindowItem* KonqClosedWindowsManager::findClosedLocalWindowItem(
278 const QString& configFileName,
279 const QString& configGroup)
281 readConfig();
282 KonqClosedWindowItem* closedWindowItem = 0L;
283 for (QList<KonqClosedWindowItem *>::const_iterator it = m_closedWindowItemList.constBegin();
284 it != m_closedWindowItemList.constEnd(); ++it)
286 closedWindowItem = *it;
287 KonqClosedRemoteWindowItem* closedRemoteWindowItem =
288 dynamic_cast<KonqClosedRemoteWindowItem *>(closedWindowItem);
290 if(!closedRemoteWindowItem && closedWindowItem &&
291 closedWindowItem->configGroup().config()->name() == configFileName &&
292 closedWindowItem->configGroup().name() == configGroup)
293 return closedWindowItem;
296 return closedWindowItem;
299 void KonqClosedWindowsManager::removeClosedItemsConfigFiles()
301 QString dir = KStandardDirs::locateLocal("tmp", "closeditems/");
302 QDBusConnectionInterface *idbus = QDBusConnection::sessionBus().interface();
303 QDirIterator it(dir, QDir::Writable|QDir::Files);
304 while (it.hasNext())
306 // Only remove the files for those konqueror instances not running anymore
307 QString filename = it.next();
308 if(!idbus->isServiceRegistered(KonqMisc::decodeFilename(it.fileName())))
309 QFile::remove(filename);
314 void KonqClosedWindowsManager::saveConfig()
316 readConfig();
318 // Create / overwrite the saved closed windows list
319 QString filename = "closeditems_saved";
320 QString file = KStandardDirs::locateLocal("appdata", filename);
321 QFile::remove(file);
323 KConfig *config = new KConfig(filename, KConfig::SimpleConfig, "appdata");
325 // Populate the config file
326 KonqClosedWindowItem* closedWindowItem = 0L;
327 uint counter = m_closedWindowItemList.size()-1;
328 for (QList<KonqClosedWindowItem *>::const_iterator it = m_closedWindowItemList.constBegin();
329 it != m_closedWindowItemList.constEnd(); ++it, --counter)
331 closedWindowItem = *it;
332 KConfigGroup configGroup(config, "Closed_Window" + QString::number(counter));
333 configGroup.writeEntry("title", closedWindowItem->title());
334 configGroup.writeEntry("numTabs", closedWindowItem->numTabs());
335 closedWindowItem->configGroup().copyTo(&configGroup);
338 KConfigGroup configGroup(KGlobal::config(), "Undo");
339 configGroup.writeEntry("Number of Closed Windows", m_closedWindowItemList.size());
340 configGroup.sync();
342 delete config;
345 void KonqClosedWindowsManager ::readConfig()
347 if(m_konqClosedItemsConfig)
348 return;
350 QString filename = "closeditems_saved";
351 QString file = KStandardDirs::locateLocal("appdata", filename);
353 m_konqClosedItemsConfig = new KConfig(file, KConfig::SimpleConfig);
355 // If the config file doesn't exists, there's nothing to read
356 if(!QFile::exists(file))
357 return;
359 m_blockClosedItems = true;
360 for(int i = 0; i < m_numUndoClosedItems; i++)
362 // For each item, create a new ClosedWindowItem
363 KConfigGroup configGroup(m_konqClosedItemsConfig, "Closed_Window" +
364 QString::number(i));
366 // The number of closed items was not correctly set, fix it and save the
367 // correct number.
368 if(!configGroup.exists())
370 m_numUndoClosedItems = i;
371 KConfigGroup configGroup(KGlobal::config(), "Undo");
372 configGroup.writeEntry("Number of Closed Windows",
373 m_closedWindowItemList.size());
374 configGroup.sync();
375 break;
378 QString title = configGroup.readEntry("title", i18n("no name"));
379 int numTabs = configGroup.readEntry("numTabs", 0);
381 KonqClosedWindowItem* closedWindowItem = new KonqClosedWindowItem(
382 title, KIO::FileUndoManager::self()->newCommandSerialNumber(),
383 numTabs);
384 configGroup.copyTo(&closedWindowItem->configGroup());
385 configGroup.writeEntry("foo", 0);
387 // Add the item only to this window
388 addClosedWindowItem(0L, closedWindowItem, false);
391 m_blockClosedItems = false;
394 bool KonqClosedWindowsManager::undoAvailable() const
396 return m_numUndoClosedItems > 0;