aboutsummaryrefslogtreecommitdiff
path: root/user.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'user.cpp')
-rw-r--r--user.cpp58
1 files changed, 33 insertions, 25 deletions
diff --git a/user.cpp b/user.cpp
index 2a3071af..8a9fa515 100644
--- a/user.cpp
+++ b/user.cpp
@@ -62,8 +62,8 @@ class User::Private
mutable int totalRooms = 0;
- QString nameForRoom(const Room* r) const;
- std::pair<bool, QString> setNameForRoom(const Room* r, QString newName);
+ QString nameForRoom(const Room* r, const QString& hint = {}) const;
+ void setNameForRoom(const Room* r, QString newName, QString oldName);
const Avatar& avatarForRoom(const Room* r) const;
bool setAvatarUrlForRoom(const Room* r, const QUrl& avatarUrl);
@@ -78,34 +78,29 @@ QIcon User::Private::defaultIcon()
return icon;
}
-QString User::Private::nameForRoom(const Room* r) const
+QString User::Private::nameForRoom(const Room* r, const QString& hint) const
{
+ // If the hint is accurate, this function is O(1) instead of O(n)
+ if (hint == mostUsedName || otherNames.contains(hint, r))
+ return hint;
return otherNames.key(r, mostUsedName);
}
-static constexpr int MIN_JOINED_ROOMS_TO_LOG = 100;
+static constexpr int MIN_JOINED_ROOMS_TO_LOG = 20;
-std::pair<bool, QString> User::Private::setNameForRoom(const Room* r,
- QString newName)
+void User::Private::setNameForRoom(const Room* r, QString newName,
+ QString oldName)
{
+ Q_ASSERT(oldName != newName);
+ Q_ASSERT(oldName == mostUsedName || otherNames.contains(oldName, r));
if (totalRooms < 2)
{
Q_ASSERT_X(totalRooms > 0 && otherNames.empty(), __FUNCTION__,
"Internal structures inconsistency");
- // The below uses that initialization list evaluation is ordered
- return { mostUsedName != newName,
- exchange(mostUsedName, move(newName)) };
- }
- QString oldName;
- // The below works because QMultiHash iterators dereference to stored values
- auto it = std::find(otherNames.begin(), otherNames.end(), r);
- if (it != otherNames.end())
- {
- oldName = it.key();
- if (oldName == newName)
- return { false, oldName }; // old name and new name coincide
- otherNames.erase(it);
+ mostUsedName = move(newName);
+ return;
}
+ otherNames.remove(oldName, r);
if (newName != mostUsedName)
{
// Check if the newName is about to become most used.
@@ -134,7 +129,6 @@ std::pair<bool, QString> User::Private::setNameForRoom(const Room* r,
else
otherNames.insert(newName, r);
}
- return { true, oldName };
}
const Avatar& User::Private::avatarForRoom(const Room* r) const
@@ -255,11 +249,19 @@ QString User::name(const Room* room) const
void User::updateName(const QString& newName, const Room* room)
{
- const auto setNameResult = d->setNameForRoom(room, newName);
- if (setNameResult.first)
+ updateName(newName, d->nameForRoom(room), room);
+}
+
+void User::updateName(const QString& newName, const QString& oldName,
+ const Room* room)
+{
+ Q_ASSERT(oldName == d->mostUsedName || d->otherNames.contains(oldName, room));
+ if (newName != oldName)
{
+ emit nameAboutToChange(newName, oldName, room);
+ d->setNameForRoom(room, newName, oldName);
setObjectName(displayname());
- emit nameChanged(newName, setNameResult.second, room);
+ emit nameChanged(newName, oldName, room);
}
}
@@ -337,7 +339,8 @@ QImage User::avatar(int width, int height, const Room* room)
return avatar(width, height, room, []{});
}
-QImage User::avatar(int width, int height, const Room* room, Avatar::get_callback_t callback)
+QImage User::avatar(int width, int height, const Room* room,
+ Avatar::get_callback_t callback)
{
return avatarObject(room).get(d->connection, width, height,
[=] { emit avatarChanged(this, room); callback(); });
@@ -385,7 +388,12 @@ void User::processEvent(RoomMemberEvent* event, const Room* room)
}
newName.truncate(match.capturedStart(0));
}
- updateName(event->displayName(), room);
+ if (event->prevContent())
+ updateName(event->displayName(),
+ d->nameForRoom(room, event->prevContent()->displayName),
+ room);
+ else
+ updateName(event->displayName(), room);
if (d->setAvatarUrlForRoom(room, event->avatarUrl()))
emit avatarChanged(this, room);
}