Compare commits

..

No commits in common. "a5f43c08fa5a8bc241bc1d69e043f43a1a2be054" and "42f890ea7ceed2cccfd09b1e8a82b070cee8d46d" have entirely different histories.

6 changed files with 22 additions and 103 deletions

View file

@ -214,7 +214,6 @@ DlgCreateGame::DlgCreateGame(const ServerInfo_Game &gameInfo, const QMap<int, QS
spectatorsNeedPasswordCheckBox->setChecked(gameInfo.spectators_need_password()); spectatorsNeedPasswordCheckBox->setChecked(gameInfo.spectators_need_password());
spectatorsCanTalkCheckBox->setChecked(gameInfo.spectators_can_chat()); spectatorsCanTalkCheckBox->setChecked(gameInfo.spectators_can_chat());
spectatorsSeeEverythingCheckBox->setChecked(gameInfo.spectators_omniscient()); spectatorsSeeEverythingCheckBox->setChecked(gameInfo.spectators_omniscient());
shareDecklistsOnLoadCheckBox->setChecked(gameInfo.share_decklists_on_load());
QSet<int> types; QSet<int> types;
for (int i = 0; i < gameInfo.game_types_size(); ++i) { for (int i = 0; i < gameInfo.game_types_size(); ++i) {

View file

@ -527,21 +527,6 @@ void UserInfoPopup::onGamesContextMenu(const QPoint &pos)
// ── showForUser ─────────────────────────────────────────────────────────────── // ── showForUser ───────────────────────────────────────────────────────────────
void UserInfoPopup::refreshHeader()
{
if (m_currentUser.isEmpty()) {
return;
}
const QPixmap avatar = m_avatarCache ? m_avatarCache->value(m_currentUser) : QPixmap{};
const CardArtParams params = (m_cardArtParamsMap && m_cardArtParamsMap->contains(m_currentUser))
? m_cardArtParamsMap->value(m_currentUser)
: CardArtParams{};
const QString artKey = m_currentUser + u'|' + params.cardName + u'|' + params.cardProviderId;
const QPixmap cardArt = (m_cardArtCache && !params.cardName.isEmpty()) ? m_cardArtCache->value(artKey) : QPixmap{};
m_header->setUserData(m_currentUserInfo, m_currentOnline, avatar, cardArt, params);
}
void UserInfoPopup::showForUser(const QString &userName, void UserInfoPopup::showForUser(const QString &userName,
const ServerInfo_User &userInfo, const ServerInfo_User &userInfo,
bool online, bool online,
@ -553,7 +538,13 @@ void UserInfoPopup::showForUser(const QString &userName,
m_currentOnline = online; m_currentOnline = online;
// Header // Header
refreshHeader(); const QPixmap avatar = m_avatarCache ? m_avatarCache->value(userName) : QPixmap{};
const CardArtParams params = (m_cardArtParamsMap && m_cardArtParamsMap->contains(userName))
? m_cardArtParamsMap->value(userName)
: CardArtParams{};
const QString artKey = userName + u'|' + params.cardName + u'|' + params.cardProviderId;
const QPixmap cardArt = (m_cardArtCache && !params.cardName.isEmpty()) ? m_cardArtCache->value(artKey) : QPixmap{};
m_header->setUserData(userInfo, online, avatar, cardArt, params);
// Actions // Actions
rebuildActionButtons(userInfo, online, isBuddy, isIgnored); rebuildActionButtons(userInfo, online, isBuddy, isIgnored);

View file

@ -116,9 +116,6 @@ public:
/** Called when buddy/ignore status changes externally while popup is open. */ /** Called when buddy/ignore status changes externally while popup is open. */
void updateActionButtons(const ServerInfo_User &userInfo, bool online, bool isBuddy, bool isIgnored); void updateActionButtons(const ServerInfo_User &userInfo, bool online, bool isBuddy, bool isIgnored);
/** Re-pulls the avatar/card art for the currently shown user (e.g. after it loads). */
void refreshHeader();
signals: signals:
void mouseEnteredPopup(); void mouseEnteredPopup();
void mouseLeftPopup(); void mouseLeftPopup();

View file

@ -23,7 +23,6 @@
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QPushButton> #include <QPushButton>
#include <QRadioButton> #include <QRadioButton>
#include <QScreen>
#include <QSpinBox> #include <QSpinBox>
#include <QWidget> #include <QWidget>
#include <libcockatrice/card/database/card_database_manager.h> #include <libcockatrice/card/database/card_database_manager.h>
@ -496,6 +495,8 @@ UserListWidget::UserListWidget(TabSupervisor *_tabSupervisor,
m_userInfoPopup->setWindowOpacity(0.0); m_userInfoPopup->setWindowOpacity(0.0);
m_userInfoPopup->installEventFilter(this); m_userInfoPopup->installEventFilter(this);
connectPopupSignals();
m_showPopupTimer = new QTimer(this); m_showPopupTimer = new QTimer(this);
m_showPopupTimer->setSingleShot(true); m_showPopupTimer->setSingleShot(true);
m_showPopupTimer->setInterval(280); m_showPopupTimer->setInterval(280);
@ -514,8 +515,6 @@ UserListWidget::UserListWidget(TabSupervisor *_tabSupervisor,
} }
}); });
connectPopupSignals();
userTree->setMouseTracking(true); userTree->setMouseTracking(true);
userTree->viewport()->setMouseTracking(true); userTree->viewport()->setMouseTracking(true);
userTree->viewport()->installEventFilter(this); userTree->viewport()->installEventFilter(this);
@ -544,14 +543,15 @@ UserListWidget::UserListWidget(TabSupervisor *_tabSupervisor,
connect(userTree->verticalScrollBar(), &QScrollBar::valueChanged, this, [this] { connect(userTree->verticalScrollBar(), &QScrollBar::valueChanged, this, [this] {
m_showPopupTimer->stop(); m_showPopupTimer->stop();
hidePopup(true); hidePopup(true);
requestAvatarsForVisibleItems();
}); });
// Forward join requests from popup upward // Forward join requests from popup upward
connect(m_userInfoPopup, &UserInfoPopup::joinGameRequested, this, &UserListWidget::joinGameRequested); connect(m_userInfoPopup, &UserInfoPopup::joinGameRequested, this, &UserListWidget::joinGameRequested);
connect(avatarProvider, &UserAvatarProvider::avatarUpdated, this, &UserListWidget::refreshVisibleUserHeader); connect(avatarProvider, &UserAvatarProvider::avatarUpdated, this,
connect(cardArtProvider, &UserCardArtProvider::cardArtUpdated, this, &UserListWidget::refreshVisibleUserHeader); [this](const QString &) { userTree->viewport()->update(); });
connect(cardArtProvider, &UserCardArtProvider::cardArtUpdated, this,
[this](const QString &) { userTree->viewport()->update(); });
connect(&SettingsCache::instance().appearance(), &AppearanceSettings::styleUserListChanged, this, connect(&SettingsCache::instance().appearance(), &AppearanceSettings::styleUserListChanged, this,
&UserListWidget::applyDisplayMode); &UserListWidget::applyDisplayMode);
@ -633,14 +633,6 @@ void UserListWidget::bind(UserListManager *mgr)
rebuild(); rebuild();
} }
void UserListWidget::refreshVisibleUserHeader(const QString &name)
{
userTree->viewport()->update();
if (m_userInfoPopup->isVisible() && m_userInfoPopup->currentUser() == name) {
m_userInfoPopup->refreshHeader();
}
}
void UserListWidget::refreshPopupButtons(const QString &userName) void UserListWidget::refreshPopupButtons(const QString &userName)
{ {
UserListTWI *item = users.value(userName); UserListTWI *item = users.value(userName);
@ -665,12 +657,6 @@ void UserListWidget::hideEvent(QHideEvent *e)
hidePopup(true); hidePopup(true);
} }
void UserListWidget::showEvent(QShowEvent *e)
{
QGroupBox::showEvent(e);
requestAvatarsForVisibleItems();
}
void UserListWidget::applyDisplayMode() void UserListWidget::applyDisplayMode()
{ {
const bool styled = SettingsCache::instance().appearance().getStyleUserList(); const bool styled = SettingsCache::instance().appearance().getStyleUserList();
@ -772,8 +758,6 @@ void UserListWidget::showPopupForUser(const QString &userName)
return; return;
} }
avatarProvider->requestAvatar(userName); // ensure the hovered user's avatar is fetched promptly
const ServerInfo_User &info = item->getUserInfo(); const ServerInfo_User &info = item->getUserInfo();
const bool online = item->data(0, UserListRoles::Online).toBool(); const bool online = item->data(0, UserListRoles::Online).toBool();
const bool isBuddy = userContextMenu->getUserListProxy()->isUserBuddy(userName); const bool isBuddy = userContextMenu->getUserListProxy()->isUserBuddy(userName);
@ -817,12 +801,7 @@ void UserListWidget::positionPopup(const QString &userName)
const int popH = m_userInfoPopup->height(); const int popH = m_userInfoPopup->height();
const int margin = 12; const int margin = 12;
QScreen *activeScreen = QGuiApplication::screenAt(itemTL); const QRect screen = QGuiApplication::primaryScreen()->availableGeometry();
if (!activeScreen) {
activeScreen = window()->screen();
}
const QRect screen =
activeScreen ? activeScreen->availableGeometry() : QGuiApplication::primaryScreen()->availableGeometry();
// ── X: prefer the side with more space ─────────────────────────────────── // ── X: prefer the side with more space ───────────────────────────────────
const int spaceLeft = vpTL.x() - screen.left() - margin; const int spaceLeft = vpTL.x() - screen.left() - margin;
@ -896,38 +875,6 @@ void UserListWidget::retranslateUi()
updateCount(); updateCount();
} }
void UserListWidget::beginBulkLoad()
{
m_bulkLoading = true;
}
void UserListWidget::endBulkLoad()
{
m_bulkLoading = false;
sortItems();
requestAvatarsForVisibleItems();
userTree->viewport()->update();
}
bool UserListWidget::isItemNearViewport(const UserListTWI *item) const
{
// Prefetch a full viewport of rows above and below so scrolling never shows
// an unloaded row.
const QRect nearView =
userTree->viewport()->rect().adjusted(0, -userTree->viewport()->height(), 0, userTree->viewport()->height());
return userTree->visualItemRect(item).intersects(nearView);
}
void UserListWidget::requestAvatarsForVisibleItems()
{
for (int i = 0; i < userTree->topLevelItemCount(); ++i) {
auto *twi = static_cast<UserListTWI *>(userTree->topLevelItem(i));
if (isItemNearViewport(twi)) {
avatarProvider->requestAvatar(QString::fromStdString(twi->getUserInfo().name()));
}
}
}
void UserListWidget::rebuild() void UserListWidget::rebuild()
{ {
userTree->clear(); userTree->clear();
@ -954,11 +901,11 @@ void UserListWidget::rebuild()
break; break;
} }
beginBulkLoad();
for (auto it = source->cbegin(); it != source->cend(); ++it) { for (auto it = source->cbegin(); it != source->cend(); ++it) {
processUserInfo(it.value(), manager->getOnlineUser(it.key()) != nullptr); processUserInfo(it.value(), manager->getOnlineUser(it.key()) != nullptr);
} }
endBulkLoad();
sortItems();
} }
void UserListWidget::processUserInfo(const ServerInfo_User &user, bool online) void UserListWidget::processUserInfo(const ServerInfo_User &user, bool online)
@ -993,15 +940,11 @@ void UserListWidget::processUserInfo(const ServerInfo_User &user, bool online)
++onlineCount; ++onlineCount;
} }
updateCount(); updateCount();
if (!m_bulkLoading && isItemNearViewport(item)) { avatarProvider->requestAvatar(userName);
avatarProvider->requestAvatar(userName);
}
} }
item->setOnline(online); item->setOnline(online);
if (!m_bulkLoading) { sortItems();
sortItems(); userTree->viewport()->update();
userTree->viewport()->update();
}
} }
bool UserListWidget::deleteUser(const QString &userName) bool UserListWidget::deleteUser(const QString &userName)

