mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 19:08:58 +03:00
Remove flickering by updating auto-complete menu items in-place
Instead of deleting the current items and creating new ones.
This commit is contained in:
parent
d6ac72ab3f
commit
7dab863738
2 changed files with 105 additions and 21 deletions
|
@ -53,11 +53,14 @@ class UserItem : public PopupItem
|
|||
public:
|
||||
UserItem(QWidget *parent, const QString &user_id);
|
||||
QString selectedText() const { return userId_; }
|
||||
void updateItem(const QString &user_id);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
void resolveAvatar(const QString &user_id);
|
||||
|
||||
QLabel *userName_;
|
||||
QString userId_;
|
||||
};
|
||||
|
@ -69,6 +72,7 @@ class RoomItem : public PopupItem
|
|||
public:
|
||||
RoomItem(QWidget *parent, const RoomSearchResult &res);
|
||||
QString selectedText() const { return roomId_; }
|
||||
void updateItem(const RoomSearchResult &res);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
|
@ -124,12 +128,16 @@ private:
|
|||
void resetSelection() { selectedItem_ = -1; }
|
||||
void selectFirstItem() { selectedItem_ = 0; }
|
||||
void selectLastItem() { selectedItem_ = layout_->count() - 1; }
|
||||
void removeItems()
|
||||
void removeLayoutItemsAfter(size_t startingPos)
|
||||
{
|
||||
size_t posToRemove = layout_->count() - 1;
|
||||
|
||||
QLayoutItem *item;
|
||||
while ((item = layout_->takeAt(0)) != 0) {
|
||||
while (startingPos <= posToRemove && (item = layout_->takeAt(posToRemove)) != 0) {
|
||||
delete item->widget();
|
||||
delete item;
|
||||
|
||||
posToRemove = layout_->count() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -96,6 +124,24 @@ RoomItem::RoomItem(QWidget *parent, const RoomSearchResult &res)
|
|||
avatar_->setImage(res.img);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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);
|
||||
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);
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue