Commits

prokhin_alexey  committed 9378628

Added Config::remove(), Config::clear(). Added caching of the contact list

  • Participants
  • Parent commits f536f9e

Comments (0)

Files changed (18)

File src/lime/account.cpp

 		config().setValue("isEnabled", true);
 	emit enabled();
 	onEnabled(this);
+	loadContactList();
 	return true;
 }
 
 {
 	if (!m_isEnabled)
 		return true;
+	storeContactList();
 	if (disableImpl()) {
 		m_isEnabled = false;
 		if (ExtensionManager::state() == ExtensionManager::Working)
 	onContactRemoved(this, contact);
 }
 
+void Account::storeContactList()
+{
+	auto cfg = config("contactListCache");
+	cfg.clear();
+	cfg.setValue("version", 1);
+	foreach (auto contact, m_contacts) {
+		if (!contact->isInList())
+			return;
+		cfg.beginGroup(contact->id());
+		cfg.setValue("name", contact->name());
+		cfg.setValue("groups", contact->groups());
+		cfg.setValue("avatar", contact->avatar());
+		cfg.endGroup();
+	}
+}
+
+void Account::loadContactList()
+{
+	auto cfg = config("contactListCache");
+	int ver = cfg.value("version", 0);
+	if (ver == 0)
+		return;
+	if (ver != 1) {
+		qWarning() << "Contact list cache is of unsupported version";
+		return;
+	}
+	cfg.handleGroups([&] {
+		auto contact = createContact(cfg.currentName());
+		qDebug() << cfg.currentName();
+		if (!contact)
+			return;
+		contact->updateName(cfg.value("name", QString()));
+		contact->updateGroups(cfg.value("groups", QStringList()));
+		contact->updateAvatar(cfg.value("avatar", QString()));
+		contact->updateInList(true);
+	});
+}
+
 QString Account::storeAvatar(const QByteArray &avatar, const QString &hash)
 {
 	auto avatarDir = QString("%1/avatars/%2")

File src/lime/account.h

 	/* The method must send a new \a status of the account to the server.
 	 */
 	virtual void setStatusImpl(Status status, const QString &statusText) = 0;
+	virtual void storeContactList();
+	virtual void loadContactList();
 private:
 	friend class Contact;
 	void removeContact(Contact *contact);

File src/lime/buddy.h

 	Status  m_status;
 	QString m_avatar;
 	QString m_statusText;
-	QStringRef m_hash;
 	QMap<QString, QVariantMap> m_extendedInfo;
 };
 

File src/lime/chatmanager.cpp

 	unit->m_isActive = true;
 	emit unit->chatActivated();
 	unit->onChatActivated(unit);
-	unit->clearUnireadMessages();
+	unit->clearUnreadMessages();
 }
 
 void ChatManager::handleChatDeactivation(ChatUnit *unit)

File src/lime/chatunit.cpp

 	ChatManager::instance()->activateChat(this);
 }
 