View file

@ -36,7 +36,6 @@ class QPlainTextEdit;
class Response; class Response;
class CommandContainer; class CommandContainer;
class UserContextMenu; class UserContextMenu;
class QShowEvent;
class BanDialog : public QDialog class BanDialog : public QDialog
{ {
@ -159,14 +158,11 @@ private:
QTimer *m_hidePopupTimer = nullptr; QTimer *m_hidePopupTimer = nullptr;
QString m_hoveredUser; QString m_hoveredUser;
bool m_popupPinned = false; bool m_popupPinned = false;
bool m_bulkLoading = false;
void showPopupForUser(const QString &userName); void showPopupForUser(const QString &userName);
void hidePopup(bool immediate = false); void hidePopup(bool immediate = false);
void positionPopup(const QString &userName); void positionPopup(const QString &userName);
void connectPopupSignals(); void connectPopupSignals();
bool isItemNearViewport(const UserListTWI *item) const;
void requestAvatarsForVisibleItems();
QMap<QString, UserListTWI *> users; QMap<QString, UserListTWI *> users;
TabSupervisor *tabSupervisor; TabSupervisor *tabSupervisor;
@ -181,7 +177,6 @@ private:
void refreshPopupButtons(const QString &userName); void refreshPopupButtons(const QString &userName);
private slots: private slots:
void userClicked(QTreeWidgetItem *item, int column); void userClicked(QTreeWidgetItem *item, int column);
void refreshVisibleUserHeader(const QString &name);
signals: signals:
void openMessageDialog(const QString &userName, bool focus); void openMessageDialog(const QString &userName, bool focus);
void addBuddy(const QString &userName); void addBuddy(const QString &userName);
@ -197,8 +192,6 @@ public:
QWidget *parent = nullptr); QWidget *parent = nullptr);
void bind(UserListManager *mgr); void bind(UserListManager *mgr);
void applyDisplayMode(); void applyDisplayMode();
void beginBulkLoad();
void endBulkLoad();
bool eventFilter(QObject *obj, QEvent *event) override; bool eventFilter(QObject *obj, QEvent *event) override;
void retranslateUi(); void retranslateUi();
void rebuild(); void rebuild();
@ -214,7 +207,6 @@ public:
protected: protected:
void hideEvent(QHideEvent *e) override; void hideEvent(QHideEvent *e) override;
void showEvent(QShowEvent *e) override;
}; };
#endif #endif

