summary refs log tree commit diff
path: root/src/SuggestionsPopup.cpp
diff options
context:
space:
mode:
authorKonstantinos Sideris <sideris.konstantin@gmail.com>2018-05-03 17:29:02 +0300
committerKonstantinos Sideris <sideris.konstantin@gmail.com>2018-05-03 17:29:02 +0300
commit7dab863738eddc29081dd9ebe63f05a8636046b3 (patch)
treed249d86f994bb2e5bc7ec5f803f693b5db2c214e /src/SuggestionsPopup.cpp
parentDefault to the first item in room selection menu (diff)
downloadnheko-7dab863738eddc29081dd9ebe63f05a8636046b3.tar.xz
Remove flickering by updating auto-complete menu items in-place
Instead of deleting the current items and creating new ones.
Diffstat (limited to 'src/SuggestionsPopup.cpp')
-rw-r--r--src/SuggestionsPopup.cpp114
1 files changed, 95 insertions, 19 deletions
diff --git a/src/SuggestionsPopup.cpp b/src/SuggestionsPopup.cpp

index 9ac2ef23..82b7938b 100644 --- a/src/SuggestionsPopup.cpp +++ b/src/SuggestionsPopup.cpp
@@ -5,7 +5,6 @@ #include "SuggestionsPopup.hpp" #include "Utils.h" -#include <QDebug> #include <QPaintEvent> #include <QPainter> #include <QStyleOption> @@ -60,10 +59,39 @@ UserItem::UserItem(QWidget *parent, const QString &user_id) topLayout_->addWidget(avatar_); topLayout_->addWidget(userName_, 1); - AvatarProvider::resolve(ChatPage::instance()->currentRoom(), - userId_, - this, - [this](const QImage &img) { avatar_->setImage(img); }); + resolveAvatar(user_id); +} + +void +UserItem::updateItem(const QString &user_id) +{ + userId_ = user_id; + + auto displayName = Cache::displayName(ChatPage::instance()->currentRoom(), userId_); + + // If it's a matrix id we use the second letter. + if (displayName.size() > 1 && displayName.at(0) == '@') + avatar_->setLetter(QChar(displayName.at(1))); + else + avatar_->setLetter(utils::firstChar(displayName)); + + userName_->setText(displayName); + resolveAvatar(user_id); +} + +void +UserItem::resolveAvatar(const QString &user_id) +{ + AvatarProvider::resolve( + ChatPage::instance()->currentRoom(), userId_, this, [this, user_id](const QImage &img) { + // The user on the widget when the avatar is resolved, + // might be different from the user that made the call. + if (user_id == userId_) + avatar_->setImage(img); + else + // We try to resolve the avatar again. + resolveAvatar(userId_); + }); } void @@ -97,6 +125,24 @@ RoomItem::RoomItem(QWidget *parent, const RoomSearchResult &res) } void +RoomItem::updateItem(const RoomSearchResult &result) +{ + roomId_ = QString::fromStdString(std::move(result.room_id)); + + auto name = + QFontMetrics(QFont()).elidedText(QString::fromStdString(std::move(result.info.name)), + Qt::ElideRight, + parentWidget()->width() - 10); + + roomName_->setText(name); + + if (!result.img.isNull()) + avatar_->setImage(result.img); + else + avatar_->setLetter(utils::firstChar(name)); +} + +void RoomItem::mousePressEvent(QMouseEvent *event) { if (event->buttons() != Qt::RightButton) @@ -119,17 +165,33 @@ SuggestionsPopup::SuggestionsPopup(QWidget *parent) void SuggestionsPopup::addRooms(const std::vector<RoomSearchResult> &rooms) { - removeItems(); - if (rooms.empty()) { hide(); return; } - for (const auto &r : rooms) { - auto room = new RoomItem(this, r); - layout_->addWidget(room); - connect(room, &RoomItem::clicked, this, &SuggestionsPopup::itemSelected); + const size_t layoutCount = layout_->count(); + const size_t roomCount = rooms.size(); + + // Remove the extra widgets from the layout. + if (roomCount < layoutCount) + removeLayoutItemsAfter(roomCount - 1); + + for (size_t i = 0; i < roomCount; ++i) { + auto item = layout_->itemAt(i); + + // Create a new widget if there isn't already one in that + // layout position. + if (!item) { + auto room = new RoomItem(this, rooms.at(i)); + connect(room, &RoomItem::clicked, this, &SuggestionsPopup::itemSelected); + layout_->addWidget(room); + } else { + // Update the current widget with the new data. + auto room = qobject_cast<RoomItem *>(item->widget()); + if (room) + room->updateItem(rooms.at(i)); + } } resetSelection(); @@ -143,24 +205,38 @@ SuggestionsPopup::addRooms(const std::vector<RoomSearchResult> &rooms) void SuggestionsPopup::addUsers(const QVector<SearchResult> &users) { - removeItems(); - if (users.isEmpty()) { hide(); return; } - for (const auto &u : users) { - auto user = new UserItem(this, u.user_id); - layout_->addWidget(user); - connect(user, &UserItem::clicked, this, &SuggestionsPopup::itemSelected); + const size_t layoutCount = layout_->count(); + const size_t userCount = users.size(); + + // Remove the extra widgets from the layout. + if (userCount < layoutCount) + removeLayoutItemsAfter(userCount - 1); + + for (size_t i = 0; i < userCount; ++i) { + auto item = layout_->itemAt(i); + + // Create a new widget if there isn't already one in that + // layout position. + if (!item) { + auto user = new UserItem(this, users.at(i).user_id); + connect(user, &UserItem::clicked, this, &SuggestionsPopup::itemSelected); + layout_->addWidget(user); + } else { + // Update the current widget with the new data. + auto userWidget = qobject_cast<UserItem *>(item->widget()); + if (userWidget) + userWidget->updateItem(users.at(i).user_id); + } } resetSelection(); adjustSize(); - resize(geometry().width(), 40 * users.size()); - selectNextSuggestion(); }