-void ChatUnit::clearUnireadMessages()
+void ChatUnit::clearUnreadMessages()
 {
 	if (!m_unread.isEmpty()) {
 		m_unread.clear();

File src/lime/chatunit.h

 	Signal<void(ToolTip *toolTip)> toolTipHook;
 public slots:
 	void activateChat();
-	void clearUnireadMessages();
+	void clearUnreadMessages();
 public: // static signals
 	static Signal<void(ChatUnit* /*unit*/, QString /* newName*/, QString /*oldName*/)> onNameChanged;
 	static Signal<void(ChatUnit* /*unit*/, Message /*message*/)> onMessageReceived;

File src/lime/config.cpp

 	file.close();
 }
 
-QString Config::currentName()
+QString Config::currentName() const
 {
 	return d->levels.last().name;
 }
 
+bool Config::remove(const QString &fullName)
+{
+	auto groups = getGroupList(fullName);
+	Q_ASSERT(!groups.isEmpty() && "Cannot remove a value with an empty name");
+	auto name = groups.takeLast();
+	Q_ASSERT(!name.isEmpty() && "Cannot remove a value with an empty name");
+	auto map = d->getGroupMap(groups);
+	return map->remove(name) > 0;
+}
+
+void Config::clear()
+{
+	auto &level = d->levels.last();
+	if (level.type == Level::Map) {
+		*level.map = QVariantMap();
+	} else {
+		Q_ASSERT(level.type == Level::List);
+		*level.list = QVariantList();
+	}
+}
+
 void Config::beginGroup(const QString &group)
 {
 	auto groups = getGroupList(group);
 	d->levels.append(newLevel);
 }
 
-void Config::handleArray(const function<void()> &hanler)
+void Config::handleArray(const function<void()> &handler)
 {
 	auto &level = d->levels.last();
 	Q_ASSERT(level.type == Level::List);
 	auto list = level.list;
 	for (int i = 0, n = list->size(); i < n; ++i) {
 		setArrayIndex(i);
-		hanler();
+		handler();
 	}
 }
 
-void Config::handleGroups(const function<void()> &hanler)
+void Config::handleGroups(const function<void()> &handler)
 {
 	auto &level = d->levels.last();
 	Q_ASSERT(level.type == Level::Map);
 	for (; itr != end; ++itr) {
 		if (itr.value().type() == QVariant::Map) {
 			beginGroup(itr.key());
-			hanler();
+			handler();
 			endGroup();
 		}
 	}
 }
 
-void Config::handleValues(const function<void(const QString &key, const QVariant &value)> &hanler)
+void Config::handleValues(const function<void(const QString &key, const QVariant &value)> &handler)
 {
 	auto &level = d->levels.last();
 	Q_ASSERT(level.type == Level::Map);
 	auto end = level.map->end();
 	for (; itr != end; ++itr) {
 		if (itr.value().type() != QVariant::Map)
-			hanler(itr.key(), itr.value());
+			handler(itr.key(), itr.value());
 	}
 }
 
 void Config::setValue(const QString &fullName, const QVariant &value)
 {
 	auto groups = getGroupList(fullName);
-	Q_ASSERT(!groups.isEmpty() && "Cannot set a value with empty name");
+	Q_ASSERT(!groups.isEmpty() && "Cannot set a value with an empty name");
 	auto name = groups.takeLast();
-	Q_ASSERT(!name.isEmpty() && "Cannot set a value with empty name");
+	Q_ASSERT(!name.isEmpty() && "Cannot set a value with an empty name");
 	auto map = d->getGroupMap(groups);
 	(*map)[name] = value;
 	d->changed = true;
 }
 
-QVariant Config::value(const QString &name, const QVariant &def) const
+QVariant Config::value(const QString &fullName, const QVariant &def) const
 {
-	auto &level = d->levels.last();
-	if (level.type == Level::Map)
-		return level.map->value(name, def);
-	return QVariant();
+	auto groups = getGroupList(fullName);
+	Q_ASSERT(!groups.isEmpty() && "Cannot get a value with an empty name");
+	auto name = groups.takeLast();
+	Q_ASSERT(!name.isEmpty() && "Cannot get a value with an empty name");
+	auto map = d->getGroupMap(groups);
+	return map->value(name, def);
 }
 
 } // Lime

File src/lime/config.h

 	Config(const Config &cfg);
 	Config &operator=(const Config &cfg);
 	void save();
-	QString currentName(); // name of the current group or array
+	QString currentName() const; // name of the current group or array
+	bool remove(const QString &name);
+	void clear(); // clear current group or an array
 
 	void beginGroup(const QString &group);
 	void endGroup();
 	int arraySize();
 	void setArrayIndex(int index);
 
-	void handleArray(const function<void()> &hanler);
-	void handleGroups(const function<void()> &hanler);
-	void handleValues(const function<void(const QString &key, const QVariant &value)> &hanler);
+	void handleArray(const function<void()> &handler);
+	void handleGroups(const function<void()> &handler);
+	void handleValues(const function<void(const QString &key, const QVariant &value)> &handler);
 
 	void setValue(const QString &name, const QVariant &value);
 	QVariant value(const QString &name, const QVariant &def = QVariant()) const;

File src/lime/contact.cpp

 
 void Contact::setInList(bool inList)
 {
+	setInListImpl(inList);
+}
+
+void Contact::updateGroups(const QStringList &groups)
+{
+	Q_ASSERT((flags() & SupportsMultiGroups) || groups.count() <= 1);
+	if (groups == m_groups)
+		return;
+	auto old = m_groups;
+	m_groups = groups;
+	emit groupsUpdated(groups, old);
+	onGroupsUpdated(this, groups, old);
+}
+
+void Contact::updateInList(bool inList)
+{
 	if (m_isInList == inList)
 		return;
 	m_isInList = inList;
 	onInListChanged(this, inList);
 }
 
-void Contact::updateGroups(const QStringList &groups)
-{
-	Q_ASSERT((flags() & SupportsMultiGroups) || groups.count() <= 1);
-	if (groups == m_groups)
-		return;
-	auto old = m_groups;
-	m_groups = groups;
-	emit groupsUpdated(groups, old);
-	onGroupsUpdated(this, groups, old);
-}
-
 }
 

File src/lime/contact.h

 	void removedFromContactList();
 protected:
 	void updateGroups(const QStringList &groups);
+	void updateInList(bool inList);
 protected:
 	virtual void setNameImpl(const QString &name) = 0;
 	virtual void setGroupsImpl(const QStringList &groups) = 0;