View file

@ -135,7 +135,6 @@ void TabAccount::retranslateUi()
void TabAccount::processListUsersResponse(const Response &response) void TabAccount::processListUsersResponse(const Response &response)
{ {
const Response_ListUsers &resp = response.GetExtension(Response_ListUsers::ext); const Response_ListUsers &resp = response.GetExtension(Response_ListUsers::ext);
allUsersList->beginBulkLoad();
for (int i = 0; i < resp.user_list_size(); ++i) { for (int i = 0; i < resp.user_list_size(); ++i) {
const ServerInfo_User &info = resp.user_list(i); const ServerInfo_User &info = resp.user_list(i);
const QString &userName = QString::fromStdString(info.name()); const QString &userName = QString::fromStdString(info.name());
@ -143,8 +142,8 @@ void TabAccount::processListUsersResponse(const Response &response)
ignoreList->setUserOnline(userName, true); ignoreList->setUserOnline(userName, true);
buddyList->setUserOnline(userName, true); buddyList->setUserOnline(userName, true);
} }
allUsersList->endBulkLoad();
allUsersList->sortItems();
ignoreList->sortItems(); ignoreList->sortItems();
buddyList->sortItems(); buddyList->sortItems();
} }
@ -189,20 +188,18 @@ void TabAccount::processUserLeftEvent(const Event_UserLeft &event)
void TabAccount::buddyListReceived(const QList<ServerInfo_User> &_buddyList) void TabAccount::buddyListReceived(const QList<ServerInfo_User> &_buddyList)
{ {
buddyList->beginBulkLoad();
for (const auto &user : _buddyList) { for (const auto &user : _buddyList) {
buddyList->processUserInfo(user, false); buddyList->processUserInfo(user, false);
} }
buddyList->endBulkLoad(); buddyList->sortItems();
} }
void TabAccount::ignoreListReceived(const QList<ServerInfo_User> &_ignoreList) void TabAccount::ignoreListReceived(const QList<ServerInfo_User> &_ignoreList)
{ {
ignoreList->beginBulkLoad();
for (const auto &user : _ignoreList) { for (const auto &user : _ignoreList) {
ignoreList->processUserInfo(user, false); ignoreList->processUserInfo(user, false);
} }
ignoreList->endBulkLoad(); ignoreList->sortItems();
} }
void TabAccount::processAddToListEvent(const Event_AddToList &event) void TabAccount::processAddToListEvent(const Event_AddToList &event)