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"
24 #include "konqcloseditem.h"
25 #include "konqclosedwindowsmanageradaptor.h"
26 #include "konqclosedwindowsmanager_interface.h"
27 #include <kio/fileundomanager.h>
28 #include <QDirIterator>
30 #include <QtDBus/QtDBus>
33 #include <kstandarddirs.h>
35 #include <unistd.h> // getpid
37 Q_DECLARE_METATYPE(QList
<QVariant
>)
39 class KonqClosedWindowsManagerPrivate
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
);
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()
84 return m_konqClosedItemsConfig
;
87 KonqClosedWindowsManager
*KonqClosedWindowsManager::self()
89 return &myKonqClosedWindowsManagerPrivate
->instance
;
92 void KonqClosedWindowsManager::addClosedWindowItem(KonqUndoManager
93 *real_sender
, KonqClosedWindowItem
*closedWindowItem
, bool propagate
)
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();
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
);
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.
129 // Once saved, tell to other konqi processes
130 emitNotifyClosedWindowItem(closedWindowItem
);
134 void KonqClosedWindowsManager::removeClosedWindowItem(KonqUndoManager
135 *real_sender
, const KonqClosedWindowItem
*closedWindowItem
, bool propagate
)
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
);
149 emitNotifyRemove(closedWindowItem
);
152 const QList
<KonqClosedWindowItem
*>& KonqClosedWindowsManager::closedWindowItemList()
155 return m_closedWindowItemList
;
158 void KonqClosedWindowsManager::readSettings()
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() );
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
) )
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
,
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
,
235 void KonqClosedWindowsManager::slotNotifyRemove(
236 const QString
& configFileName
, const QString
& configGroup
,
237 const QDBusMessage
& msg
)
239 if ( isSenderOfSignal( msg
) )
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
)
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
)
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
)
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
);
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()
318 // Create / overwrite the saved closed windows list
319 QString filename
= "closeditems_saved";
320 QString file
= KStandardDirs::locateLocal("appdata", filename
);
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());
345 void KonqClosedWindowsManager ::readConfig()
347 if(m_konqClosedItemsConfig
)
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
))
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" +
366 // The number of closed items was not correctly set, fix it and save the
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());
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(),
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;