From 087bc243ffb53e3273580bce5ce66305841a3bff Mon Sep 17 00:00:00 2001 From: Kevin Smith <git@kismith.co.uk> Date: Sat, 2 Oct 2010 09:53:43 +0100 Subject: Persist roster group expandiness. Release-Notes: Whether roster groups are expanded or collapsed is now persisted between sessions. Resolves: #399 diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index 7ff3ed0..9915da9 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -255,7 +255,7 @@ void MainController::handleConnected() { if (freshLogin) { serverDiscoInfo_ = boost::shared_ptr<DiscoInfo>(new DiscoInfo()); - rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickResolver_, presenceOracle_, presenceSender_, eventController_, uiEventStream_, client_->getIQRouter()); + rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickResolver_, presenceOracle_, presenceSender_, eventController_, uiEventStream_, client_->getIQRouter(), settings_); rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2)); rosterController_->onSignOutRequest.connect(boost::bind(&MainController::signOut, this)); diff --git a/Swift/Controllers/RosterController.cpp b/Swift/Controllers/RosterController.cpp index 79cf3b8..5288df1 100644 --- a/Swift/Controllers/RosterController.cpp +++ b/Swift/Controllers/RosterController.cpp @@ -37,12 +37,13 @@ namespace Swift { /** * The controller does not gain ownership of these parameters. */ -RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter) +RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings) : myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()) { iqRouter_ = iqRouter; presenceOracle_ = presenceOracle; presenceSender_ = presenceSender; eventController_ = eventController; + expandiness_ = new RosterGroupExpandinessPersister(roster_, settings); roster_->addFilter(offlineFilter_); mainWindow_->setRosterModel(roster_); @@ -65,7 +66,7 @@ RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, Avata RosterController::~RosterController() { delete offlineFilter_; - + delete expandiness_; } void RosterController::setNickResolver(NickResolver* nickResolver) { diff --git a/Swift/Controllers/RosterController.h b/Swift/Controllers/RosterController.h index 80e7e3e..3cb3812 100644 --- a/Swift/Controllers/RosterController.h +++ b/Swift/Controllers/RosterController.h @@ -14,6 +14,7 @@ #include "Swiften/Elements/RosterPayload.h" #include "Swiften/Avatars/AvatarManager.h" #include "Swift/Controllers/UIEvents/UIEvent.h" +#include "Swift/Controllers/RosterGroupExpandinessPersister.h" #include "Swiften/Base/boost_bsignals.h" #include <boost/shared_ptr.hpp> @@ -32,10 +33,11 @@ namespace Swift { class SubscriptionRequestEvent; class UIEventStream; class IQRouter; + class SettingsProvider; class RosterController { public: - RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter_); + RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter_, SettingsProvider* settings); ~RosterController(); void showRosterWindow(); MainWindow* getWindow() {return mainWindow_;}; @@ -70,6 +72,7 @@ namespace Swift { PresenceOracle* presenceOracle_; PresenceSender* presenceSender_; EventController* eventController_; + RosterGroupExpandinessPersister* expandiness_; IQRouter* iqRouter_; boost::bsignals::scoped_connection changeStatusConnection_; boost::bsignals::scoped_connection showOfflineConnection_; diff --git a/Swift/Controllers/RosterGroupExpandinessPersister.cpp b/Swift/Controllers/RosterGroupExpandinessPersister.cpp new file mode 100644 index 0000000..a6a998a --- /dev/null +++ b/Swift/Controllers/RosterGroupExpandinessPersister.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2010 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swift/Controllers/RosterGroupExpandinessPersister.h" + +#include <boost/bind.hpp> +#include <vector> + +#include "Swiften/Roster/GroupRosterItem.h" + +namespace Swift { + +RosterGroupExpandinessPersister::RosterGroupExpandinessPersister(Roster* roster, SettingsProvider* settings) : roster_(roster), settings_(settings) { + load(); + roster_->onGroupAdded.connect(boost::bind(&RosterGroupExpandinessPersister::handleGroupAdded, this, _1)); +} + +void RosterGroupExpandinessPersister::handleGroupAdded(GroupRosterItem* group) { + if (collapsed_.find(group->getDisplayName()) != collapsed_.end()) { + group->setExpanded(false); + } else { + group->setExpanded(true); + } + group->onExpandedChanged.connect(boost::bind(&RosterGroupExpandinessPersister::handleExpandedChanged, this, group, _1)); +} + +void RosterGroupExpandinessPersister::handleExpandedChanged(GroupRosterItem* group, bool expanded) { + if (expanded) { + collapsed_.erase(collapsed_.find(group->getDisplayName())); + } else { + collapsed_.insert(group->getDisplayName()); + } + save(); +} + +void RosterGroupExpandinessPersister::save() { + String setting; + foreach (const String& group, collapsed_) { + if (setting.isEmpty()) { + setting += "\n"; + } + setting += group; + } + settings_->storeString(SettingPath, setting); +} + +void RosterGroupExpandinessPersister::load() { + String saved = settings_->getStringSetting(SettingPath); + std::vector<String> collapsed = saved.split('\n'); + foreach (const String& group, collapsed) { + collapsed_.insert(group); + } +} + +const String RosterGroupExpandinessPersister::SettingPath = "GroupExpandiness"; + +} diff --git a/Swift/Controllers/RosterGroupExpandinessPersister.h b/Swift/Controllers/RosterGroupExpandinessPersister.h new file mode 100644 index 0000000..545c9d0 --- /dev/null +++ b/Swift/Controllers/RosterGroupExpandinessPersister.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2010 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <set> +#include "Swiften/Roster/Roster.h" +#include "Swiften/Settings/SettingsProvider.h" + +namespace Swift { + class RosterGroupExpandinessPersister { + public: + RosterGroupExpandinessPersister(Roster* roster, SettingsProvider* settings); + private: + void handleExpandedChanged(GroupRosterItem* group, bool expanded); + void handleGroupAdded(GroupRosterItem* group); + void load(); + void save(); + std::set<String> collapsed_; + Roster* roster_; + SettingsProvider* settings_; + static const String SettingPath; + }; +} diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript index d37b370..dead16a 100644 --- a/Swift/Controllers/SConscript +++ b/Swift/Controllers/SConscript @@ -29,6 +29,7 @@ if env["SCONS_STAGE"] == "build" : "MainController.cpp", "NickResolver.cpp", "RosterController.cpp", + "RosterGroupExpandinessPersister.cpp", "EventWindowController.cpp", "SoundEventController.cpp", "SystemTrayController.cpp", diff --git a/Swift/Controllers/UnitTest/RosterControllerTest.cpp b/Swift/Controllers/UnitTest/RosterControllerTest.cpp index 4ecc4c8..dde48ed 100644 --- a/Swift/Controllers/UnitTest/RosterControllerTest.cpp +++ b/Swift/Controllers/UnitTest/RosterControllerTest.cpp @@ -20,6 +20,7 @@ #include "Swiften/Roster/Roster.h" #include "Swiften/Roster/GroupRosterItem.h" #include "Swiften/Roster/ContactRosterItem.h" +#include "Swiften/Settings/DummySettingsProvider.h" #include "Swiften/Avatars/NullAvatarManager.h" #include "Swift/Controllers/XMPPEvents/EventController.h" #include "Swiften/Presence/PresenceOracle.h" @@ -61,7 +62,8 @@ class RosterControllerTest : public CppUnit::TestFixture presenceSender_ = new PresenceSender(stanzaChannel_); eventController_ = new EventController(); uiEventStream_ = new UIEventStream(); - rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickResolver_, presenceOracle_, presenceSender_, eventController_, uiEventStream_, router_); + settings_ = new DummySettingsProvider(); + rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickResolver_, presenceOracle_, presenceSender_, eventController_, uiEventStream_, router_, settings_); mainWindow_ = mainWindowFactory_->last; }; @@ -78,6 +80,7 @@ class RosterControllerTest : public CppUnit::TestFixture delete presenceOracle_; delete stanzaChannel_; delete uiEventStream_; + delete settings_; }; GroupRosterItem* groupChild(size_t i) { @@ -206,6 +209,7 @@ class RosterControllerTest : public CppUnit::TestFixture EventController* eventController_; UIEventStream* uiEventStream_; MockMainWindow* mainWindow_; + DummySettingsProvider* settings_; }; CPPUNIT_TEST_SUITE_REGISTRATION(RosterControllerTest); diff --git a/Swiften/Roster/GroupRosterItem.cpp b/Swiften/Roster/GroupRosterItem.cpp index aa9fdd4..325c890 100644 --- a/Swiften/Roster/GroupRosterItem.cpp +++ b/Swiften/Roster/GroupRosterItem.cpp @@ -31,7 +31,11 @@ bool GroupRosterItem::isExpanded() const { to avoid a loop in this case. */ void GroupRosterItem::setExpanded(bool expanded) { + bool old = expanded_; expanded_ = expanded; + if (expanded != old) { + onExpandedChanged(expanded); + } } const std::vector<RosterItem*>& GroupRosterItem::getChildren() const { diff --git a/Swiften/Roster/GroupRosterItem.h b/Swiften/Roster/GroupRosterItem.h index 67ced97..b306b59 100644 --- a/Swiften/Roster/GroupRosterItem.h +++ b/Swiften/Roster/GroupRosterItem.h @@ -29,6 +29,7 @@ class GroupRosterItem : public RosterItem { static bool itemLessThanWithoutStatus(const RosterItem* left, const RosterItem* right); void setExpanded(bool expanded); bool isExpanded() const; + boost::signal<void (bool)> onExpandedChanged; private: void handleChildrenChanged(GroupRosterItem* group); void handleDataChanged(RosterItem* item); diff --git a/Swiften/Settings/DummySettingsProvider.h b/Swiften/Settings/DummySettingsProvider.h new file mode 100644 index 0000000..33f02b7 --- /dev/null +++ b/Swiften/Settings/DummySettingsProvider.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2010 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include "Swiften/Settings/SettingsProvider.h" + +namespace Swift { + +class DummySettingsProvider : public SettingsProvider { + public: + virtual ~DummySettingsProvider() {} + virtual String getStringSetting(const String&) {return "";} + virtual void storeString(const String &, const String &) {} + virtual bool getBoolSetting(const String &, bool ) {return true;} + virtual void storeBool(const String &, bool ) {} + virtual int getIntSetting(const String &, int ) {return 0;} + virtual void storeInt(const String &, int ) {} + virtual std::vector<String> getAvailableProfiles() {return std::vector<String>();} + virtual void createProfile(const String& ) {} +}; + +} + + + -- cgit v0.10.2-6-g49f6