mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-26 13:08:48 +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:
|
public:
|
||||||
UserItem(QWidget *parent, const QString &user_id);
|
UserItem(QWidget *parent, const QString &user_id);
|
||||||
QString selectedText() const { return userId_; }
|
QString selectedText() const { return userId_; }
|
||||||
|
void updateItem(const QString &user_id);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void resolveAvatar(const QString &user_id);
|
||||||
|
|
||||||
QLabel *userName_;
|
QLabel *userName_;
|
||||||
QString userId_;
|
QString userId_;
|
||||||
};
|
};
|
||||||
|
@ -69,6 +72,7 @@ class RoomItem : public PopupItem
|
||||||
public:
|
public:
|
||||||
RoomItem(QWidget *parent, const RoomSearchResult &res);
|
RoomItem(QWidget *parent, const RoomSearchResult &res);
|
||||||
QString selectedText() const { return roomId_; }
|
QString selectedText() const { return roomId_; }
|
||||||
|
void updateItem(const RoomSearchResult &res);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
@ -124,12 +128,16 @@ private:
|
||||||
void resetSelection() { selectedItem_ = -1; }
|
void resetSelection() { selectedItem_ = -1; }
|
||||||
void selectFirstItem() { selectedItem_ = 0; }
|
void selectFirstItem() { selectedItem_ = 0; }
|
||||||
void selectLastItem() { selectedItem_ = layout_->count() - 1; }
|
void selectLastItem() { selectedItem_ = layout_->count() - 1; }
|
||||||
void removeItems()
|
void removeLayoutItemsAfter(size_t startingPos)
|
||||||
{
|
{
|
||||||
|
size_t posToRemove = layout_->count() - 1;
|
||||||
|
|
||||||
QLayoutItem *item;
|
QLayoutItem *item;
|
||||||
while ((item = layout_->takeAt(0)) != 0) {
|
while (startingPos <= posToRemove && (item = layout_->takeAt(posToRemove)) != 0) {
|
||||||
delete item->widget();
|
delete item->widget();
|
||||||
delete item;
|
delete item;
|
||||||
|
|
||||||
|
posToRemove = layout_->count() - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "SuggestionsPopup.hpp"
|
#include "SuggestionsPopup.hpp"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QPaintEvent>
|
#include <QPaintEvent>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QStyleOption>
|
#include <QStyleOption>
|
||||||
|
@ -60,10 +59,39 @@ UserItem::UserItem(QWidget *parent, const QString &user_id)
|
||||||
topLayout_->addWidget(avatar_);
|
topLayout_->addWidget(avatar_);
|
||||||
topLayout_->addWidget(userName_, 1);
|
topLayout_->addWidget(userName_, 1);
|
||||||
|
|
||||||
AvatarProvider::resolve(ChatPage::instance()->currentRoom(),
|
resolveAvatar(user_id);
|
||||||
userId_,
|
}
|
||||||
this,
|
|
||||||
[this](const QImage &img) { avatar_->setImage(img); });
|
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
|
void
|
||||||
|
@ -96,6 +124,24 @@ RoomItem::RoomItem(QWidget *parent, const RoomSearchResult &res)
|
||||||
avatar_->setImage(res.img);
|
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
|
void
|
||||||
RoomItem::mousePressEvent(QMouseEvent *event)
|
RoomItem::mousePressEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
|
@ -119,17 +165,33 @@ SuggestionsPopup::SuggestionsPopup(QWidget *parent)
|
||||||
void
|
void
|
||||||
SuggestionsPopup::addRooms(const std::vector<RoomSearchResult> &rooms)
|
SuggestionsPopup::addRooms(const std::vector<RoomSearchResult> &rooms)
|
||||||
{
|
{
|
||||||
removeItems();
|
|
||||||
|
|
||||||
if (rooms.empty()) {
|
if (rooms.empty()) {
|
||||||
hide();
|
hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &r : rooms) {
|
const size_t layoutCount = layout_->count();
|
||||||
auto room = new RoomItem(this, r);
|
const size_t roomCount = rooms.size();
|
||||||
layout_->addWidget(room);
|
|
||||||
connect(room, &RoomItem::clicked, this, &SuggestionsPopup::itemSelected);
|
// 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();
|
resetSelection();
|
||||||
|
@ -143,24 +205,38 @@ SuggestionsPopup::addRooms(const std::vector<RoomSearchResult> &rooms)
|
||||||
void
|
void
|
||||||
SuggestionsPopup::addUsers(const QVector<SearchResult> &users)
|
SuggestionsPopup::addUsers(const QVector<SearchResult> &users)
|
||||||
{
|
{
|
||||||
removeItems();
|
|
||||||
|
|
||||||
if (users.isEmpty()) {
|
if (users.isEmpty()) {
|
||||||
hide();
|
hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &u : users) {
|
const size_t layoutCount = layout_->count();
|
||||||
auto user = new UserItem(this, u.user_id);
|
const size_t userCount = users.size();
|
||||||
layout_->addWidget(user);
|
|
||||||
connect(user, &UserItem::clicked, this, &SuggestionsPopup::itemSelected);
|
// 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();
|
resetSelection();
|
||||||
adjustSize();
|
adjustSize();
|
||||||
|
|
||||||
resize(geometry().width(), 40 * users.size());
|
|
||||||
|
|
||||||
selectNextSuggestion();
|
selectNextSuggestion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue