rendered paste bodyIndex: src/konqcloseditem.cpp===================================================================--- src/konqcloseditem.cpp (revisión: 794475)+++ src/konqcloseditem.cpp (copia de trabajo)@@ -19,6 +19,7 @@ */ #include "konqcloseditem.h"+#include "konqundomanager.h" #include <QFile> #include <QFont> #include <QFontMetrics>@@ -34,27 +35,6 @@ #include <kstandarddirs.h> #include <unistd.h> -class KConfigNew-{-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;-};- class KonqIcon { public: KonqIcon()@@ -66,11 +46,10 @@ QImage image; }; -K_GLOBAL_STATIC(KConfigNew, s_config) 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(KonqClosedWindowsManager::self()->config(), group), m_serialNumber(serialNumber) { } @@ -92,7 +71,7 @@ kDebug(1202) << "deleted group" << m_configGroup.name(); } -QPixmap KonqClosedTabItem::icon() {+QPixmap KonqClosedTabItem::icon() const { return KonqPixmapProvider::self()->pixmapFor(m_url); } @@ -104,11 +83,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 +115,54 @@ 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()+{+ delete m_remoteConfigGroup;+ 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,11 @@ } mainWindow->viewManager()->loadRootItem( closedWindowItem.configGroup(), mainWindow->viewManager()->tabContainer(), KUrl(), true, KUrl() );+ // read window settings+ mainWindow->applyMainWindowSettings( KConfigGroup( KGlobal::config(), "KonqMainWindow" ), true );+ 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 KonqClosedWindowsManager konqundomanageradaptor KonqClosedWindowsManagerAdaptor)+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,16 @@ #ifndef KONQUNDOMANAGER_H #define KONQUNDOMANAGER_H -#include "konqprivate_export.h"- #include <QObject>+#include <QString>+#include <QList>+#include <kconfig.h> #include "konqcloseditem.h"+#include "konqundomanager_interface.h" class QAction;-class KonqUndoManagerCommunicatorPrivate;+class KonqClosedWindowsManagerPrivate;+class QDBusMessage;+ /** * Note that there is one KonqUndoManager per mainwindow. * It integrates KonqFileUndoManager (undoing file operations)@@ -54,7 +58,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 +106,157 @@ /** * 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+class KONQ_TESTS_EXPORT KonqClosedWindowsManager : public QObject { Q_OBJECT public:- friend class KonqUndoManagerCommunicatorPrivate;- static KonqUndoManagerCommunicator *self();+ friend class KonqClosedWindowsManagerPrivate;+ + static KonqClosedWindowsManager *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);+ + KConfig* config();+ 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();+ KonqClosedWindowsManager();+ + virtual ~KonqClosedWindowsManager();+ + /**+ * 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();+private:+ QList<KonqClosedWindowItem *> m_closedWindowItemList;+ KConfig *m_konqClosedItemsConfig;+ int m_maxNumClosedItems;+ bool m_amIalone;+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,35 @@ 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;+};+ #endif /* KONQCLOSEDITEM_H */ Index: src/konqundomanager.cpp===================================================================--- src/konqundomanager.cpp (revisión: 794475)+++ src/konqundomanager.cpp (copia de trabajo)@@ -19,23 +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 KonqClosedWindowsManagerPrivate+{ public:- KonqUndoManagerCommunicator instance;- QList<KonqClosedWindowItem *> m_closedWindowItemList;+ KonqClosedWindowsManager instance; int m_maxNumClosedItems;+ bool m_amIalone; }; -K_GLOBAL_STATIC(KonqUndoManagerCommunicatorPrivate, myKonqUndoManagerCommunicatorPrivate)+K_GLOBAL_STATIC(KonqClosedWindowsManagerPrivate, myKonqClosedWindowsManagerPrivate); + KonqUndoManager::KonqUndoManager(QObject* parent) : QObject(parent) {@@ -45,14 +58,12 @@ connect( KonqFileUndoManager::self(), SIGNAL(undoTextChanged(QString)), this, SLOT(slotFileUndoTextChanged(QString)) ); - connect(KonqUndoManagerCommunicator::self(),+ connect(KonqClosedWindowsManager::self(), SIGNAL(addWindowInOtherInstances(KonqUndoManager *, KonqClosedWindowItem *)), this, SLOT( slotAddClosedWindowItem(KonqUndoManager *, KonqClosedWindowItem *) ));- connect(KonqUndoManagerCommunicator::self(),+ connect(KonqClosedWindowsManager::self(), SIGNAL(removeWindowInOtherInstances(KonqUndoManager *, const KonqClosedWindowItem *)), this, SLOT( slotRemoveClosedWindowItem(KonqUndoManager *, const KonqClosedWindowItem *) ));-- populate(); } KonqUndoManager::~KonqUndoManager()@@ -62,22 +73,24 @@ disconnect( KonqFileUndoManager::self(), SIGNAL(undoTextChanged(QString)), this, SLOT(slotFileUndoTextChanged(QString)) ); - disconnect(KonqUndoManagerCommunicator::self(),+ disconnect(KonqClosedWindowsManager::self(), SIGNAL(addWindowInOtherInstances(KonqUndoManager *, KonqClosedWindowItem *)), this, SLOT( slotAddClosedWindowItem(KonqUndoManager *, KonqClosedWindowItem *) ));- disconnect(KonqUndoManagerCommunicator::self(),+ disconnect(KonqClosedWindowsManager::self(), SIGNAL(removeWindowInOtherInstances(KonqUndoManager *, const KonqClosedWindowItem *)), this, 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();+ KonqClosedWindowsManager::self()->closedWindowItemList(); foreach(KonqClosedWindowItem *closedWindowItem, closedWindowItemList) slotAddClosedWindowItem(0L, closedWindowItem);@@ -115,27 +128,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(); }@@ -149,7 +146,7 @@ if(real_sender == this) return; - if(m_closedItemList.size() >= KonqUndoManagerCommunicator::self()->maxNumClosedItems())+ if(m_closedItemList.size() >= KonqClosedWindowsManager::self()->maxNumClosedItems()) { const KonqClosedItem* last = m_closedItemList.last(); const KonqClosedTabItem* lastTab =@@ -161,7 +158,6 @@ delete lastTab; } - kDebug(); m_closedItemList.prepend(closedWindowItem); emit undoTextChanged(i18n("Und&o: Closed Window")); emit undoAvailable(true);@@ -170,7 +166,7 @@ void KonqUndoManager::addClosedWindowItem(KonqClosedWindowItem *closedWindowItem) {- KonqUndoManagerCommunicator::self()->addClosedWindowItem(this, closedWindowItem);+ KonqClosedWindowsManager::self()->addClosedWindowItem(this, closedWindowItem); } void KonqUndoManager::slotRemoveClosedWindowItem(KonqUndoManager *real_sender, const KonqClosedWindowItem *closedWindowItem)@@ -201,15 +197,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);+ KonqClosedWindowsManager::self()->removeClosedWindowItem(this, closedRemoteWindowItem);+ } else if(closedWindowItem) { emit openClosedWindow(*closedWindowItem);- emit removeWindowInOtherInstances(this, closedWindowItem);+ KonqClosedWindowsManager::self()->removeClosedWindowItem(this, closedWindowItem);+ closedWindowItem->configGroup().deleteGroup(); }- delete closedTabItem;+ delete closedItem; emit undoAvailable(this->undoAvailable()); emit undoTextChanged(this->undoText()); emit closedItemsListChanged();@@ -235,7 +237,7 @@ void KonqUndoManager::addClosedTabItem(KonqClosedTabItem* closedTabItem) {- if(m_closedItemList.size() >= KonqUndoManagerCommunicator::self()->maxNumClosedItems())+ if(m_closedItemList.size() >= KonqClosedWindowsManager::self()->maxNumClosedItems()) { const KonqClosedItem* last = m_closedItemList.last(); const KonqClosedTabItem* lastTab =@@ -258,7 +260,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 +270,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) {+ KonqClosedWindowsManager::self()->removeClosedWindowItem(this, closedWindowItem, false);+ delete closedWindowItem;+ } } emit closedItemsListChanged(); emit undoAvailable(this->undoAvailable());@@ -285,81 +290,426 @@ undoClosedItem(0); } -KonqUndoManagerCommunicator::KonqUndoManagerCommunicator()+KonqClosedWindowsManager::KonqClosedWindowsManager() { QTimer::singleShot(0, this, SLOT(readSettings()));+ + qDBusRegisterMetaType<QList<QVariant> >();+ + new KonqClosedWindowsManagerAdaptor ( 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)));+ + QString filename = "closeditems/closeditems_" + QString::number(getpid());+ QString file = KStandardDirs::locateLocal("appdata", filename);+ QFile::remove(file);+ + m_konqClosedItemsConfig = new KConfig(filename, KConfig::SimpleConfig, "appdata");+ } -KonqUndoManagerCommunicator::~KonqUndoManagerCommunicator()+KonqClosedWindowsManager::~KonqClosedWindowsManager() {+ saveConfig();+ + delete m_konqClosedItemsConfig; } -KonqUndoManagerCommunicator *KonqUndoManagerCommunicator::self()+KConfig* KonqClosedWindowsManager::config() {- return &myKonqUndoManagerCommunicatorPrivate->instance;+ return m_konqClosedItemsConfig; } -void KonqUndoManagerCommunicator::addClosedWindowItem(KonqUndoManager-*real_sender, KonqClosedWindowItem *closedWindowItem)+KonqClosedWindowsManager *KonqClosedWindowsManager::self() {+ return &myKonqClosedWindowsManagerPrivate->instance;+}++void KonqClosedWindowsManager::addClosedWindowItem(KonqUndoManager+*real_sender, KonqClosedWindowItem *closedWindowItem, bool propagate)+{ // If we are off the limit, remove the last closed window item- if(myKonqUndoManagerCommunicatorPrivate->m_closedWindowItemList.size() >= + if(m_closedWindowItemList.size() >= maxNumClosedItems()) {- QList<KonqClosedWindowItem *> &closedWindowItemList =- myKonqUndoManagerCommunicatorPrivate->m_closedWindowItemList;- KonqClosedWindowItem* last = closedWindowItemList.last();+ KonqClosedWindowItem* last = m_closedWindowItemList.last();+ emit removeWindowInOtherInstances(0L, last);- closedWindowItemList.removeLast();+ emitNotifyClosedWindowItem(closedWindowItem);+ + m_closedWindowItemList.removeLast(); delete last; } - myKonqUndoManagerCommunicatorPrivate->m_closedWindowItemList.prepend(closedWindowItem);+ m_closedWindowItemList.prepend(closedWindowItem); emit addWindowInOtherInstances(real_sender, closedWindowItem);+ + if(propagate)+ emitNotifyClosedWindowItem(closedWindowItem); } -void KonqUndoManagerCommunicator::removeClosedWindowItem(KonqUndoManager-*real_sender, const KonqClosedWindowItem *closedWindowItem)+void KonqClosedWindowsManager::removeClosedWindowItem(KonqUndoManager+*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(m_closedWindowItemList.begin(),+ m_closedWindowItemList.end(), closedWindowItem); // If the item was found, remove it from the list- if(it != closedWindowItemList.end()) {- closedWindowItemList.erase(it);+ if(it != m_closedWindowItemList.end()) {+ m_closedWindowItemList.erase(it); } emit removeWindowInOtherInstances(real_sender, closedWindowItem);+ + if(propagate)+ emitNotifyRemove(closedWindowItem); } -const QList<KonqClosedWindowItem *>& KonqUndoManagerCommunicator::closedWindowItemList()+const QList<KonqClosedWindowItem *>& KonqClosedWindowsManager::closedWindowItemList() {- return myKonqUndoManagerCommunicatorPrivate->m_closedWindowItemList;+ return m_closedWindowItemList; } -int KonqUndoManagerCommunicator::maxNumClosedItems()+int KonqClosedWindowsManager::maxNumClosedItems() {- return myKonqUndoManagerCommunicatorPrivate->m_maxNumClosedItems;+ return m_maxNumClosedItems; } -void KonqUndoManagerCommunicator::setMaxNumClosedItems(int max)+void KonqClosedWindowsManager::setMaxNumClosedItems(int max) {- myKonqUndoManagerCommunicatorPrivate->m_maxNumClosedItems = qMax(1, max);+ m_maxNumClosedItems = qMax(1, max); } -void KonqUndoManagerCommunicator::readSettings()+void KonqClosedWindowsManager::readSettings() { KSharedConfigPtr config = KGlobal::config(); KConfigGroup configGroup( config, "UndoManagerSettings");- myKonqUndoManagerCommunicatorPrivate->m_maxNumClosedItems = configGroup.readEntry("Maximum number of Closed Items", 20 );- myKonqUndoManagerCommunicatorPrivate->m_maxNumClosedItems = qMax(1, myKonqUndoManagerCommunicatorPrivate->m_maxNumClosedItems);+ m_maxNumClosedItems = configGroup.readEntry("Maximum number of Closed Items", 20 );+ m_maxNumClosedItems = qMax(1, m_maxNumClosedItems);+ + 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()+++void KonqClosedWindowsManager::applySettings() { KConfigGroup configGroup(KSharedConfig::openConfig("konquerorrc"), "UndoManagerSettings"); - configGroup.writeEntry("Value youngerThan", myKonqUndoManagerCommunicatorPrivate->m_maxNumClosedItems );+ configGroup.writeEntry("Value youngerThan", 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 KonqClosedWindowsManager::emitNotifyClosedWindowItem(+ const KonqClosedWindowItem *closedWindowItem)+{+ emit notifyClosedWindowItem( closedWindowItem->title(),+ closedWindowItem->numTabs(),+ closedWindowItem->configGroup().config()->name(),+ closedWindowItem->configGroup().name() );+}++void KonqClosedWindowsManager::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 KonqClosedWindowsManager::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 KonqClosedWindowsManager::slotNotifyClosedWindowItem(+ const QString& title, const int& numTabs, const QString& configFileName,+ const QString& configGroup, const QDBusMessage& msg )+{+ slotNotifyClosedWindowItem(title, numTabs, configFileName, configGroup, + msg.service() );+}++void KonqClosedWindowsManager::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 KonqClosedWindowsManager::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())+ {+ org::kde::Konqueror::UndoManager interface(msg.service(), + "/KonqUndoManager", QDBusConnection::sessionBus(), this);+ + if(!interface.isValid())+ return;+ + interface.localClosedWindowItems(windowItems, dbusService());+ }+}++void KonqClosedWindowsManager::emitPong(const QString & service)+{+ org::kde::Konqueror::UndoManager interface(service, + "/KonqUndoManager", QDBusConnection::sessionBus(), this);+ + if(!interface.isValid())+ return;+ + interface.pong();+}++void KonqClosedWindowsManager::localClosedWindowItems(+ const QList<QVariant>& windowItems, const QString& service)+{+ + QListIterator<QVariant> it(windowItems);+ for (it.toBack(); it.hasPrevious(); )+ {+ QString title, configFileName, configGroup;+ int numTabs;+ QByteArray data = (it.previous()).toByteArray();+ QDataStream stream( const_cast<QByteArray *>( &data ), QIODevice::ReadOnly );+ stream >> title >> numTabs >> configFileName >> configGroup;+ slotNotifyClosedWindowItem(title, numTabs, configFileName, configGroup,+ service);+ }+ +}++void KonqClosedWindowsManager::pong()+{+ m_amIalone = false;+}++KonqClosedRemoteWindowItem* KonqClosedWindowsManager::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* KonqClosedWindowsManager::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 KonqClosedWindowsManager::populate()+{+ emit requestLocalClosedWindowItems();+}++void KonqClosedWindowsManager::removeClosedItemsConfigFiles()+{+ QString dir= KStandardDirs::locateLocal("appdata", "closeditems/");+ + QDirIterator it(dir, QDir::Writable|QDir::Files);+ while (it.hasNext())+ {+ QFile::remove(it.next());+ }+}+++void KonqClosedWindowsManager::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 KonqClosedWindowsManager::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(!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());+ configGroup.writeEntry("foo", 0);+ closedWindowItem->configGroup().config()->sync();+ + // Add the item to all the windows and propagate over dbus+ addClosedWindowItem(0L, closedWindowItem, true); + }+}