+	virtual void setInListImpl(bool inList) = 0;
 private:
+	friend class Account;
 	QStringList m_groups;
 	bool m_isInList;
 };

File src/protocols/jabber/jabbercontact.cpp

 	}
 }
 
+void JabberContact::setInListImpl(bool inList)
+{
+	auto roster = account()->roster();
+	if (inList)
+		roster->addContact(this);
+	else
+		roster->removeContact(this);
+	// TODO: update subscription
+}
+
 void JabberContact::updateData(QSharedPointer<Jreen::RosterItem> item)
 {
 	updateName(item->name());

File src/protocols/jabber/jabbercontact.h

 protected:
 	virtual SendMessageError sendMessageImpl(const Lime::Message& message);
 	void sendChatStateImpl(ChatState state);
-	virtual void setGroupsImpl(const QStringList& groups);
-	virtual void setNameImpl(const QString& name);
+	virtual void setGroupsImpl(const QStringList &groups);
+	virtual void setNameImpl(const QString &name);
+	virtual void setInListImpl(bool inList);
 private:
 	friend class JabberRoster;
 	friend class JabberMessageFilter;

File src/protocols/jabber/jabberroster.cpp

 	return ChatUnit::UnsupportedTypeError;
 }
 
+void JabberRoster::addContact(JabberContact *contact)
+{
+	add(contact->id(), contact->name(), contact->groups());
+}
+
+void JabberRoster::removeContact(JabberContact *contact)
+{
+	remove(contact->id());
+}
+
 void JabberRoster::onItemAdded(QSharedPointer<Jreen::RosterItem> item)
 {
 	auto contact = m_account->contact(item->jid(), true);
 	contact->updateData(item);
-	contact->addToContactList();
+	contact->updateInList(true);
 }
 
 void JabberRoster::onItemUpdated(QSharedPointer<Jreen::RosterItem> item)
 	auto contact = m_account->contact(item->jid(), false);
 	if (contact) {
 		contact->updateData(item);
-		contact->addToContactList();
+		contact->updateInList(true);
 	}
 }
 
 {
 	auto contact = m_account->contact(jid, false);
 	if (contact)
-		contact->removeFromContactList();
+		contact->updateInList(false);
 }
 
 } // Lime

File src/protocols/jabber/jabberroster.h

 public:
 	JabberRoster(JabberAccount *account);
 	static ChatUnit::SendMessageError sendMessage(const Message &message);
+	void addContact(JabberContact *contact);
+	void removeContact(JabberContact *contact);
 protected:
 	void onItemAdded(QSharedPointer<Jreen::RosterItem> item);
 	void onItemUpdated(QSharedPointer<Jreen::RosterItem> item);

File src/protocols/null/nullcontact.cpp

 
 NullContact::~NullContact()
 {
-
 }
 
 ChatUnit::SendMessageError NullContact::sendMessageImpl(const Message &message)
 	updateName(name);
 }
 
+void NullContact::setInListImpl(bool inList)
+{
+	updateInList(inList);
+}
+
 }

File src/protocols/null/nullcontact.h

 	virtual SendMessageError sendMessageImpl(const Lime::Message& message);
 	virtual void setGroupsImpl(const QStringList& groups);
 	virtual void setNameImpl(const QString& name);
+	virtual void setInListImpl(bool inList);
 };
 
 }

File src/tests/configtest.cpp

 	tmpDir.remove(cfgName);
 }
 
+void ConfigTest::removeAndClear()
+{
+	auto tmpDir = QDir::temp();
+	tmpDir.remove(cfgName);
+	auto cfgPath = tmpDir.filePath(cfgName);
+	Config cfg(cfgPath);
+	{
+		cfg.beginGroup("group");
+		cfg.setValue("str", "I'm suicidal value");
+		cfg.clear();
+		QCOMPARE(cfg.value("str", QString()), QString());
+		cfg.endGroup();
+	}
+	{
+		cfg.beginGroup("group");
+		cfg.setValue("value", 3.14);
+		cfg.remove("value");
+		QCOMPARE(cfg.value("value", 9.8), 9.8);
+		cfg.endGroup();
+		cfg.beginArray("array");
+		cfg.endArray();
+		cfg.remove("group");
+		cfg.remove("array");
+		QCOMPARE(cfg.hasChildGroup("group"), false);
+		QCOMPARE(cfg.hasChildGroup("array"), false);
+	}
+}
+
 UNITTEST(ConfigTest);
 
-} // Lime
+} // Lime

File src/tests/configtest.h

 private slots:
 	void basicConfigApi();
 	void lamdaConfigApi();
+	void removeAndClear();
 };
 
 } // Lime