aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKitsune Ral <Kitsune-Ral@users.sf.net>2016-04-12 16:03:29 +0900
committerKitsune Ral <Kitsune-Ral@users.sf.net>2016-05-02 19:22:40 +0900
commit32b055f56287e97d84a4431a36909027991ef1fc (patch)
tree8c24e1de55ea3b582cdae03111399fa4854cec92
parentd5bde8fbf3f8a47fe1140f307be0dcd39d1c0307 (diff)
downloadlibquotient-32b055f56287e97d84a4431a36909027991ef1fc.tar.gz
libquotient-32b055f56287e97d84a4431a36909027991ef1fc.zip
Change the way room members are stored to the one recommended by the CS spec.
According to section 11.2.2.3 of the CS spec, clients SHOULD follow a certain algorithm of making a non-ambiguous display name of a user in the room context. This algorithm implies checking whether other room members have the same display name. This commit prepares for implementation of the algorithm: 1. Use a hash map instead of a list to store room members. The external Room::users() API is kept intact. 2. Convenience CRUD methods are implemented to deal with the hash map. 3. An additional slot for user renaming is introduced (because renaming affects the hash map). Binding of actual signals is left for the next commit. 4. nullptr is the recommended representation of a null pointer since C++11. Use that and mandate compiler support of that.
-rw-r--r--CMakeLists.txt1
-rw-r--r--room.cpp78
-rw-r--r--room.h1
3 files changed, 69 insertions, 11 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 32792435..0203f2dc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -104,6 +104,7 @@ else ( CMAKE_VERSION VERSION_LESS "3.1" )
target_compile_features(qmatrixclient PRIVATE cxx_lambdas)
target_compile_features(qmatrixclient PRIVATE cxx_auto_type)
target_compile_features(qmatrixclient PRIVATE cxx_generalized_initializers)
+ target_compile_features(qmatrixclient PRIVATE cxx_nullptr)
endif ( CMAKE_VERSION VERSION_LESS "3.1" )
target_link_libraries(qmatrixclient Qt5::Core Qt5::Network Qt5::Gui)
diff --git a/room.cpp b/room.cpp
index bf3477e3..b770c85c 100644
--- a/room.cpp
+++ b/room.cpp
@@ -18,6 +18,7 @@
#include "room.h"
+#include <QtCore/QHash>
#include <QtCore/QJsonArray>
#include <QtCore/QDebug>
@@ -40,6 +41,9 @@ using namespace QMatrixClient;
class Room::Private: public QObject
{
public:
+ /** Map of user names to users. User names potentially duplicate, hence a multi-hashmap. */
+ typedef QMultiHash<QString, User*> members_map_t;
+
Private(Room* parent): q(parent) {}
Room* q;
@@ -57,12 +61,23 @@ class Room::Private: public QObject
JoinState joinState;
int highlightCount;
int notificationCount;
- QList<User*> users;
+ members_map_t membersMap;
QList<User*> usersTyping;
QList<User*> membersLeft;
QHash<User*, QString> lastReadEvent;
QString prevBatch;
bool gettingNewContent;
+
+ // Convenience methods to work with the membersMap and usersLeft. addMember()
+ // and removeMember() emit respective Room:: signals after a succesful
+ // operation.
+ //void inviteUser(User* u); // We might get it at some point in time.
+ void addMember(User* u);
+ bool hasMember(User* u);
+ // You can't identify a single user by displayname, only by id
+ User* member(QString id);
+ void renameMember(User* u, QString oldName);
+ void removeMember(User* u);
};
Room::Room(Connection* connection, QString id)
@@ -202,7 +217,53 @@ QList< User* > Room::membersLeft() const
QList< User* > Room::users() const
{
- return d->users;
+ return d->membersMap.values();
+}
+
+void Room::Private::addMember(User *u)
+{
+ if (!membersMap.values(u->name()).contains(u))
+ {
+ membersMap.insert(u->name(), u);
+ emit q->userAdded(u);
+ }
+}
+
+bool Room::Private::hasMember(User* u)
+{
+ return membersMap.values(u->name()).contains(u);
+}
+
+User* Room::Private::member(QString id)
+{
+ User* u = connection->user(id);
+ return hasMember(u) ? u : nullptr;
+}
+
+void Room::Private::renameMember(User* u, QString oldName)
+{
+ // We can't use hasUser because we need to search by oldName
+ if (membersMap.values(oldName).contains(u))
+ {
+ membersMap.remove(oldName, u);
+ membersMap.insert(u->name(), u);
+ }
+}
+
+void Room::Private::removeMember(User* u)
+{
+ if (hasMember(u))
+ {
+ if ( !membersLeft.contains(u) )
+ membersLeft.append(u);
+ membersMap.remove(u->name(), u);
+ emit q->userRemoved(u);
+ }
+}
+
+void Room::memberRenamed(User* user, QString oldName)
+{
+ d->renameMember(user, oldName);
}
void Room::addMessage(Event* event)
@@ -333,18 +394,13 @@ void Room::processStateEvent(Event* event)
RoomMemberEvent* memberEvent = static_cast<RoomMemberEvent*>(event);
User* u = d->connection->user(memberEvent->userId());
u->processEvent(event);
- if( memberEvent->membership() == MembershipType::Join and !d->users.contains(u) )
+ if( memberEvent->membership() == MembershipType::Join )
{
- d->users.append(u);
- emit userAdded(u);
+ d->addMember(u);
}
- else if( memberEvent->membership() == MembershipType::Leave
- and d->users.contains(u) )
+ else if( memberEvent->membership() == MembershipType::Leave )
{
- d->users.removeAll(u);
- if ( !d->membersLeft.contains(u) )
- d->membersLeft.append(u);
- emit userRemoved(u);
+ d->removeMember(u);
}
}
}
diff --git a/room.h b/room.h
index fd49f2ef..72a1f249 100644
--- a/room.h
+++ b/room.h
@@ -68,6 +68,7 @@ namespace QMatrixClient
public slots:
void getPreviousContent();
+ void memberRenamed(User* user, QString oldName);
signals:
void newMessage(Event* event);