rendered paste bodyIndex: src/konqcloseditem.cpp===================================================================--- src/konqcloseditem.cpp (revisión: 794475)+++ src/konqcloseditem.cpp (copia de trabajo)@@ -34,27 +34,21 @@ #include <kstandarddirs.h> #include <unistd.h> -class KConfigNew+KonqClosedItemsConfig::KonqClosedItemsConfig() {-public:- KConfigNew()- {- filename = "closeditems/closeditems_" + QString::number(getpid());- QString file = KStandardDirs::locateLocal("appdata", filename);- if(QFile::exists(file))- QFile::remove(file);- - config = new KConfig(filename, KConfig::SimpleConfig, "appdata");- kDebug();- }- ~KConfigNew() {- QFile::remove(KStandardDirs::locateLocal("appdata", filename));- delete config;- }- KConfig *config;- QString filename;-};+ filename = "closeditems/closeditems_" + QString::number(getpid());+ QString file = KStandardDirs::locateLocal("appdata", filename);+ if(QFile::exists(file))+ QFile::remove(file);+ + config = new KConfig(filename, KConfig::SimpleConfig, "appdata");+ kDebug();+} +KonqClosedItemsConfig::~KonqClosedItemsConfig() {+ // config is "leaked"+}+ class KonqIcon { public: KonqIcon()@@ -66,11 +60,13 @@ QImage image; }; -K_GLOBAL_STATIC(KConfigNew, s_config)++// deleted manually in KonqUndoManagerCommunicator::~KonqUndoManagerCommunicator()+K_GLOBAL_STATIC(KonqClosedItemsConfig, s_closedItemsConfig) K_GLOBAL_STATIC(KonqIcon, s_lightIconImage) KonqClosedItem::KonqClosedItem(const QString& title, const QString& group, quint64 serialNumber)- : m_title(title), m_configGroup(s_config->config, group), m_serialNumber(serialNumber)+ : m_title(title), m_configGroup(s_closedItemsConfig->config, group), m_serialNumber(serialNumber) { } @@ -92,7 +88,7 @@ kDebug(1202) << "deleted group" << m_configGroup.name(); } -QPixmap KonqClosedTabItem::icon() {+QPixmap KonqClosedTabItem::icon() const { return KonqPixmapProvider::self()->pixmapFor(m_url); } @@ -104,11 +100,13 @@ KonqClosedWindowItem::~KonqClosedWindowItem() {- m_configGroup.deleteGroup();- kDebug(1202) << "deleted group" << m_configGroup.name();+// Do this manually when needed:+// m_configGroup.deleteGroup();+// kDebug(1202) << "deleted group" << m_configGroup.name(); } -QPixmap KonqClosedWindowItem::icon() {+QPixmap KonqClosedWindowItem::icon() const+{ QImage overlayImg = s_lightIconImage->image.copy(); int oldWidth = overlayImg.width(); QString countStr = QString::number( m_numTabs );@@ -134,3 +132,57 @@ return QPixmap::fromImage(overlayImg); }++int KonqClosedWindowItem::numTabs() const+{+ return m_numTabs;+}++KonqClosedRemoteWindowItem::KonqClosedRemoteWindowItem(const QString& title,+ const QString& groupName, const QString& configFileName, quint64 serialNumber,+ int numTabs, const QString& dbusService)+ : KonqClosedWindowItem(title, serialNumber, numTabs),+ m_remoteGroupName(groupName), m_remoteConfigFileName(configFileName),+ m_dbusService(dbusService), m_remoteConfigGroup(0L), m_remoteConfig(0L)+{+ kDebug();+ readConfig();+}++KonqClosedRemoteWindowItem::~KonqClosedRemoteWindowItem()+{+ if(m_remoteConfigGroup)+ delete m_remoteConfigGroup;+ + if(m_remoteConfig)+ delete m_remoteConfig;+}++void KonqClosedRemoteWindowItem::readConfig()+{+ // only do this once+ if(m_remoteConfig || m_remoteConfigGroup)+ return;++ m_remoteConfig = new KConfig(+ KStandardDirs::locateLocal("appdata", m_remoteConfigFileName),+ KConfig::SimpleConfig, "appdata");+ m_remoteConfigGroup = new KConfigGroup(m_remoteConfig, m_remoteGroupName);+}++const KConfigGroup& KonqClosedRemoteWindowItem::configGroup() const+{+ return *m_remoteConfigGroup;+}++KConfigGroup& KonqClosedRemoteWindowItem::configGroup()+{+ return *m_remoteConfigGroup;+}++bool KonqClosedRemoteWindowItem::equalsTo(const QString& groupName,+ const QString& configFileName) const+{ + return (m_remoteGroupName == groupName &&+ m_remoteConfigFileName == configFileName);+}Index: src/konqviewmanager.cpp===================================================================--- src/konqviewmanager.cpp (revisión: 794475)+++ src/konqviewmanager.cpp (copia de trabajo)@@ -358,9 +358,10 @@ } mainWindow->viewManager()->loadRootItem( closedWindowItem.configGroup(), mainWindow->viewManager()->tabContainer(), KUrl(), true, KUrl() );+ // read window settings+ mainWindow->applyMainWindowSettings( KConfigGroup( & closedWindowItem.configGroup(), "Main Window Settings" ), true ); mainWindow->activateChild(); mainWindow->show();- kDebug(1202) << "done"; } Index: src/org.kde.Konqueror.UndoManager.xml===================================================================--- src/org.kde.Konqueror.UndoManager.xml (revisión: 0)+++ src/org.kde.Konqueror.UndoManager.xml (revisión: 0)@@ -0,0 +1,23 @@+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">+<node>+ <interface name="org.kde.Konqueror.UndoManager">+ <signal name="notifyClosedWindowItem">+ <arg name="title" type="s" direction="out"/>+ <arg name="numTabs" type="i" direction="out"/>+ <arg name="configFileName" type="s" direction="out"/>+ <arg name="configGroup" type="s" direction="out"/>+ </signal>+ <signal name="notifyRemove">+ <arg name="configFileName" type="s" direction="out"/>+ <arg name="configGroup" type="s" direction="out"/>+ </signal>+ <signal name="requestLocalClosedWindowItems">+ </signal>+ <method name="localClosedWindowItems">+ <arg name="windowItems" type="av" direction="in"/>+ <arg name="service" type="s" direction="in"/>+ </method>+ <method name="pong">+ </method>+ </interface>+</node>Index: src/konqmainwindow.cpp===================================================================--- src/konqmainwindow.cpp (revisión: 794475)+++ src/konqmainwindow.cpp (copia de trabajo)@@ -2895,7 +2895,7 @@ QMenu* popup = m_paClosedItems->menu(); // Clear the menu and fill it with a maximum of s_closedTabsListLength number of urls popup->clear();- QAction* clearAction = popup->addAction( i18n("Empty Closed Tabs History") );+ QAction* clearAction = popup->addAction( i18n("Empty Closed Items History") ); connect(clearAction, SIGNAL(triggered()), m_undoManager, SLOT(clearClosedItemsList())); popup->insertSeparator((QAction*)0); @@ -4994,10 +4994,7 @@ // save size to have something to restore if the profile does not contain size saveWindowSize();- // Save the window tabs so that we can restore it later, but only if there- // are other windows opened- if(s_konqMainWindowInstancesCount > 1)- addClosedWindowToUndoList();+ addClosedWindowToUndoList(); hide(); qApp->flush();@@ -5040,7 +5037,11 @@ closedWindowItem->configGroup().writeEntry( "Height", height() ); closedWindowItem->configGroup().writeEntry( "FullScreen", fullScreenMode() ); tabContainer->saveConfig( closedWindowItem->configGroup(), prefix, flags, 0L, 0, 1);-+ // Save window settings+ KConfigGroup cfg( &closedWindowItem->configGroup(), "Main Window Settings" );+ saveMainWindowSettings( cfg );+ closedWindowItem->configGroup().sync();+ // 3. Finally add the KonqClosedWindowItem to the undo list m_paClosedItems->setEnabled(true); m_undoManager->addClosedWindowItem( closedWindowItem );Index: src/CMakeLists.txt===================================================================--- src/CMakeLists.txt (revisión: 794475)+++ src/CMakeLists.txt (copia de trabajo)@@ -69,6 +69,9 @@ qt4_add_dbus_interface(konqueror_KDEINIT_SRCS org.kde.Konqueror.Main.xml konqueror_interface) qt4_add_dbus_interface(konqueror_KDEINIT_SRCS ${KDE4_DBUS_INTERFACES_DIR}/org.kde.kded.xml kded_interface)+qt4_add_dbus_adaptor(konqueror_KDEINIT_SRCS org.kde.Konqueror.UndoManager.xml konqundomanager.h KonqUndoManagerCommunicator konqundomanageradaptor KonqUndoManagerCommunicatorAdaptor)+qt4_add_dbus_interface(konqueror_KDEINIT_SRCS org.kde.Konqueror.UndoManager.xml konqundomanager_interface)+kde4_add_kdeinit_executable(konqueror ${konqueror_KDEINIT_SRCS} konqmain.cpp) kde4_add_app_icon(konqueror_KDEINIT_SRCS "${KDE4_ICON_INSTALL_DIR}/oxygen/*/apps/konqueror.png") Index: src/konqundomanager.h===================================================================--- src/konqundomanager.h (revisión: 794475)+++ src/konqundomanager.h (copia de trabajo)@@ -21,12 +21,15 @@ #ifndef KONQUNDOMANAGER_H #define KONQUNDOMANAGER_H -#include "konqprivate_export.h"- #include <QObject>+#include <QString>+#include <QList> #include "konqcloseditem.h"+#include "konqundomanager_interface.h" class QAction; class KonqUndoManagerCommunicatorPrivate;+class QDBusMessage;+ /** * Note that there is one KonqUndoManager per mainwindow. * It integrates KonqFileUndoManager (undoing file operations)@@ -54,7 +57,7 @@ public Q_SLOTS: void undo();- void clearClosedItemsList();+ void clearClosedItemsList(bool onlyInthisWindow = false); void undoLastClosedItem(); /** * Opens in a new tab/window the item the user selected from the closed tabs @@ -102,31 +105,150 @@ /** * Provides a shared singleton for all Konq window instances. * This class is a singleton, use self() to access its only instance.+ * + * - it synchronizes the closed window list with other+ * Konqueror instances via DBUS.+ * + * - When a konqueror instance is closed, the closed window list is written+ * to disk so that the undo closed windows list can be retrieved even when+ * no other konqueror instance is running. */ class KONQ_TESTS_EXPORT KonqUndoManagerCommunicator : public QObject { Q_OBJECT public: friend class KonqUndoManagerCommunicatorPrivate;+ static KonqUndoManagerCommunicator *self();+ const QList<KonqClosedWindowItem *>& closedWindowItemList();+ void addClosedWindowItem(KonqUndoManager *real_sender, KonqClosedWindowItem- *closedWindowItem);+ *closedWindowItem, bool propagate = true);+ void removeClosedWindowItem(KonqUndoManager *real_sender, const- KonqClosedWindowItem *closedWindowItem);+ + KonqClosedWindowItem *closedWindowItem, bool propagate = true);+ void applySettings();+ int maxNumClosedItems();+ void setMaxNumClosedItems(int max);+ public Q_SLOTS: void readSettings();+ + /**+ * Reads the list of closed window from the configuration file if it couldn't+ * be retrieved from running konqueror windows+ */+ void readConfig();+ Q_SIGNALS:+ /**+ * Notifies the addition the closed window list in all the konqueror windows of+ * this konqueror instance.+ */ void addWindowInOtherInstances(KonqUndoManager *real_sender, KonqClosedWindowItem *closedWindowItem);++ /**+ * Notifies the removal the closed window list in all the konqueror windows of+ * this konqueror instance.+ */ void removeWindowInOtherInstances(KonqUndoManager *real_sender, const- KonqClosedWindowItem *closedWindowItem);+ KonqClosedWindowItem *closedWindowItem);+ private: KonqUndoManagerCommunicator();+ virtual ~KonqUndoManagerCommunicator();+ + /**+ * Called by readSettings(), which is called by a singleShot timer inside+ * the constructor. Fills the closed window list with items from other + * konqueror instances, being the list retrieved via DBUS using the method+ * localClosedWindowItems();+ *+ * It also sets a timer so that if no other konqueror instance pings back in+ * X miliseconds, then the closed window list is read from disk.+ */+ void populate();+ + /**+ * Called by the destructor. Saves the closed windows list to disk inside a+ * config file+ */+ void saveConfig();++ KonqClosedRemoteWindowItem* findClosedRemoteWindowItem(const QString& configFileName,+ const QString& configGroup);+ + KonqClosedWindowItem* findClosedLocalWindowItem(const QString& configFileName,+ const QString& configGroup);+ + /**+ * This function removes all the files in appdata/closeditem/. Thus, it's + * used to clean the config files inside that directory.+ */+ void removeClosedItemsConfigFiles();+Q_SIGNALS: // DBUS signals+ /**+ * Every konqueror instance broadcasts new closed windows to other+ * konqueror instances.+ */+ void notifyClosedWindowItem( const QString& title, const int& numTabs, + const QString& configFileName, const QString& configGroup );+ + /**+ * Every konqueror instance broadcasts removed closed windows to other+ * konqueror instances.+ */+ void notifyRemove( const QString& configFileName, + const QString& configGroup );++ /**+ * Ask over D-BUS to all running konqueror instances to return their list+ * of local closed window items.+ */+ void requestLocalClosedWindowItems();+public Q_SLOTS: // DBUS methods+ /**+ * This is the answer call when a konqueror instance receives a call from+ * requestLocalClosedWindowItems().+ */+ void localClosedWindowItems(const QList<QVariant>& windowItems,+ const QString& dbusService);+ + /**+ * This signal is received from other konqueror instances in order to let+ * us know that there are other konqueror instances from which we can+ * retrieve the list of closed window items, so that we don't need to read+ * them from disk.+ */+ void pong();++private Q_SLOTS:// connected to DBUS signals+ void slotNotifyClosedWindowItem( const QString& title, const int& numTabs,+ const QString& configFileName, const QString& configGroup,+ const QString& service );+ + void slotNotifyClosedWindowItem( const QString& title, const int& numTabs,+ const QString& configFileName, const QString& configGroup,+ const QDBusMessage& msg );+ + void slotNotifyRemove( const QString& configFileName,+ const QString& configGroup, const QDBusMessage& msg );+ + void slotRequestLocalClosedWindowItems( const QDBusMessage& msg );++private:+ void emitNotifyClosedWindowItem(const KonqClosedWindowItem *closedWindowItem);+ + void emitNotifyRemove(const KonqClosedWindowItem *closedWindowItem);+ + void emitPong(const QString & service); }; #endif /* KONQUNDOMANAGER_H */Index: src/konqcloseditem.h===================================================================--- src/konqcloseditem.h (revisión: 794475)+++ src/konqcloseditem.h (copia de trabajo)@@ -23,17 +23,20 @@ #include "konqprivate_export.h" #include <kconfiggroup.h>+#include <QtDBus/QtDBus> #include <QString> #include <QImage> +class KConfig;+ class KONQ_TESTS_EXPORT KonqClosedItem : public QObject { public: virtual ~KonqClosedItem();- const KConfigGroup& configGroup() const { return m_configGroup; }- KConfigGroup& configGroup() { return m_configGroup; }+ virtual KConfigGroup& configGroup() { return m_configGroup; }+ virtual const KConfigGroup& configGroup() const { return m_configGroup; } quint64 serialNumber() const { return m_serialNumber; } QString title() const { return m_title; }- virtual QPixmap icon() = 0;+ virtual QPixmap icon() const = 0; protected: KonqClosedItem(const QString& title, const QString& group, quint64 serialNumber);@@ -50,7 +53,7 @@ public: KonqClosedTabItem(const QString& url, const QString& title, int index, quint64 serialNumber); virtual ~KonqClosedTabItem();- virtual QPixmap icon();+ virtual QPixmap icon() const; QString url() const { return m_url; } /// The position inside the tabbar that the tab had when it was closed int pos() const { return m_pos; }@@ -68,11 +71,44 @@ public: KonqClosedWindowItem(const QString& title, quint64 serialNumber, int numTabs); virtual ~KonqClosedWindowItem();- virtual QPixmap icon();+ virtual QPixmap icon() const;+ int numTabs() const; protected: int m_numTabs; }; +class KONQ_TESTS_EXPORT KonqClosedRemoteWindowItem : public KonqClosedWindowItem {+public:+ KonqClosedRemoteWindowItem(const QString& title, const QString& groupName, const QString& configFileName, quint64 serialNumber, int numTabs, const QString& dbusService);+ virtual ~KonqClosedRemoteWindowItem();+ virtual KConfigGroup& configGroup();+ virtual const KConfigGroup& configGroup() const;+ bool equalsTo(const QString& groupName, const QString& configFileName) const;+ QString dbusService() const { return m_dbusService; }+ const QString& remoteGroupName() const { return m_remoteGroupName; }+ const QString& remoteConfigFileName() const { return m_remoteConfigFileName; }+protected:+ /**+ * Actually reads the config file. Call to this function before calling to+ * configGroup().+ */+ void readConfig();+ QString m_remoteGroupName;+ QString m_remoteConfigFileName;+ QString m_dbusService;+ KConfigGroup* m_remoteConfigGroup;+ KConfig* m_remoteConfig;+};++class KonqClosedItemsConfig+{+public:+ KonqClosedItemsConfig();+ ~KonqClosedItemsConfig();+ KConfig *config;+ QString filename;+};+ #endif /* KONQCLOSEDITEM_H */ Index: src/konqundomanager.cpp===================================================================--- src/konqundomanager.cpp (revisión: 794475)+++ src/konqundomanager.cpp (copia de trabajo)@@ -19,22 +19,36 @@ */ #include "konqundomanager.h"+#include "konqundomanageradaptor.h"+#include "konqundomanager_interface.h" #include <QAction>+#include <QByteArray>+#include <QDBusArgument>+#include <QDirIterator>+#include <QFile>+#include <QMetaType>+#include <QtDBus/QtDBus> #include <QTimer>+#include <QVariant> #include <konq_fileundomanager.h> #include <kconfig.h> #include <kdebug.h> #include <klocale.h> #include <kglobal.h>+#include <kstandarddirs.h> -class KonqUndoManagerCommunicatorPrivate {+Q_DECLARE_METATYPE(QList<QVariant>);++class KonqUndoManagerCommunicatorPrivate+{ public: KonqUndoManagerCommunicator instance;- QList<KonqClosedWindowItem *> m_closedWindowItemList; int m_maxNumClosedItems;+ bool m_amIalone; }; -K_GLOBAL_STATIC(KonqUndoManagerCommunicatorPrivate, myKonqUndoManagerCommunicatorPrivate)+K_GLOBAL_STATIC(KonqUndoManagerCommunicatorPrivate, myKonqUndoManagerCommunicatorPrivate);+static QList<KonqClosedWindowItem *> *s_closedWindowItemList = new QList<KonqClosedWindowItem *>(); KonqUndoManager::KonqUndoManager(QObject* parent) : QObject(parent)@@ -51,8 +65,6 @@ connect(KonqUndoManagerCommunicator::self(), SIGNAL(removeWindowInOtherInstances(KonqUndoManager *, const KonqClosedWindowItem *)), this, SLOT( slotRemoveClosedWindowItem(KonqUndoManager *, const KonqClosedWindowItem *) ));-- populate(); } KonqUndoManager::~KonqUndoManager()@@ -70,12 +82,14 @@ SLOT( slotRemoveClosedWindowItem(KonqUndoManager *, const KonqClosedWindowItem *) )); KonqFileUndoManager::decRef();- clearClosedItemsList();+ + // Clear the closed item lists but only removed closed windows items+ // in this window+ clearClosedItemsList(true); } void KonqUndoManager::populate() {- kDebug(); const QList<KonqClosedWindowItem *> closedWindowItemList = KonqUndoManagerCommunicator::self()->closedWindowItemList(); @@ -115,27 +129,11 @@ void KonqUndoManager::undo() { if (!m_closedItemList.isEmpty()) {- const KonqClosedItem* closedItem = m_closedItemList.first();+ KonqClosedItem* closedItem = m_closedItemList.first(); // Check what to undo- kDebug() << "closedTabItem->serialNumber:" << closedItem->serialNumber()- << ", KonqFileUndoManager currentCommandSerialNumber(): " << KonqFileUndoManager::self()->currentCommandSerialNumber();- if (closedItem->serialNumber() > KonqFileUndoManager::self()->currentCommandSerialNumber()) {- m_closedItemList.removeFirst();- const KonqClosedTabItem* closedTabItem =- dynamic_cast<const KonqClosedTabItem *>(closedItem);- const KonqClosedWindowItem* closedWindowItem =- dynamic_cast<const KonqClosedWindowItem *>(closedItem);- if(closedTabItem)- emit openClosedTab(*closedTabItem);- else if(closedWindowItem) {- emit openClosedWindow(*closedWindowItem);- KonqUndoManagerCommunicator::self()->removeClosedWindowItem(this, closedWindowItem);- }- delete closedItem;- emit undoAvailable(this->undoAvailable());- emit closedItemsListChanged();+ undoClosedItem(0); } else { KonqFileUndoManager::self()->undo(); }@@ -161,7 +159,6 @@ delete lastTab; } - kDebug(); m_closedItemList.prepend(closedWindowItem); emit undoTextChanged(i18n("Und&o: Closed Window")); emit undoAvailable(true);@@ -201,15 +198,21 @@ const KonqClosedTabItem* closedTabItem = dynamic_cast<const KonqClosedTabItem *>(closedItem);- const KonqClosedWindowItem* closedWindowItem =- dynamic_cast<const KonqClosedWindowItem *>(closedItem);+ KonqClosedRemoteWindowItem* closedRemoteWindowItem =+ dynamic_cast<KonqClosedRemoteWindowItem *>(closedItem);+ KonqClosedWindowItem* closedWindowItem =+ dynamic_cast<KonqClosedWindowItem *>(closedItem); if(closedTabItem) emit openClosedTab(*closedTabItem);- else if(closedWindowItem) {+ else if(closedRemoteWindowItem) {+ emit openClosedWindow(*closedRemoteWindowItem);+ KonqUndoManagerCommunicator::self()->removeClosedWindowItem(this, closedRemoteWindowItem);+ } else if(closedWindowItem) { emit openClosedWindow(*closedWindowItem);- emit removeWindowInOtherInstances(this, closedWindowItem);+ KonqUndoManagerCommunicator::self()->removeClosedWindowItem(this, closedWindowItem);+ closedWindowItem->configGroup().deleteGroup(); }- delete closedTabItem;+ delete closedItem; emit undoAvailable(this->undoAvailable()); emit undoTextChanged(this->undoText()); emit closedItemsListChanged();@@ -258,7 +261,7 @@ emit undoAvailable(this->undoAvailable()); } -void KonqUndoManager::clearClosedItemsList()+void KonqUndoManager::clearClosedItemsList(bool onlyInthisWindow) { // we only DELETE tab items! So we can't do this anymore: // qDeleteAll(m_closedItemList);@@ -268,13 +271,16 @@ KonqClosedItem *closedItem = *it; const KonqClosedTabItem* closedTabItem = dynamic_cast<const KonqClosedTabItem *>(closedItem);-// const KonqClosedWindowItem* closedWindowItem =-// dynamic_cast<const KonqClosedWindowItem *>(closedItem);+ const KonqClosedWindowItem* closedWindowItem =+ dynamic_cast<const KonqClosedWindowItem *>(closedItem); m_closedItemList.erase(it); if(closedTabItem) delete closedTabItem;- // we never delete closed window items here+ else if (closedWindowItem && !onlyInthisWindow) {+ KonqUndoManagerCommunicator::self()->removeClosedWindowItem(this, closedWindowItem, false);+ delete closedWindowItem;+ } } emit closedItemsListChanged(); emit undoAvailable(this->undoAvailable());@@ -288,10 +294,25 @@ KonqUndoManagerCommunicator::KonqUndoManagerCommunicator() { QTimer::singleShot(0, this, SLOT(readSettings()));+ + qDBusRegisterMetaType<QList<QVariant> >();+ + (void) new KonqUndoManagerCommunicatorAdaptor ( this );+ const QString dbusPath = "/KonqUndoManager";+ const QString dbusInterface = "org.kde.Konqueror.UndoManager";+ + QDBusConnection dbus = QDBusConnection::sessionBus();+ dbus.registerObject( dbusPath, this );+ dbus.connect(QString(), dbusPath, dbusInterface, "notifyClosedWindowItem", this, SLOT(slotNotifyClosedWindowItem(QString,int,QString,QString,QDBusMessage)));+ dbus.connect(QString(), dbusPath, dbusInterface, "notifyRemove", this, SLOT(slotNotifyRemove(QString,QString,QDBusMessage)));+ dbus.connect(QString(), dbusPath, dbusInterface, "requestLocalClosedWindowItems", this, SLOT(slotRequestLocalClosedWindowItems(QDBusMessage))); } KonqUndoManagerCommunicator::~KonqUndoManagerCommunicator() {+ saveConfig();+ + delete s_closedWindowItemList; } KonqUndoManagerCommunicator *KonqUndoManagerCommunicator::self()@@ -300,42 +321,47 @@ } void KonqUndoManagerCommunicator::addClosedWindowItem(KonqUndoManager-*real_sender, KonqClosedWindowItem *closedWindowItem)+*real_sender, KonqClosedWindowItem *closedWindowItem, bool propagate) { // If we are off the limit, remove the last closed window item- if(myKonqUndoManagerCommunicatorPrivate->m_closedWindowItemList.size() >= + if(s_closedWindowItemList->size() >= maxNumClosedItems()) {- QList<KonqClosedWindowItem *> &closedWindowItemList =- myKonqUndoManagerCommunicatorPrivate->m_closedWindowItemList;- KonqClosedWindowItem* last = closedWindowItemList.last();+ KonqClosedWindowItem* last = s_closedWindowItemList->last();+ emit removeWindowInOtherInstances(0L, last);- closedWindowItemList.removeLast();+ emitNotifyClosedWindowItem(closedWindowItem);+ + s_closedWindowItemList->removeLast(); delete last; } - myKonqUndoManagerCommunicatorPrivate->m_closedWindowItemList.prepend(closedWindowItem);+ s_closedWindowItemList->prepend(closedWindowItem); emit addWindowInOtherInstances(real_sender, closedWindowItem);+ + if(propagate)+ emitNotifyClosedWindowItem(closedWindowItem); } void KonqUndoManagerCommunicator::removeClosedWindowItem(KonqUndoManager-*real_sender, const KonqClosedWindowItem *closedWindowItem)+*real_sender, const KonqClosedWindowItem *closedWindowItem, bool propagate) {- QList<KonqClosedWindowItem *> &closedWindowItemList =- myKonqUndoManagerCommunicatorPrivate->m_closedWindowItemList;- QList<KonqClosedWindowItem *>::iterator it = qFind(closedWindowItemList.begin(),- closedWindowItemList.end(), closedWindowItem);+ QList<KonqClosedWindowItem *>::iterator it = qFind(s_closedWindowItemList->begin(),+ s_closedWindowItemList->end(), closedWindowItem); // If the item was found, remove it from the list- if(it != closedWindowItemList.end()) {- closedWindowItemList.erase(it);+ if(it != s_closedWindowItemList->end()) {+ s_closedWindowItemList->erase(it); } emit removeWindowInOtherInstances(real_sender, closedWindowItem);+ + if(propagate)+ emitNotifyRemove(closedWindowItem); } const QList<KonqClosedWindowItem *>& KonqUndoManagerCommunicator::closedWindowItemList() {- return myKonqUndoManagerCommunicatorPrivate->m_closedWindowItemList;+ return *s_closedWindowItemList; } int KonqUndoManagerCommunicator::maxNumClosedItems()@@ -355,11 +381,330 @@ KConfigGroup configGroup( config, "UndoManagerSettings"); myKonqUndoManagerCommunicatorPrivate->m_maxNumClosedItems = configGroup.readEntry("Maximum number of Closed Items", 20 ); myKonqUndoManagerCommunicatorPrivate->m_maxNumClosedItems = qMax(1, myKonqUndoManagerCommunicatorPrivate->m_maxNumClosedItems);+ + myKonqUndoManagerCommunicatorPrivate->m_amIalone = true;+ populate();+ + // If in 0.5 seconds no other konqueror instance answer, we will assume that+ // we're alone and therefore instead of getting the undo closed window list+ // via dbus, we'll read it from disk+ QTimer::singleShot(500, this, SLOT(readConfig())); } ++ void KonqUndoManagerCommunicator::applySettings() { KConfigGroup configGroup(KSharedConfig::openConfig("konquerorrc"), "UndoManagerSettings"); configGroup.writeEntry("Value youngerThan", myKonqUndoManagerCommunicatorPrivate->m_maxNumClosedItems ); }++static QString dbusService()+{+ return QDBusConnection::sessionBus().baseService();+}++/**+ * Returns whether the DBUS call we are handling was a call from us self+ */+bool isSenderOfSignal( const QDBusMessage& msg )+{+ return dbusService() == msg.service();+}++bool isSenderOfSignal( const QString& service )+{+ return dbusService() == service;+}++void KonqUndoManagerCommunicator::emitNotifyClosedWindowItem(+ const KonqClosedWindowItem *closedWindowItem)+{+ emit notifyClosedWindowItem( closedWindowItem->title(),+ closedWindowItem->numTabs(),+ closedWindowItem->configGroup().config()->name(),+ closedWindowItem->configGroup().name() );+}++void KonqUndoManagerCommunicator::emitNotifyRemove(+ const KonqClosedWindowItem *closedWindowItem)+{+ const KonqClosedRemoteWindowItem* closedRemoteWindowItem =+ dynamic_cast<const KonqClosedRemoteWindowItem *>(closedWindowItem);++ // Here we do this because there's no need to call to configGroup() if it's+ // a remote window item, and it would be error prone to be so, because+ // it could give us a null pointer and konqueror would crash+ if(closedRemoteWindowItem)+ emit notifyRemove( closedRemoteWindowItem->remoteConfigFileName(),+ closedRemoteWindowItem->remoteGroupName() );+ else+ emit notifyRemove( closedWindowItem->configGroup().config()->name(),+ closedWindowItem->configGroup().name() );+}++void KonqUndoManagerCommunicator::slotNotifyClosedWindowItem(+ const QString& title, const int& numTabs, const QString& configFileName,+ const QString& configGroup, const QString& service )+{+ if ( isSenderOfSignal( service ) )+ return;+ + // Create a new ClosedWindowItem and add it to the list+ KonqClosedWindowItem* closedWindowItem = new KonqClosedRemoteWindowItem(+ title, configGroup, configFileName, + KonqFileUndoManager::self()->newCommandSerialNumber(), numTabs,+ service);+ + // Add it to all the windows but don't propogate over dbus,+ // as it already comes from dbus)+ addClosedWindowItem(0L, closedWindowItem, false); +}++void KonqUndoManagerCommunicator::slotNotifyClosedWindowItem(+ const QString& title, const int& numTabs, const QString& configFileName,+ const QString& configGroup, const QDBusMessage& msg )+{+ slotNotifyClosedWindowItem(title, numTabs, configFileName, configGroup, + msg.service() );+}++void KonqUndoManagerCommunicator::slotNotifyRemove( + const QString& configFileName, const QString& configGroup,+ const QDBusMessage& msg )+{+ if ( isSenderOfSignal( msg ) )+ return;+ + // Find the window item. It can be either remote or local+ KonqClosedWindowItem* closedWindowItem =+ findClosedRemoteWindowItem(configFileName, configGroup);+ if(!closedWindowItem)+ {+ closedWindowItem = findClosedLocalWindowItem(configFileName, configGroup);+ if(!closedWindowItem)+ return;+ }++ // Remove it in all the windows but don't propogate over dbus,+ // as it already comes from dbus)+ removeClosedWindowItem(0L, closedWindowItem, false);+}++void KonqUndoManagerCommunicator::slotRequestLocalClosedWindowItems(+ const QDBusMessage& msg)+{+ if ( isSenderOfSignal( msg ) )+ return;+ + emitPong(msg.service());+ + + if ( closedWindowItemList().empty() )+ return;+ + QList<QVariant> windowItems;+ KonqClosedWindowItem *closedWindowItem;+ for (QList<KonqClosedWindowItem *>::const_iterator it = closedWindowItemList().begin();+ it != closedWindowItemList().end(); ++it)+ {+ closedWindowItem = *it;+ KonqClosedRemoteWindowItem* closedRemoteWindowItem =+ dynamic_cast<KonqClosedRemoteWindowItem *>(closedWindowItem);+ + if(!closedRemoteWindowItem && closedWindowItem)+ {+ // Add to the list+ QByteArray data;+ QDataStream stream( &data, QIODevice::WriteOnly );+ stream << closedWindowItem->title();+ stream << closedWindowItem->numTabs();+ stream << closedWindowItem->configGroup().config()->name();+ stream << closedWindowItem->configGroup().name();+ QVariant variant(data);+ windowItems.append(variant);+ }+ }+ + if(!windowItems.empty())+ {+ QDBusInterface interface(msg.service(),+ "/KonqUndoManager", "org.kde.Konqueror.UndoManager");+ + if(!interface.isValid())+ return;+ + QList<QVariant> args;+ args.append(windowItems);+ args.append(dbusService());+ interface.callWithArgumentList(QDBus::NoBlock, "localClosedWindowItems", args );+ }+}++void KonqUndoManagerCommunicator::emitPong(const QString & service)+{+ QDBusInterface interface(service,+ "/KonqUndoManager", "org.kde.Konqueror.UndoManager");+ + if(!interface.isValid())+ return;+ + interface.call(QDBus::Block, "pong" );+}++void KonqUndoManagerCommunicator::localClosedWindowItems(+ const QList<QVariant>& windowItems, const QString& service)+{+ + for (QList<QVariant>::const_iterator it = windowItems.begin();+ it != windowItems.end(); ++it)+ {+ QString title, configFileName, configGroup;+ int numTabs;+ QByteArray data = (*it).toByteArray();+ QDataStream stream( const_cast<QByteArray *>( &data ), QIODevice::ReadOnly );+ stream >> title >> numTabs >> configFileName >> configGroup;+ slotNotifyClosedWindowItem(title, numTabs, configFileName, configGroup,+ service);+ }+ +}++void KonqUndoManagerCommunicator::pong()+{+ myKonqUndoManagerCommunicatorPrivate->m_amIalone = false;+}++KonqClosedRemoteWindowItem* KonqUndoManagerCommunicator::findClosedRemoteWindowItem(+ const QString& configFileName,+ const QString& configGroup)+{+ KonqClosedRemoteWindowItem* closedRemoteWindowItem = 0L;+ for (QList<KonqClosedWindowItem *>::const_iterator it = closedWindowItemList().begin();+ it != closedWindowItemList().end(); ++it)+ {+ closedRemoteWindowItem = dynamic_cast<KonqClosedRemoteWindowItem *>(*it);+ + if(closedRemoteWindowItem &&+ closedRemoteWindowItem->equalsTo(configFileName, configGroup))+ return closedRemoteWindowItem;+ }+ + return closedRemoteWindowItem;+}++KonqClosedWindowItem* KonqUndoManagerCommunicator::findClosedLocalWindowItem(+ const QString& configFileName,+ const QString& configGroup)+{+ KonqClosedWindowItem* closedWindowItem = 0L;+ for (QList<KonqClosedWindowItem *>::const_iterator it = closedWindowItemList().begin();+ it != closedWindowItemList().end(); ++it)+ {+ closedWindowItem = *it;+ KonqClosedRemoteWindowItem* closedRemoteWindowItem =+ dynamic_cast<KonqClosedRemoteWindowItem *>(closedWindowItem);+ + if(!closedRemoteWindowItem && closedWindowItem &&+ closedWindowItem->configGroup().config()->name() == configFileName &&+ closedWindowItem->configGroup().name() == configGroup)+ return closedWindowItem;+ }+ + return closedWindowItem;+}++void KonqUndoManagerCommunicator::populate()+{+ emit requestLocalClosedWindowItems();+}++void KonqUndoManagerCommunicator::removeClosedItemsConfigFiles()+{+ QString dir= KStandardDirs::locateLocal("appdata", "closeditems/");+ + QDirIterator it(dir, QDir::Writable|QDir::Files);+ while (it.hasNext())+ {+ QFile::remove(it.next());+ }+}+++void KonqUndoManagerCommunicator::saveConfig()+{+ // Create / overwrite the saved closed windows list+ QString filename = "closeditems_saved";+ QString file = KStandardDirs::locateLocal("appdata", filename);+ if(QFile::exists(file))+ QFile::remove(file);+ + KConfig *config = new KConfig(filename, KConfig::SimpleConfig, "appdata");+ + // Populate the config file+ KonqClosedWindowItem* closedWindowItem = 0L;+ uint counter = closedWindowItemList().size()-1;+ for (QList<KonqClosedWindowItem *>::const_iterator it = closedWindowItemList().begin();+ it != closedWindowItemList().end(); ++it, --counter)+ {+ closedWindowItem = *it;+ KConfigGroup configGroup(config, "Closed_Window" + QString::number(counter));+ configGroup.writeEntry("title", closedWindowItem->title());+ configGroup.writeEntry("numTabs", closedWindowItem->numTabs());+ closedWindowItem->configGroup().copyTo(&configGroup);+ }+ + KConfigGroup configGroup(config, "General");+ configGroup.writeEntry("Number of Closed Windows", closedWindowItemList().size());+ + delete config;+}++void KonqUndoManagerCommunicator::readConfig()+{+ // We will read the configuration file *only* if we are alone, which means+ // only if we couldn't get the closed windows list via dbus because no+ // dbus instance answered/exists+ if(!myKonqUndoManagerCommunicatorPrivate->m_amIalone)+ return;+ + // Simplification: we assume there was no time to open and close+ // a konqueror window in 500ms of konqueror life time and thus there+ // shouldn't be any file in closeditem/* to do some houskeeping everytime+ // konqueror starts+ removeClosedItemsConfigFiles();+ + QString filename = "closeditems_saved";+ QString file = KStandardDirs::locateLocal("appdata", filename);+ + // If the config file doesn't exists, there's nothing to read+ if(!QFile::exists(file))+ return;+ + KConfig config(filename, KConfig::SimpleConfig, "appdata");+ KConfigGroup generalGroup(&config, "General");+ int numClosedWindows = generalGroup.readEntry("Number of Closed Windows", 0);+ + for(int i = 0; i < numClosedWindows; i++)+ {+ // For each item, create a new ClosedWindowItem+ KConfigGroup configGroup(&config, "Closed_Window" + QString::number(i));+ QString title = configGroup.readEntry("title", i18n("no name"));+ int numTabs = configGroup.readEntry("numTabs", 0);+ + KonqClosedWindowItem* closedWindowItem = new KonqClosedWindowItem(+ title, KonqFileUndoManager::self()->newCommandSerialNumber(), + numTabs);+ configGroup.copyTo(&closedWindowItem->configGroup());+ // TODO: the config file isn't being written to disk. Why oh why??+ // I don't know. But this obviously leads to crashes if other konqueror+ // instance tries to read this closed window item from a non existant+ // config file.+ kDebug() << "WRITE TO DISK: " << closedWindowItem->configGroup().config()->name();+ closedWindowItem->configGroup().config()->sync(); // this doesn't work :-(+ + // Add the item to all the windows and propagate over dbus+ addClosedWindowItem(0L, closedWindowItem, true); + }+}