diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index bee20d60..4ad7bd14 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -23,10 +23,6 @@
#include "MainWindow.h"
#include "MatrixClient.h"
#include "Olm.h"
-#include "RoomList.h"
-#include "SideBarActions.h"
-#include "Splitter.h"
-#include "UserInfoWidget.h"
#include "UserSettingsPage.h"
#include "Utils.h"
#include "ui/OverlayModal.h"
@@ -36,7 +32,6 @@
#include "notifications/Manager.h"
#include "dialogs/ReadReceipts.h"
-#include "popups/UserMentions.h"
#include "timeline/TimelineViewManager.h"
#include "blurhash.hpp"
@@ -76,62 +71,9 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
topLayout_->setSpacing(0);
topLayout_->setMargin(0);
- communitiesList_ = new CommunitiesList(this);
- topLayout_->addWidget(communitiesList_);
-
- splitter = new Splitter(this);
- splitter->setHandleWidth(0);
-
- topLayout_->addWidget(splitter);
-
- // SideBar
- sideBar_ = new QFrame(this);
- sideBar_->setObjectName("sideBar");
- sideBar_->setMinimumWidth(::splitter::calculateSidebarSizes(QFont{}).normal);
- sideBarLayout_ = new QVBoxLayout(sideBar_);
- sideBarLayout_->setSpacing(0);
- sideBarLayout_->setMargin(0);
-
- sideBarTopWidget_ = new QWidget(sideBar_);
- sidebarActions_ = new SideBarActions(this);
- connect(
- sidebarActions_, &SideBarActions::showSettings, this, &ChatPage::showUserSettingsPage);
- connect(sidebarActions_, &SideBarActions::joinRoom, this, &ChatPage::joinRoom);
- connect(sidebarActions_, &SideBarActions::createRoom, this, &ChatPage::createRoom);
-
- user_info_widget_ = new UserInfoWidget(sideBar_);
- connect(user_info_widget_, &UserInfoWidget::openGlobalUserProfile, this, [this]() {
- UserProfile *userProfile = new UserProfile("", utils::localUser(), view_manager_);
- emit view_manager_->openProfile(userProfile);
- });
-
- user_mentions_popup_ = new popups::UserMentions();
- room_list_ = new RoomList(userSettings, sideBar_);
- connect(room_list_, &RoomList::joinRoom, this, &ChatPage::joinRoom);
-
- sideBarLayout_->addWidget(user_info_widget_);
- sideBarLayout_->addWidget(room_list_);
- sideBarLayout_->addWidget(sidebarActions_);
-
- sideBarTopWidgetLayout_ = new QVBoxLayout(sideBarTopWidget_);
- sideBarTopWidgetLayout_->setSpacing(0);
- sideBarTopWidgetLayout_->setMargin(0);
-
- // Content
- content_ = new QFrame(this);
- content_->setObjectName("mainContent");
- contentLayout_ = new QVBoxLayout(content_);
- contentLayout_->setSpacing(0);
- contentLayout_->setMargin(0);
-
view_manager_ = new TimelineViewManager(callManager_, this);
- contentLayout_->addWidget(view_manager_->getWidget());
-
- // Splitter
- splitter->addWidget(sideBar_);
- splitter->addWidget(content_);
- splitter->restoreSizes(parent->width());
+ topLayout_->addWidget(view_manager_->getWidget());
connect(this,
&ChatPage::downloadedSecrets,
@@ -153,17 +95,6 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
trySync();
});
- connect(
- new QShortcut(QKeySequence("Ctrl+Down"), this), &QShortcut::activated, this, [this]() {
- if (isVisible())
- room_list_->nextRoom();
- });
- connect(
- new QShortcut(QKeySequence("Ctrl+Up"), this), &QShortcut::activated, this, [this]() {
- if (isVisible())
- room_list_->previousRoom();
- });
-
connectivityTimer_.setInterval(CHECK_CONNECTIVITY_INTERVAL);
connect(&connectivityTimer_, &QTimer::timeout, this, [=]() {
if (http::client()->access_token().empty()) {
@@ -185,10 +116,8 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
connect(this, &ChatPage::loggedOut, this, &ChatPage::logout);
- connect(
- view_manager_, &TimelineViewManager::showRoomList, splitter, &Splitter::showFullRoomList);
connect(view_manager_, &TimelineViewManager::inviteUsers, this, [this](QStringList users) {
- const auto room_id = current_room_.toStdString();
+ const auto room_id = currentRoom().toStdString();
for (int ii = 0; ii < users.size(); ++ii) {
QTimer::singleShot(ii * 500, this, [this, room_id, ii, users]() {
@@ -211,29 +140,6 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
}
});
- connect(room_list_, &RoomList::roomChanged, this, [this](QString room_id) {
- this->current_room_ = room_id;
- });
- connect(room_list_, &RoomList::roomChanged, splitter, &Splitter::showChatView);
-
- connect(room_list_, &RoomList::acceptInvite, this, [this](const QString &room_id) {
- joinRoom(room_id);
- room_list_->removeRoom(room_id, currentRoom() == room_id);
- });
-
- connect(room_list_, &RoomList::declineInvite, this, [this](const QString &room_id) {
- leaveRoom(room_id);
- room_list_->removeRoom(room_id, currentRoom() == room_id);
- });
-
- connect(view_manager_,
- &TimelineViewManager::updateRoomsLastMessage,
- room_list_,
- &RoomList::updateRoomDescription);
-
- connect(
- this, &ChatPage::updateGroupsInfo, communitiesList_, &CommunitiesList::setCommunities);
-
connect(this, &ChatPage::leftRoom, this, &ChatPage::removeRoom);
connect(this, &ChatPage::newRoom, this, &ChatPage::changeRoom, Qt::QueuedConnection);
connect(this, &ChatPage::notificationsRetrieved, this, &ChatPage::sendNotifications);
@@ -248,60 +154,23 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
}
});
- connect(communitiesList_,
- &CommunitiesList::communityChanged,
- this,
- [this](const QString &groupId) {
- current_community_ = groupId;
-
- if (groupId == "world") {
- auto hidden = communitiesList_->hiddenTagsAndCommunities();
- std::set<QString> roomsToHide = communitiesList_->roomList(groupId);
- for (const auto &hiddenTag : hidden) {
- auto temp = communitiesList_->roomList(hiddenTag);
- roomsToHide.insert(temp.begin(), temp.end());
- }
-
- room_list_->removeFilter(roomsToHide);
- } else {
- auto hidden = communitiesList_->hiddenTagsAndCommunities();
- hidden.erase(current_community_);
-
- auto roomsToShow = communitiesList_->roomList(groupId);
- for (const auto &hiddenTag : hidden) {
- for (const auto &r : communitiesList_->roomList(hiddenTag))
- roomsToShow.erase(r);
- }
-
- room_list_->applyFilter(roomsToShow);
- }
- });
-
connect(¬ificationsManager,
&NotificationsManager::notificationClicked,
this,
[this](const QString &roomid, const QString &eventid) {
Q_UNUSED(eventid)
- room_list_->highlightSelectedRoom(roomid);
+ view_manager_->rooms()->setCurrentRoom(roomid);
activateWindow();
});
connect(¬ificationsManager,
&NotificationsManager::sendNotificationReply,
this,
[this](const QString &roomid, const QString &eventid, const QString &body) {
+ view_manager_->rooms()->setCurrentRoom(roomid);
view_manager_->queueReply(roomid, eventid, body);
- room_list_->highlightSelectedRoom(roomid);
activateWindow();
});
- setGroupViewState(userSettings_->groupView());
-
- connect(userSettings_.data(),
- &UserSettings::groupViewStateChanged,
- this,
- &ChatPage::setGroupViewState);
-
- connect(this, &ChatPage::initializeRoomList, room_list_, &RoomList::initialize);
connect(
this,
&ChatPage::initializeViews,
@@ -312,30 +181,13 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
&ChatPage::initializeEmptyViews,
view_manager_,
&TimelineViewManager::initializeRoomlist);
- connect(this,
- &ChatPage::initializeMentions,
- user_mentions_popup_,
- &popups::UserMentions::initializeMentions);
connect(
this, &ChatPage::chatFocusChanged, view_manager_, &TimelineViewManager::chatFocusChanged);
connect(this, &ChatPage::syncUI, this, [this](const mtx::responses::Rooms &rooms) {
- try {
- room_list_->cleanupInvites(cache::invites());
- } catch (const lmdb::error &e) {
- nhlog::db()->error("failed to retrieve invites: {}", e.what());
- }
-
view_manager_->sync(rooms);
- removeLeftRooms(rooms.leave);
bool hasNotifications = false;
for (const auto &room : rooms.join) {
- auto room_id = QString::fromStdString(room.first);
- updateRoomNotificationCount(
- room_id,
- room.second.unread_notifications.notification_count,
- room.second.unread_notifications.highlight_count);
-
if (room.second.unread_notifications.notification_count > 0)
hasNotifications = true;
}
@@ -358,16 +210,6 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
emit notificationsRetrieved(std::move(res));
});
});
- connect(this, &ChatPage::syncRoomlist, room_list_, &RoomList::sync);
- connect(this, &ChatPage::syncTags, communitiesList_, &CommunitiesList::syncTags);
-
- // Callbacks to update the user info (top left corner of the page).
- connect(this, &ChatPage::setUserAvatar, user_info_widget_, &UserInfoWidget::setAvatar);
- connect(this, &ChatPage::setUserDisplayName, this, [this](const QString &name) {
- auto userid = utils::localUser();
- user_info_widget_->setUserId(userid);
- user_info_widget_->setDisplayName(name);
- });
connect(
this, &ChatPage::tryInitialSyncCb, this, &ChatPage::tryInitialSync, Qt::QueuedConnection);
@@ -420,8 +262,6 @@ ChatPage::dropToLoginPage(const QString &msg)
void
ChatPage::resetUI()
{
- room_list_->clear();
- user_info_widget_->reset();
view_manager_->clearAll();
emit unreadMessages(0);
@@ -474,9 +314,6 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token)
view_manager_,
&TimelineViewManager::updateReadReceipts);
- connect(
- cache::client(), &Cache::roomReadStatus, room_list_, &RoomList::updateReadStatus);
-
connect(cache::client(),
&Cache::removeNotification,
¬ificationsManager,
@@ -553,9 +390,7 @@ ChatPage::loadStateFromCache()
olm::client()->load(cache::restoreOlmAccount(), STORAGE_SECRET_KEY);
emit initializeEmptyViews();
- emit initializeRoomList(cache::roomInfo());
emit initializeMentions(cache::getTimelineMentions());
- emit syncTags(cache::roomInfo().toStdMap());
cache::calculateRoomReadStatus();
@@ -593,38 +428,6 @@ ChatPage::removeRoom(const QString &room_id)
nhlog::db()->critical("failure while removing room: {}", e.what());
// TODO: Notify the user.
}
-
- room_list_->removeRoom(room_id, room_id == current_room_);
-}
-
-void
-ChatPage::removeLeftRooms(const std::map<std::string, mtx::responses::LeftRoom> &rooms)
-{
- for (auto it = rooms.cbegin(); it != rooms.cend(); ++it) {
- const auto room_id = QString::fromStdString(it->first);
- room_list_->removeRoom(room_id, room_id == current_room_);
- }
-}
-
-void
-ChatPage::setGroupViewState(bool isEnabled)
-{
- if (!isEnabled) {
- communitiesList_->communityChanged("world");
- communitiesList_->hide();
-
- return;
- }
-
- communitiesList_->show();
-}
-
-void
-ChatPage::updateRoomNotificationCount(const QString &room_id,
- uint16_t notification_count,
- uint16_t highlight_count)
-{
- room_list_->updateUnreadMessageCount(room_id, notification_count, highlight_count);
}
void
@@ -673,18 +476,6 @@ ChatPage::sendNotifications(const mtx::responses::Notifications &res)
}
void
-ChatPage::showNotificationsDialog(const QPoint &widgetPos)
-{
- auto notifDialog = user_mentions_popup_;
-
- notifDialog->setGeometry(
- widgetPos.x() - (width() / 10), widgetPos.y() + 25, width() / 5, height() / 2);
-
- notifDialog->raise();
- notifDialog->showPopup();
-}
-
-void
ChatPage::tryInitialSync()
{
nhlog::crypto()->info("ed25519 : {}", olm::client()->identity_keys().ed25519);
@@ -782,11 +573,9 @@ ChatPage::startInitialSync()
olm::handle_to_device_messages(res.to_device.events);
emit initializeViews(std::move(res.rooms));
- emit initializeRoomList(cache::roomInfo());
emit initializeMentions(cache::getTimelineMentions());
cache::calculateRoomReadStatus();
- emit syncTags(cache::roomInfo().toStdMap());
} catch (const lmdb::error &e) {
nhlog::db()->error("failed to save state after initial sync: {}",
e.what());
@@ -823,12 +612,8 @@ ChatPage::handleSyncResponse(const mtx::responses::Sync &res, const std::string
auto updates = cache::getRoomInfo(cache::client()->roomsWithStateUpdates(res));
- emit syncRoomlist(updates);
-
emit syncUI(res.rooms);
- emit syncTags(cache::getRoomInfo(cache::client()->roomsWithTagUpdates(res)));
-
// if we process a lot of syncs (1 every 200ms), this means we clean the
// db every 100s
static int syncCounter = 0;
@@ -932,7 +717,7 @@ ChatPage::joinRoomVia(const std::string &room_id,
emit showNotification(tr("Failed to remove invite: %1").arg(e.what()));
}
- room_list_->highlightSelectedRoom(QString::fromStdString(room_id));
+ view_manager_->rooms()->setCurrentRoom(QString::fromStdString(room_id));
});
}
@@ -981,18 +766,17 @@ void
ChatPage::changeRoom(const QString &room_id)
{
view_manager_->rooms()->setCurrentRoom(room_id);
- room_list_->highlightSelectedRoom(room_id);
}
void
ChatPage::inviteUser(QString userid, QString reason)
{
- auto room = current_room_;
+ auto room = currentRoom();
if (QMessageBox::question(this,
tr("Confirm invite"),
tr("Do you really want to invite %1 (%2)?")
- .arg(cache::displayName(current_room_, userid))
+ .arg(cache::displayName(room, userid))
.arg(userid)) != QMessageBox::Yes)
return;
@@ -1014,12 +798,12 @@ ChatPage::inviteUser(QString userid, QString reason)
void
ChatPage::kickUser(QString userid, QString reason)
{
- auto room = current_room_;
+ auto room = currentRoom();
if (QMessageBox::question(this,
tr("Confirm kick"),
tr("Do you really want to kick %1 (%2)?")
- .arg(cache::displayName(current_room_, userid))
+ .arg(cache::displayName(room, userid))
.arg(userid)) != QMessageBox::Yes)
return;
@@ -1041,12 +825,12 @@ ChatPage::kickUser(QString userid, QString reason)
void
ChatPage::banUser(QString userid, QString reason)
{
- auto room = current_room_;
+ auto room = currentRoom();
if (QMessageBox::question(this,
tr("Confirm ban"),
tr("Do you really want to ban %1 (%2)?")
- .arg(cache::displayName(current_room_, userid))
+ .arg(cache::displayName(room, userid))
.arg(userid)) != QMessageBox::Yes)
return;
@@ -1068,12 +852,12 @@ ChatPage::banUser(QString userid, QString reason)
void
ChatPage::unbanUser(QString userid, QString reason)
{
- auto room = current_room_;
+ auto room = currentRoom();
if (QMessageBox::question(this,
tr("Confirm unban"),
tr("Do you really want to unban %1 (%2)?")
- .arg(cache::displayName(current_room_, userid))
+ .arg(cache::displayName(room, userid))
.arg(userid)) != QMessageBox::Yes)
return;
@@ -1175,51 +959,6 @@ ChatPage::getProfileInfo()
emit setUserAvatar(QString::fromStdString(res.avatar_url));
});
-
- http::client()->joined_groups(
- [this](const mtx::responses::JoinedGroups &res, mtx::http::RequestErr err) {
- if (err) {
- nhlog::net()->critical("failed to retrieve joined groups: {} {}",
- static_cast<int>(err->status_code),
- err->matrix_error.error);
- emit updateGroupsInfo({});
- return;
- }
-
- emit updateGroupsInfo(res);
- });
-}
-
-void
-ChatPage::hideSideBars()
-{
- // Don't hide side bar, if we are currently only showing the side bar!
- if (view_manager_->getWidget()->isVisible()) {
- communitiesList_->hide();
- sideBar_->hide();
- }
- view_manager_->enableBackButton();
-}
-
-void
-ChatPage::showSideBars()
-{
- if (userSettings_->groupView())
- communitiesList_->show();
-
- sideBar_->show();
- view_manager_->disableBackButton();
- content_->show();
-}
-
-uint64_t
-ChatPage::timelineWidth()
-{
- int sidebarWidth = sideBar_->minimumSize().width();
- sidebarWidth += communitiesList_->minimumSize().width();
- nhlog::ui()->info("timelineWidth: {}", size().width() - sidebarWidth);
-
- return size().width() - sidebarWidth;
}
void
@@ -1305,7 +1044,8 @@ ChatPage::startChat(QString userid)
if (std::find(room_members.begin(),
room_members.end(),
(userid).toStdString()) != room_members.end()) {
- room_list_->highlightSelectedRoom(QString::fromStdString(room_id));
+ view_manager_->rooms()->setCurrentRoom(
+ QString::fromStdString(room_id));
return;
}
}
@@ -1406,7 +1146,7 @@ ChatPage::handleMatrixUri(const QByteArray &uri)
for (auto roomid : joined_rooms) {
if (roomid == targetRoomId) {
- room_list_->highlightSelectedRoom(mxid1);
+ view_manager_->rooms()->setCurrentRoom(mxid1);
if (!mxid2.isEmpty())
view_manager_->showEvent(mxid1, mxid2);
return;
@@ -1424,7 +1164,7 @@ ChatPage::handleMatrixUri(const QByteArray &uri)
auto aliases = cache::client()->getRoomAliases(roomid);
if (aliases) {
if (aliases->alias == targetRoomAlias) {
- room_list_->highlightSelectedRoom(
+ view_manager_->rooms()->setCurrentRoom(
QString::fromStdString(roomid));
if (!mxid2.isEmpty())
view_manager_->showEvent(
@@ -1446,8 +1186,17 @@ ChatPage::handleMatrixUri(const QUrl &uri)
handleMatrixUri(uri.toString(QUrl::ComponentFormattingOption::FullyEncoded).toUtf8());
}
-void
-ChatPage::highlightRoom(const QString &room_id)
+bool
+ChatPage::isRoomActive(const QString &room_id)
+{
+ return isActiveWindow() && currentRoom() == room_id;
+}
+
+QString
+ChatPage::currentRoom() const
{
- room_list_->highlightSelectedRoom(room_id);
+ if (view_manager_->rooms()->currentRoom())
+ return view_manager_->rooms()->currentRoom()->roomId();
+ else
+ return "";
}
diff --git a/src/ChatPage.h b/src/ChatPage.h
index eb60047d..751e7074 100644
--- a/src/ChatPage.h
+++ b/src/ChatPage.h
@@ -27,15 +27,10 @@
#include "CacheCryptoStructs.h"
#include "CacheStructs.h"
-#include "CommunitiesList.h"
#include "notifications/Manager.h"
class OverlayModal;
-class RoomList;
-class SideBarActions;
-class Splitter;
class TimelineViewManager;
-class UserInfoWidget;
class UserSettings;
class NotificationsManager;
class TimelineModel;
@@ -53,11 +48,6 @@ struct Notifications;
struct Sync;
struct Timeline;
struct Rooms;
-struct LeftRoom;
-}
-
-namespace popups {
-class UserMentions;
}
using SecretsToDecrypt = std::map<std::string, mtx::secret_storage::AesHmacSha2EncryptedData>;
@@ -71,7 +61,6 @@ public:
// Initialize all the components of the UI.
void bootstrap(QString userid, QString homeserver, QString token);
- QString currentRoom() const { return current_room_; }
static ChatPage *instance() { return instance_; }
@@ -80,14 +69,6 @@ public:
TimelineViewManager *timelineManager() { return view_manager_; }
void deleteConfigs();
- CommunitiesList *communitiesList() { return communitiesList_; }
-
- //! Calculate the width of the message timeline.
- uint64_t timelineWidth();
- //! Hide the room & group list (if it was visible).
- void hideSideBars();
- //! Show the room/group list (if it was visible).
- void showSideBars();
void initiateLogout();
QString status() const;
@@ -95,6 +76,9 @@ public:
mtx::presence::PresenceState currentPresence() const;
+ // TODO(Nico): Get rid of this!
+ QString currentRoom() const;
+
public slots:
void handleMatrixUri(const QByteArray &uri);
void handleMatrixUri(const QUrl &uri);
@@ -102,7 +86,6 @@ public slots:
void startChat(QString userid);
void leaveRoom(const QString &room_id);
void createRoom(const mtx::requests::CreateRoom &req);
- void highlightRoom(const QString &room_id);
void joinRoom(const QString &room);
void joinRoomVia(const std::string &room_id,
const std::vector<std::string> &via,
@@ -145,13 +128,10 @@ signals:
void leftRoom(const QString &room_id);
void newRoom(const QString &room_id);
- void initializeRoomList(QMap<QString, RoomInfo>);
void initializeViews(const mtx::responses::Rooms &rooms);
void initializeEmptyViews();
void initializeMentions(const QMap<QString, mtx::responses::Notifications> ¬ifs);
void syncUI(const mtx::responses::Rooms &rooms);
- void syncRoomlist(const std::map<QString, RoomInfo> &updates);
- void syncTags(const std::map<QString, RoomInfo> &updates);
void dropToLoginPageCb(const QString &msg);
void notifyMessage(const QString &roomid,
@@ -161,7 +141,6 @@ signals:
const QString &message,
const QImage &icon);
- void updateGroupsInfo(const mtx::responses::JoinedGroups &groups);
void retrievedPresence(const QString &statusMsg, mtx::presence::PresenceState state);
void themeChanged();
void decryptSidebarChanged();
@@ -207,65 +186,31 @@ private:
void getProfileInfo();
//! Check if the given room is currently open.
- bool isRoomActive(const QString &room_id)
- {
- return isActiveWindow() && currentRoom() == room_id;
- }
+ bool isRoomActive(const QString &room_id);
using UserID = QString;
using Membership = mtx::events::StateEvent<mtx::events::state::Member>;
using Memberships = std::map<std::string, Membership>;
- using LeftRooms = std::map<std::string, mtx::responses::LeftRoom>;
- void removeLeftRooms(const LeftRooms &rooms);
-
void loadStateFromCache();
void resetUI();
- //! Decides whether or not to hide the group's sidebar.
- void setGroupViewState(bool isEnabled);
template<class Collection>
Memberships getMemberships(const std::vector<Collection> &events) const;
- //! Update the room with the new notification count.
- void updateRoomNotificationCount(const QString &room_id,
- uint16_t notification_count,
- uint16_t highlight_count);
//! Send desktop notification for the received messages.
void sendNotifications(const mtx::responses::Notifications &);
- void showNotificationsDialog(const QPoint &point);
-
template<typename T>
void connectCallMessage();
QHBoxLayout *topLayout_;
- Splitter *splitter;
-
- QWidget *sideBar_;
- QVBoxLayout *sideBarLayout_;
- QWidget *sideBarTopWidget_;
- QVBoxLayout *sideBarTopWidgetLayout_;
-
- QFrame *content_;
- QVBoxLayout *contentLayout_;
-
- CommunitiesList *communitiesList_;
- RoomList *room_list_;
TimelineViewManager *view_manager_;
- SideBarActions *sidebarActions_;
QTimer connectivityTimer_;
std::atomic_bool isConnected_;
- QString current_room_;
- QString current_community_;
-
- UserInfoWidget *user_info_widget_;
-
- popups::UserMentions *user_mentions_popup_;
-
// Global user settings.
QSharedPointer<UserSettings> userSettings_;
diff --git a/src/CommunitiesList.cpp b/src/CommunitiesList.cpp
deleted file mode 100644
index 7cc5d10e..00000000
--- a/src/CommunitiesList.cpp
+++ /dev/null
@@ -1,345 +0,0 @@
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include "CommunitiesList.h"
-#include "Cache.h"
-#include "Logging.h"
-#include "MatrixClient.h"
-#include "MxcImageProvider.h"
-#include "Splitter.h"
-#include "UserSettingsPage.h"
-
-#include <mtx/responses/groups.hpp>
-#include <nlohmann/json.hpp>
-
-#include <QLabel>
-
-CommunitiesList::CommunitiesList(QWidget *parent)
- : QWidget(parent)
-{
- QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
- sizePolicy.setHorizontalStretch(0);
- sizePolicy.setVerticalStretch(1);
- setSizePolicy(sizePolicy);
-
- topLayout_ = new QVBoxLayout(this);
- topLayout_->setSpacing(0);
- topLayout_->setMargin(0);
-
- const auto sideBarSizes = splitter::calculateSidebarSizes(QFont{});
- setFixedWidth(sideBarSizes.groups);
-
- scrollArea_ = new QScrollArea(this);
- scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- scrollArea_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- scrollArea_->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
- scrollArea_->setWidgetResizable(true);
- scrollArea_->setAlignment(Qt::AlignLeading | Qt::AlignTop | Qt::AlignVCenter);
-
- contentsLayout_ = new QVBoxLayout();
- contentsLayout_->setSpacing(0);
- contentsLayout_->setMargin(0);
-
- addGlobalItem();
- contentsLayout_->addStretch(1);
-
- scrollArea_->setLayout(contentsLayout_);
- topLayout_->addWidget(scrollArea_);
-
- connect(
- this, &CommunitiesList::avatarRetrieved, this, &CommunitiesList::updateCommunityAvatar);
-}
-
-void
-CommunitiesList::setCommunities(const mtx::responses::JoinedGroups &response)
-{
- // remove all non-tag communities
- auto it = communities_.begin();
- while (it != communities_.end()) {
- if (it->second->is_tag()) {
- ++it;
- } else {
- it = communities_.erase(it);
- }
- }
-
- addGlobalItem();
-
- for (const auto &group : response.groups)
- addCommunity(group);
-
- communities_["world"]->setPressedState(true);
- selectedCommunity_ = "world";
- emit communityChanged("world");
- sortEntries();
-}
-
-void
-CommunitiesList::syncTags(const std::map<QString, RoomInfo> &info)
-{
- for (const auto &room : info)
- setTagsForRoom(room.first, room.second.tags);
- emit communityChanged(selectedCommunity_);
- sortEntries();
-}
-
-void
-CommunitiesList::setTagsForRoom(const QString &room_id, const std::vector<std::string> &tags)
-{
- // create missing tag if any
- for (const auto &tag : tags) {
- // filter out tags we should ignore according to the spec
- // https://matrix.org/docs/spec/client_server/r0.4.0.html#id154
- // nheko currently does not make use of internal tags
- // so we ignore any tag containig a `.` (which would indicate a tag
- // in the form `tld.domain.*`) except for `m.*` and `u.*`.
- if (tag.find(".") != ::std::string::npos && tag.compare(0, 2, "m.") &&
- tag.compare(0, 2, "u."))
- continue;
- QString name = QString("tag:") + QString::fromStdString(tag);
- if (!communityExists(name)) {
- addCommunity(std::string("tag:") + tag);
- }
- }
- // update membership of the room for all tags
- auto it = communities_.begin();
- while (it != communities_.end()) {
- // Skip if the community is not a tag
- if (!it->second->is_tag()) {
- ++it;
- continue;
- }
- // insert or remove the room from the tag as appropriate
- std::string current_tag =
- it->first.right(static_cast<int>(it->first.size() - strlen("tag:")))
- .toStdString();
- if (std::find(tags.begin(), tags.end(), current_tag) != tags.end()) {
- // the room has this tag
- it->second->addRoom(room_id);
- } else {
- // the room does not have this tag
- it->second->delRoom(room_id);
- }
- // Check if the tag is now empty, if yes delete it
- if (it->second->rooms().empty()) {
- it = communities_.erase(it);
- } else {
- ++it;
- }
- }
-}
-
-void
-CommunitiesList::addCommunity(const std::string &group_id)
-{
- auto hiddenTags = UserSettings::instance()->hiddenTags();
-
- const auto id = QString::fromStdString(group_id);
-
- CommunitiesListItem *list_item = new CommunitiesListItem(id, scrollArea_);
-
- if (hiddenTags.contains(id))
- list_item->setDisabled(true);
-
- communities_.emplace(id, QSharedPointer<CommunitiesListItem>(list_item));
- contentsLayout_->insertWidget(contentsLayout_->count() - 1, list_item);
-
- connect(list_item,
- &CommunitiesListItem::clicked,
- this,
- &CommunitiesList::highlightSelectedCommunity);
- connect(list_item, &CommunitiesListItem::isDisabledChanged, this, [this]() {
- for (const auto &community : communities_) {
- if (community.second->isPressed()) {
- emit highlightSelectedCommunity(community.first);
- break;
- }
- }
-
- auto hiddenTags = hiddenTagsAndCommunities();
- // Qt < 5.14 compat
- QStringList hiddenTags_;
- for (auto &&t : hiddenTags)
- hiddenTags_.push_back(t);
- UserSettings::instance()->setHiddenTags(hiddenTags_);
- });
-
- if (group_id.empty() || group_id.front() != '+')
- return;
-
- nhlog::ui()->debug("Add community: {}", group_id);
-
- connect(this,
- &CommunitiesList::groupProfileRetrieved,
- this,
- [this](const QString &id, const mtx::responses::GroupProfile &profile) {
- if (communities_.find(id) == communities_.end())
- return;
-
- communities_.at(id)->setName(QString::fromStdString(profile.name));
-
- if (!profile.avatar_url.empty())
- fetchCommunityAvatar(id,
- QString::fromStdString(profile.avatar_url));
- });
- connect(this,
- &CommunitiesList::groupRoomsRetrieved,
- this,
- [this](const QString &id, const std::set<QString> &rooms) {
- nhlog::ui()->info(
- "Fetched rooms for {}: {}", id.toStdString(), rooms.size());
- if (communities_.find(id) == communities_.end())
- return;
-
- communities_.at(id)->setRooms(rooms);
- });
-
- http::client()->group_profile(
- group_id, [id, this](const mtx::responses::GroupProfile &res, mtx::http::RequestErr err) {
- if (err) {
- return;
- }
-
- emit groupProfileRetrieved(id, res);
- });
-
- http::client()->group_rooms(
- group_id, [id, this](const nlohmann::json &res, mtx::http::RequestErr err) {
- if (err) {
- return;
- }
-
- std::set<QString> room_ids;
- for (const auto &room : res.at("chunk"))
- room_ids.emplace(QString::fromStdString(room.at("room_id")));
-
- emit groupRoomsRetrieved(id, room_ids);
- });
-}
-
-void
-CommunitiesList::updateCommunityAvatar(const QString &community_id, const QPixmap &img)
-{
- if (!communityExists(community_id)) {
- nhlog::ui()->warn("Avatar update on nonexistent community {}",
- community_id.toStdString());
- return;
- }
-
- communities_.at(community_id)->setAvatar(img.toImage());
-}
-
-void
-CommunitiesList::highlightSelectedCommunity(const QString &community_id)
-{
- if (!communityExists(community_id)) {
- nhlog::ui()->debug("CommunitiesList: clicked unknown community");
- return;
- }
-
- selectedCommunity_ = community_id;
- emit communityChanged(community_id);
-
- for (const auto &community : communities_) {
- if (community.first != community_id) {
- community.second->setPressedState(false);
- } else {
- community.second->setPressedState(true);
- scrollArea_->ensureWidgetVisible(community.second.data());
- }
- }
-}
-
-void
-CommunitiesList::fetchCommunityAvatar(const QString &id, const QString &avatarUrl)
-{
- MxcImageProvider::download(
- QString(avatarUrl).remove(QStringLiteral("mxc://")),
- QSize(96, 96),
- [this, id](QString, QSize, QImage img, QString) {
- if (img.isNull()) {
- nhlog::net()->warn("failed to download avatar: {})", id.toStdString());
- return;
- }
-
- emit avatarRetrieved(id, QPixmap::fromImage(img));
- });
-}
-
-std::set<QString>
-CommunitiesList::roomList(const QString &id) const
-{
- if (communityExists(id))
- return communities_.at(id)->rooms();
-
- return {};
-}
-
-std::vector<std::string>
-CommunitiesList::currentTags() const
-{
- std::vector<std::string> tags;
- for (auto &entry : communities_) {
- CommunitiesListItem *item = entry.second.data();
- if (item->is_tag())
- tags.push_back(entry.first.mid(4).toStdString());
- }
- return tags;
-}
-
-std::set<QString>
-CommunitiesList::hiddenTagsAndCommunities() const
-{
- std::set<QString> hiddenTags;
- for (auto &entry : communities_) {
- if (entry.second->isDisabled())
- hiddenTags.insert(entry.first);
- }
-
- return hiddenTags;
-}
-
-void
-CommunitiesList::sortEntries()
-{
- std::vector<CommunitiesListItem *> header;
- std::vector<CommunitiesListItem *> communities;
- std::vector<CommunitiesListItem *> tags;
- std::vector<CommunitiesListItem *> footer;
- // remove all the contents and sort them in the 4 vectors
- for (auto &entry : communities_) {
- CommunitiesListItem *item = entry.second.data();
- contentsLayout_->removeWidget(item);
- // world is handled separately
- if (entry.first == "world")
- continue;
- // sort the rest
- if (item->is_tag())
- if (entry.first == "tag:m.favourite")
- header.push_back(item);
- else if (entry.first == "tag:m.lowpriority")
- footer.push_back(item);
- else
- tags.push_back(item);
- else
- communities.push_back(item);
- }
-
- // now there remains only the stretch in the layout, remove it
- QLayoutItem *stretch = contentsLayout_->itemAt(0);
- contentsLayout_->removeItem(stretch);
-
- contentsLayout_->addWidget(communities_["world"].data());
-
- auto insert_widgets = [this](auto &vec) {
- for (auto item : vec)
- contentsLayout_->addWidget(item);
- };
- insert_widgets(header);
- insert_widgets(communities);
- insert_widgets(tags);
- insert_widgets(footer);
-
- contentsLayout_->addItem(stretch);
-}
diff --git a/src/CommunitiesList.h b/src/CommunitiesList.h
deleted file mode 100644
index 12b275b0..00000000
--- a/src/CommunitiesList.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#pragma once
-
-#include <QScrollArea>
-#include <QSharedPointer>
-#include <QVBoxLayout>
-
-#include "CacheStructs.h"
-#include "CommunitiesListItem.h"
-
-namespace mtx::responses {
-struct GroupProfile;
-struct JoinedGroups;
-}
-
-class CommunitiesList : public QWidget
-{
- Q_OBJECT
-
-public:
- CommunitiesList(QWidget *parent = nullptr);
-
- void clear() { communities_.clear(); }
-
- void addCommunity(const std::string &id);
- void removeCommunity(const QString &id) { communities_.erase(id); };
- std::set<QString> roomList(const QString &id) const;
-
- void syncTags(const std::map<QString, RoomInfo> &info);
- void setTagsForRoom(const QString &id, const std::vector<std::string> &tags);
- std::vector<std::string> currentTags() const;
- std::set<QString> hiddenTagsAndCommunities() const;
-
-signals:
- void communityChanged(const QString &id);
- void avatarRetrieved(const QString &id, const QPixmap &img);
- void groupProfileRetrieved(const QString &group_id, const mtx::responses::GroupProfile &);
- void groupRoomsRetrieved(const QString &group_id, const std::set<QString> &res);
-
-public slots:
- void updateCommunityAvatar(const QString &id, const QPixmap &img);
- void highlightSelectedCommunity(const QString &id);
- void setCommunities(const mtx::responses::JoinedGroups &groups);
-
-private:
- void fetchCommunityAvatar(const QString &id, const QString &avatarUrl);
- void addGlobalItem() { addCommunity("world"); }
- void sortEntries();
-
- //! Check whether or not a community id is currently managed.
- bool communityExists(const QString &id) const
- {
- return communities_.find(id) != communities_.end();
- }
-
- QString selectedCommunity_;
- QVBoxLayout *topLayout_;
- QVBoxLayout *contentsLayout_;
- QScrollArea *scrollArea_;
-
- std::map<QString, QSharedPointer<CommunitiesListItem>> communities_;
-};
diff --git a/src/CommunitiesListItem.cpp b/src/CommunitiesListItem.cpp
deleted file mode 100644
index a2f2777d..00000000
--- a/src/CommunitiesListItem.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include "CommunitiesListItem.h"
-
-#include <QMenu>
-#include <QMouseEvent>
-
-#include "Utils.h"
-#include "ui/Painter.h"
-#include "ui/Ripple.h"
-#include "ui/RippleOverlay.h"
-
-CommunitiesListItem::CommunitiesListItem(QString group_id, QWidget *parent)
- : QWidget(parent)
- , groupId_(group_id)
-{
- setMouseTracking(true);
- setAttribute(Qt::WA_Hover);
-
- QPainterPath path;
- path.addRect(0, 0, parent->width(), height());
- rippleOverlay_ = new RippleOverlay(this);
- rippleOverlay_->setClipPath(path);
- rippleOverlay_->setClipping(true);
-
- menu_ = new QMenu(this);
- hideRoomsWithTagAction_ =
- new QAction(tr("Hide rooms with this tag or from this community"), this);
- hideRoomsWithTagAction_->setCheckable(true);
- menu_->addAction(hideRoomsWithTagAction_);
- connect(menu_, &QMenu::aboutToShow, this, [this]() {
- hideRoomsWithTagAction_->setChecked(isDisabled_);
- });
-
- connect(hideRoomsWithTagAction_, &QAction::triggered, this, [this](bool checked) {
- this->setDisabled(checked);
- });
-
- updateTooltip();
-}
-
-void
-CommunitiesListItem::contextMenuEvent(QContextMenuEvent *event)
-{
- menu_->popup(event->globalPos());
-}
-
-void
-CommunitiesListItem::setName(QString name)
-{
- name_ = name;
- updateTooltip();
-}
-
-void
-CommunitiesListItem::setPressedState(bool state)
-{
- if (isPressed_ != state) {
- isPressed_ = state;
- update();
- }
-}
-
-void
-CommunitiesListItem::setDisabled(bool state)
-{
- if (isDisabled_ != state) {
- isDisabled_ = state;
- update();
- emit isDisabledChanged();
- }
-}
-
-void
-CommunitiesListItem::mousePressEvent(QMouseEvent *event)
-{
- if (event->buttons() == Qt::RightButton) {
- QWidget::mousePressEvent(event);
- return;
- }
-
- emit clicked(groupId_);
-
- setPressedState(true);
-
- QPoint pos = event->pos();
- qreal radiusEndValue = static_cast<qreal>(width()) / 3;
-
- auto ripple = new Ripple(pos);
- ripple->setRadiusEndValue(radiusEndValue);
- ripple->setOpacityStartValue(0.15);
- ripple->setColor("white");
- ripple->radiusAnimation()->setDuration(200);
- ripple->opacityAnimation()->setDuration(400);
- rippleOverlay_->addRipple(ripple);
-}
-
-void
-CommunitiesListItem::paintEvent(QPaintEvent *)
-{
- Painter p(this);
- PainterHighQualityEnabler hq(p);
-
- if (isPressed_)
- p.fillRect(rect(), highlightedBackgroundColor_);
- else if (isDisabled_)
- p.fillRect(rect(), disabledBackgroundColor_);
- else if (underMouse())
- p.fillRect(rect(), hoverBackgroundColor_);
- else
- p.fillRect(rect(), backgroundColor_);
-
- if (avatar_.isNull()) {
- QPixmap source;
- if (groupId_ == "world")
- source = QPixmap(":/icons/icons/ui/world.png");
- else if (groupId_ == "tag:m.favourite")
- source = QPixmap(":/icons/icons/ui/star.png");
- else if (groupId_ == "tag:m.lowpriority")
- source = QPixmap(":/icons/icons/ui/lowprio.png");
- else if (groupId_.startsWith("tag:"))
- source = QPixmap(":/icons/icons/ui/tag.png");
-
- if (source.isNull()) {
- QFont font;
- font.setPointSizeF(font.pointSizeF() * 1.3);
- p.setFont(font);
-
- p.drawLetterAvatar(utils::firstChar(resolveName()),
- avatarFgColor_,
- avatarBgColor_,
- width(),
- height(),
- IconSize);
- } else {
- QPainter painter(&source);
- painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
- painter.fillRect(source.rect(), avatarFgColor_);
- painter.end();
-
- const int imageSz = 32;
- p.drawPixmap(
- QRect(
- (width() - imageSz) / 2, (height() - imageSz) / 2, imageSz, imageSz),
- source);
- }
- } else {
- p.save();
-
- p.drawAvatar(avatar_, width(), height(), IconSize);
- p.restore();
- }
-}
-
-void
-CommunitiesListItem::setAvatar(const QImage &img)
-{
- avatar_ = utils::scaleImageToPixmap(img, IconSize);
- update();
-}
-
-QString
-CommunitiesListItem::resolveName() const
-{
- if (!name_.isEmpty())
- return name_;
- if (groupId_.startsWith("tag:"))
- return groupId_.right(static_cast<int>(groupId_.size() - strlen("tag:")));
- if (!groupId_.startsWith("+"))
- return QString("Group"); // Group with no name or id.
-
- // Extract the localpart of the group.
- auto firstPart = groupId_.split(':').at(0);
- return firstPart.right(firstPart.size() - 1);
-}
-
-void
-CommunitiesListItem::updateTooltip()
-{
- if (groupId_ == "world")
- setToolTip(tr("All rooms"));
- else if (is_tag()) {
- QStringRef tag =
- groupId_.rightRef(static_cast<int>(groupId_.size() - strlen("tag:")));
- if (tag == "m.favourite")
- setToolTip(tr("Favourite rooms"));
- else if (tag == "m.lowpriority")
- setToolTip(tr("Low priority rooms"));
- else if (tag == "m.server_notice")
- setToolTip(tr("Server Notices", "Tag translation for m.server_notice"));
- else if (tag.startsWith("u."))
- setToolTip(tag.right(tag.size() - 2) + tr(" (tag)"));
- else
- setToolTip(tag + tr(" (tag)"));
- } else {
- QString name = resolveName();
- setToolTip(name + tr(" (community)"));
- }
-}
diff --git a/src/CommunitiesListItem.h b/src/CommunitiesListItem.h
deleted file mode 100644
index e7468611..00000000
--- a/src/CommunitiesListItem.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#pragma once
-
-#include <QSharedPointer>
-#include <QWidget>
-
-#include <set>
-
-#include "Config.h"
-
-class RippleOverlay;
-class QMouseEvent;
-class QMenu;
-
-class CommunitiesListItem : public QWidget
-{
- Q_OBJECT
- Q_PROPERTY(QColor highlightedBackgroundColor READ highlightedBackgroundColor WRITE
- setHighlightedBackgroundColor)
- Q_PROPERTY(QColor disabledBackgroundColor READ disabledBackgroundColor WRITE
- setDisabledBackgroundColor)
- Q_PROPERTY(
- QColor hoverBackgroundColor READ hoverBackgroundColor WRITE setHoverBackgroundColor)
- Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)
-
- Q_PROPERTY(QColor avatarFgColor READ avatarFgColor WRITE setAvatarFgColor)
- Q_PROPERTY(QColor avatarBgColor READ avatarBgColor WRITE setAvatarBgColor)
-
-public:
- CommunitiesListItem(QString group_id, QWidget *parent = nullptr);
-
- void setName(QString name);
- bool isPressed() const { return isPressed_; }
- bool isDisabled() const { return isDisabled_; }
- void setAvatar(const QImage &img);
-
- void setRooms(std::set<QString> room_ids) { room_ids_ = std::move(room_ids); }
- void addRoom(const QString &id) { room_ids_.insert(id); }
- void delRoom(const QString &id) { room_ids_.erase(id); }
- std::set<QString> rooms() const { return room_ids_; }
-
- bool is_tag() const { return groupId_.startsWith("tag:"); }
-
- QColor highlightedBackgroundColor() const { return highlightedBackgroundColor_; }
- QColor disabledBackgroundColor() const { return disabledBackgroundColor_; }
- QColor hoverBackgroundColor() const { return hoverBackgroundColor_; }
- QColor backgroundColor() const { return backgroundColor_; }
-
- QColor avatarFgColor() const { return avatarFgColor_; }
- QColor avatarBgColor() const { return avatarBgColor_; }
-
- void setHighlightedBackgroundColor(QColor &color) { highlightedBackgroundColor_ = color; }
- void setDisabledBackgroundColor(QColor &color) { disabledBackgroundColor_ = color; }
- void setHoverBackgroundColor(QColor &color) { hoverBackgroundColor_ = color; }
- void setBackgroundColor(QColor &color) { backgroundColor_ = color; }
-
- void setAvatarFgColor(QColor &color) { avatarFgColor_ = color; }
- void setAvatarBgColor(QColor &color) { avatarBgColor_ = color; }
-
- QSize sizeHint() const override
- {
- return QSize(IconSize + IconSize / 3, IconSize + IconSize / 3);
- }
-
-signals:
- void clicked(const QString &group_id);
- void isDisabledChanged();
-
-public slots:
- void setPressedState(bool state);
- void setDisabled(bool state);
-
-protected:
- void mousePressEvent(QMouseEvent *event) override;
- void paintEvent(QPaintEvent *event) override;
- void contextMenuEvent(QContextMenuEvent *event) override;
-
-private:
- const int IconSize = 36;
-
- QString resolveName() const;
- void updateTooltip();
-
- std::set<QString> room_ids_;
-
- QString name_;
- QString groupId_;
- QPixmap avatar_;
-
- QColor highlightedBackgroundColor_;
- QColor disabledBackgroundColor_;
- QColor hoverBackgroundColor_;
- QColor backgroundColor_;
-
- QColor avatarFgColor_;
- QColor avatarBgColor_;
-
- bool isPressed_ = false;
- bool isDisabled_ = false;
-
- RippleOverlay *rippleOverlay_;
- QMenu *menu_;
- QAction *hideRoomsWithTagAction_;
-};
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index e2b625b0..057ee4af 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -109,10 +109,6 @@ MainWindow::MainWindow(QWidget *parent)
userSettingsPage_, SIGNAL(trayOptionChanged(bool)), trayIcon_, SLOT(setVisible(bool)));
connect(
userSettingsPage_, &UserSettingsPage::themeChanged, chat_page_, &ChatPage::themeChanged);
- connect(userSettingsPage_,
- &UserSettingsPage::decryptSidebarChanged,
- chat_page_,
- &ChatPage::decryptSidebarChanged);
connect(trayIcon_,
SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
this,
@@ -176,20 +172,6 @@ MainWindow::setWindowTitle(int notificationCount)
QMainWindow::setWindowTitle(name);
}
-void
-MainWindow::showEvent(QShowEvent *event)
-{
- adjustSideBars();
- QMainWindow::showEvent(event);
-}
-
-void
-MainWindow::resizeEvent(QResizeEvent *event)
-{
- adjustSideBars();
- QMainWindow::resizeEvent(event);
-}
-
bool
MainWindow::event(QEvent *event)
{
@@ -204,22 +186,6 @@ MainWindow::event(QEvent *event)
}
void
-MainWindow::adjustSideBars()
-{
- const auto sz = splitter::calculateSidebarSizes(QFont{});
-
- const uint64_t timelineWidth = chat_page_->timelineWidth();
- const uint64_t minAvailableWidth = sz.collapsePoint + sz.groups;
-
- nhlog::ui()->info("timelineWidth: {}, min {}", timelineWidth, minAvailableWidth);
- if (timelineWidth < minAvailableWidth) {
- chat_page_->hideSideBars();
- } else {
- chat_page_->showSideBars();
- }
-}
-
-void
MainWindow::restoreWindowSize()
{
QSettings settings;
diff --git a/src/MainWindow.h b/src/MainWindow.h
index 69d07e62..3571f079 100644
--- a/src/MainWindow.h
+++ b/src/MainWindow.h
@@ -77,13 +77,9 @@ public:
protected:
void closeEvent(QCloseEvent *event) override;
- void resizeEvent(QResizeEvent *event) override;
- void showEvent(QShowEvent *event) override;
bool event(QEvent *event) override;
private slots:
- //! Show or hide the sidebars based on window's size.
- void adjustSideBars();
//! Handle interaction with the tray icon.
void iconActivated(QSystemTrayIcon::ActivationReason reason);
diff --git a/src/RoomInfoListItem.cpp b/src/RoomInfoListItem.cpp
deleted file mode 100644
index ea5de674..00000000
--- a/src/RoomInfoListItem.cpp
+++ /dev/null
@@ -1,522 +0,0 @@
-// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include <QDateTime>
-#include <QInputDialog>
-#include <QMenu>
-#include <QMouseEvent>
-#include <QPainter>
-#include <QtGlobal>
-
-#include "AvatarProvider.h"
-#include "Cache.h"
-#include "ChatPage.h"
-#include "Config.h"
-#include "Logging.h"
-#include "MatrixClient.h"
-#include "RoomInfoListItem.h"
-#include "Splitter.h"
-#include "UserSettingsPage.h"
-#include "Utils.h"
-#include "ui/Ripple.h"
-#include "ui/RippleOverlay.h"
-
-constexpr int MaxUnreadCountDisplayed = 99;
-
-struct WidgetMetrics
-{
- int maxHeight;
- int iconSize;
- int padding;
- int unit;
-
- int unreadLineWidth;
- int unreadLineOffset;
-
- int inviteBtnX;
- int inviteBtnY;
-};
-
-WidgetMetrics
-getMetrics(const QFont &font)
-{
- WidgetMetrics m;
-
- const int height = QFontMetrics(font).lineSpacing();
-
- m.unit = height;
- m.maxHeight = std::ceil((double)height * 3.8);
- m.iconSize = std::ceil((double)height * 2.8);
- m.padding = std::ceil((double)height / 2.0);
- m.unreadLineWidth = m.padding - m.padding / 3;
- m.unreadLineOffset = m.padding - m.padding / 4;
-
- m.inviteBtnX = m.iconSize + 2 * m.padding;
- m.inviteBtnY = m.iconSize / 2.0 + m.padding + m.padding / 3.0;
-
- return m;
-}
-
-void
-RoomInfoListItem::init(QWidget *parent)
-{
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
- setMouseTracking(true);
- setAttribute(Qt::WA_Hover);
-
- auto wm = getMetrics(QFont{});
- setFixedHeight(wm.maxHeight);
-
- QPainterPath path;
- path.addRect(0, 0, parent->width(), height());
-
- ripple_overlay_ = new RippleOverlay(this);
- ripple_overlay_->setClipPath(path);
- ripple_overlay_->setClipping(true);
-
- avatar_ = new Avatar(nullptr, wm.iconSize);
- avatar_->setLetter(utils::firstChar(roomName_));
- avatar_->resize(wm.iconSize, wm.iconSize);
-
- unreadCountFont_.setPointSizeF(unreadCountFont_.pointSizeF() * 0.8);
- unreadCountFont_.setBold(true);
-
- bubbleDiameter_ = QFontMetrics(unreadCountFont_).averageCharWidth() * 3;
-
- menu_ = new QMenu(this);
- leaveRoom_ = new QAction(tr("Leave room"), this);
- connect(leaveRoom_, &QAction::triggered, this, [this]() { emit leaveRoom(roomId_); });
-
- connect(menu_, &QMenu::aboutToShow, this, [this]() {
- menu_->clear();
- menu_->addAction(leaveRoom_);
-
- menu_->addSection(QIcon(":/icons/icons/ui/tag.png"), tr("Tag room as:"));
-
- auto roomInfo = cache::singleRoomInfo(roomId_.toStdString());
-
- auto tags = ChatPage::instance()->communitiesList()->currentTags();
-
- // add default tag, remove server notice tag
- if (std::find(tags.begin(), tags.end(), "m.favourite") == tags.end())
- tags.push_back("m.favourite");
- if (std::find(tags.begin(), tags.end(), "m.lowpriority") == tags.end())
- tags.push_back("m.lowpriority");
- if (auto it = std::find(tags.begin(), tags.end(), "m.server_notice");
- it != tags.end())
- tags.erase(it);
-
- for (const auto &tag : tags) {
- QString tagName;
- if (tag == "m.favourite")
- tagName = tr("Favourite", "Standard matrix tag for favourites");
- else if (tag == "m.lowpriority")
- tagName =
- tr("Low Priority", "Standard matrix tag for low priority rooms");
- else if (tag == "m.server_notice")
- tagName =
- tr("Server Notice", "Standard matrix tag for server notices");
- else if ((tag.size() > 2 && tag.substr(0, 2) == "u.") ||
- tag.find(".") !=
- std::string::npos) // tag manager creates tags without u., which
- // is wrong, but we still want to display them
- tagName = QString::fromStdString(tag.substr(2));
-
- if (tagName.isEmpty())
- continue;
-
- auto tagAction = menu_->addAction(tagName);
- tagAction->setCheckable(true);
- tagAction->setWhatsThis(tr("Adds or removes the specified tag.",
- "WhatsThis hint for tag menu actions"));
-
- for (const auto &riTag : roomInfo.tags) {
- if (riTag == tag) {
- tagAction->setChecked(true);
- break;
- }
- }
-
- connect(tagAction, &QAction::triggered, this, [this, tag](bool checked) {
- if (checked)
- http::client()->put_tag(
- roomId_.toStdString(),
- tag,
- {},
- [tag](mtx::http::RequestErr err) {
- if (err) {
- nhlog::ui()->error(
- "Failed to add tag: {}, {}",
- tag,
- err->matrix_error.error);
- }
- });
- else
- http::client()->delete_tag(
- roomId_.toStdString(),
- tag,
- [tag](mtx::http::RequestErr err) {
- if (err) {
- nhlog::ui()->error(
- "Failed to delete tag: {}, {}",
- tag,
- err->matrix_error.error);
- }
- });
- });
- }
-
- auto newTagAction = menu_->addAction(tr("New tag...", "Add a new tag to the room"));
- connect(newTagAction, &QAction::triggered, this, [this]() {
- QString tagName =
- QInputDialog::getText(this,
- tr("New Tag", "Tag name prompt title"),
- tr("Tag:", "Tag name prompt"));
- if (tagName.isEmpty())
- return;
-
- std::string tag = "u." + tagName.toStdString();
-
- http::client()->put_tag(
- roomId_.toStdString(), tag, {}, [tag](mtx::http::RequestErr err) {
- if (err) {
- nhlog::ui()->error("Failed to add tag: {}, {}",
- tag,
- err->matrix_error.error);
- }
- });
- });
- });
-}
-
-RoomInfoListItem::RoomInfoListItem(QString room_id, const RoomInfo &info, QWidget *parent)
- : QWidget(parent)
- , roomType_{info.is_invite ? RoomType::Invited : RoomType::Joined}
- , roomId_(std::move(room_id))
- , roomName_{QString::fromStdString(std::move(info.name))}
- , isPressed_(false)
- , unreadMsgCount_(0)
- , unreadHighlightedMsgCount_(0)
-{
- init(parent);
-}
-
-void
-RoomInfoListItem::resizeEvent(QResizeEvent *)
-{
- // Update ripple's clipping path.
- QPainterPath path;
- path.addRect(0, 0, width(), height());
-
- const auto sidebarSizes = splitter::calculateSidebarSizes(QFont{});
-
- if (width() > sidebarSizes.small)
- setToolTip("");
- else
- setToolTip(roomName_);
-
- ripple_overlay_->setClipPath(path);
- ripple_overlay_->setClipping(true);
-}
-
-void
-RoomInfoListItem::paintEvent(QPaintEvent *event)
-{
- Q_UNUSED(event);
-
- QPainter p(this);
- p.setRenderHint(QPainter::TextAntialiasing);
- p.setRenderHint(QPainter::SmoothPixmapTransform);
- p.setRenderHint(QPainter::Antialiasing);
-
- QFontMetrics metrics(QFont{});
-
- QPen titlePen(titleColor_);
- QPen subtitlePen(subtitleColor_);
-
- auto wm = getMetrics(QFont{});
-
- QPixmap pixmap(avatar_->size() * p.device()->devicePixelRatioF());
- pixmap.setDevicePixelRatio(p.device()->devicePixelRatioF());
- if (isPressed_) {
- p.fillRect(rect(), highlightedBackgroundColor_);
- titlePen.setColor(highlightedTitleColor_);
- subtitlePen.setColor(highlightedSubtitleColor_);
- pixmap.fill(highlightedBackgroundColor_);
- } else if (underMouse()) {
- p.fillRect(rect(), hoverBackgroundColor_);
- titlePen.setColor(hoverTitleColor_);
- subtitlePen.setColor(hoverSubtitleColor_);
- pixmap.fill(hoverBackgroundColor_);
- } else {
- p.fillRect(rect(), backgroundColor_);
- titlePen.setColor(titleColor_);
- subtitlePen.setColor(subtitleColor_);
- pixmap.fill(backgroundColor_);
- }
-
- avatar_->render(&pixmap, QPoint(), QRegion(), RenderFlags(DrawChildren));
- p.drawPixmap(QPoint(wm.padding, wm.padding), pixmap);
-
- // Description line with the default font.
- int bottom_y = wm.maxHeight - wm.padding - metrics.ascent() / 2;
-
- const auto sidebarSizes = splitter::calculateSidebarSizes(QFont{});
-
- if (width() > sidebarSizes.small) {
- QFont headingFont;
- headingFont.setWeight(QFont::Medium);
- p.setFont(headingFont);
- p.setPen(titlePen);
-
- QFont tsFont;
- tsFont.setPointSizeF(tsFont.pointSizeF() * 0.9);
-#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
- const int msgStampWidth =
- QFontMetrics(tsFont).width(lastMsgInfo_.descriptiveTime) + 4;
-#else
- const int msgStampWidth =
- QFontMetrics(tsFont).horizontalAdvance(lastMsgInfo_.descriptiveTime) + 4;
-#endif
- // We use the full width of the widget if there is no unread msg bubble.
- const int bottomLineWidthLimit = (unreadMsgCount_ > 0) ? msgStampWidth : 0;
-
- // Name line.
- QFontMetrics fontNameMetrics(headingFont);
- int top_y = 2 * wm.padding + fontNameMetrics.ascent() / 2;
-
- const auto name = metrics.elidedText(
- roomName(),
- Qt::ElideRight,
- (width() - wm.iconSize - 2 * wm.padding - msgStampWidth) * 0.8);
- p.drawText(QPoint(2 * wm.padding + wm.iconSize, top_y), name);
-
- if (roomType_ == RoomType::Joined) {
- p.setFont(QFont{});
- p.setPen(subtitlePen);
-
- int descriptionLimit = std::max(
- 0, width() - 3 * wm.padding - bottomLineWidthLimit - wm.iconSize);
- auto description =
- metrics.elidedText(lastMsgInfo_.body, Qt::ElideRight, descriptionLimit);
- p.drawText(QPoint(2 * wm.padding + wm.iconSize, bottom_y), description);
-
- // We show the last message timestamp.
- p.save();
- if (isPressed_) {
- p.setPen(QPen(highlightedTimestampColor_));
- } else if (underMouse()) {
- p.setPen(QPen(hoverTimestampColor_));
- } else {
- p.setPen(QPen(timestampColor_));
- }
-
- p.setFont(tsFont);
- p.drawText(QPoint(width() - wm.padding - msgStampWidth, top_y),
- lastMsgInfo_.descriptiveTime);
- p.restore();
- } else {
- int btnWidth = (width() - wm.iconSize - 6 * wm.padding) / 2;
-
- acceptBtnRegion_ = QRectF(wm.inviteBtnX, wm.inviteBtnY, btnWidth, 20);
- declineBtnRegion_ = QRectF(
- wm.inviteBtnX + btnWidth + 2 * wm.padding, wm.inviteBtnY, btnWidth, 20);
-
- QPainterPath acceptPath;
- acceptPath.addRoundedRect(acceptBtnRegion_, 10, 10);
-
- p.setPen(Qt::NoPen);
- p.fillPath(acceptPath, btnColor_);
- p.drawPath(acceptPath);
-
- QPainterPath declinePath;
- declinePath.addRoundedRect(declineBtnRegion_, 10, 10);
-
- p.setPen(Qt::NoPen);
- p.fillPath(declinePath, btnColor_);
- p.drawPath(declinePath);
-
- p.setPen(QPen(btnTextColor_));
- p.setFont(QFont{});
- p.drawText(acceptBtnRegion_,
- Qt::AlignCenter,
- metrics.elidedText(tr("Accept"), Qt::ElideRight, btnWidth));
- p.drawText(declineBtnRegion_,
- Qt::AlignCenter,
- metrics.elidedText(tr("Decline"), Qt::ElideRight, btnWidth));
- }
- }
-
- p.setPen(Qt::NoPen);
-
- if (unreadMsgCount_ > 0) {
- QBrush brush;
- brush.setStyle(Qt::SolidPattern);
- if (unreadHighlightedMsgCount_ > 0) {
- brush.setColor(mentionedColor());
- } else {
- brush.setColor(bubbleBgColor());
- }
-
- if (isPressed_)
- brush.setColor(bubbleFgColor());
-
- p.setBrush(brush);
- p.setPen(Qt::NoPen);
- p.setFont(unreadCountFont_);
-
- // Extra space on the x-axis to accomodate the extra character space
- // inside the bubble.
- const int x_width = unreadMsgCount_ > MaxUnreadCountDisplayed
- ? QFontMetrics(p.font()).averageCharWidth()
- : 0;
-
- QRectF r(width() - bubbleDiameter_ - wm.padding - x_width,
- bottom_y - bubbleDiameter_ / 2 - 5,
- bubbleDiameter_ + x_width,
- bubbleDiameter_);
-
- if (width() == sidebarSizes.small)
- r = QRectF(width() - bubbleDiameter_ - 5,
- height() - bubbleDiameter_ - 5,
- bubbleDiameter_ + x_width,
- bubbleDiameter_);
-
- p.setPen(Qt::NoPen);
- p.drawEllipse(r);
-
- p.setPen(QPen(bubbleFgColor()));
-
- if (isPressed_)
- p.setPen(QPen(bubbleBgColor()));
-
- auto countTxt = unreadMsgCount_ > MaxUnreadCountDisplayed
- ? QString("99+")
- : QString::number(unreadMsgCount_);
-
- p.setBrush(Qt::NoBrush);
- p.drawText(r.translated(0, -0.5), Qt::AlignCenter, countTxt);
- }
-
- if (!isPressed_ && hasUnreadMessages_) {
- QPen pen;
- pen.setWidth(wm.unreadLineWidth);
- pen.setColor(highlightedBackgroundColor_);
-
- p.setPen(pen);
- p.drawLine(0, wm.unreadLineOffset, 0, height() - wm.unreadLineOffset);
- }
-}
-
-void
-RoomInfoListItem::updateUnreadMessageCount(int count, int highlightedCount)
-{
- unreadMsgCount_ = count;
- unreadHighlightedMsgCount_ = highlightedCount;
- update();
-}
-
-enum NotificationImportance : short
-{
- ImportanceDisabled = -1,
- AllEventsRead = 0,
- NewMessage = 1,
- NewMentions = 2,
- Invite = 3
-};
-
-short int
-RoomInfoListItem::calculateImportance() const
-{
- // Returns the degree of importance of the unread messages in the room.
- // If sorting by importance is disabled in settings, this only ever
- // returns ImportanceDisabled or Invite
- if (isInvite()) {
- return Invite;
- } else if (!ChatPage::instance()->userSettings()->sortByImportance()) {
- return ImportanceDisabled;
- } else if (unreadHighlightedMsgCount_) {
- return NewMentions;
- } else if (unreadMsgCount_) {
- return NewMessage;
- } else {
- return AllEventsRead;
- }
-}
-
-void
-RoomInfoListItem::setPressedState(bool state)
-{
- if (isPressed_ != state) {
- isPressed_ = state;
- update();
- }
-}
-
-void
-RoomInfoListItem::contextMenuEvent(QContextMenuEvent *event)
-{
- Q_UNUSED(event);
-
- if (roomType_ == RoomType::Invited)
- return;
-
- menu_->popup(event->globalPos());
-}
-
-void
-RoomInfoListItem::mousePressEvent(QMouseEvent *event)
-{
- if (event->buttons() == Qt::RightButton) {
- QWidget::mousePressEvent(event);
- return;
- } else if (event->buttons() == Qt::LeftButton) {
- if (roomType_ == RoomType::Invited) {
- const auto point = event->pos();
-
- if (acceptBtnRegion_.contains(point))
- emit acceptInvite(roomId_);
-
- if (declineBtnRegion_.contains(point))
- emit declineInvite(roomId_);
-
- return;
- }
-
- emit clicked(roomId_);
-
- setPressedState(true);
-
- // Ripple on mouse position by default.
- QPoint pos = event->pos();
- qreal radiusEndValue = static_cast<qreal>(width()) / 3;
-
- Ripple *ripple = new Ripple(pos);
-
- ripple->setRadiusEndValue(radiusEndValue);
- ripple->setOpacityStartValue(0.15);
- ripple->setColor(QColor("white"));
- ripple->radiusAnimation()->setDuration(200);
- ripple->opacityAnimation()->setDuration(400);
-
- ripple_overlay_->addRipple(ripple);
- }
-}
-
-void
-RoomInfoListItem::setAvatar(const QString &avatar_url)
-{
- if (avatar_url.isEmpty())
- avatar_->setLetter(utils::firstChar(roomName_));
- else
- avatar_->setImage(avatar_url);
-}
-
-void
-RoomInfoListItem::setDescriptionMessage(const DescInfo &info)
-{
- lastMsgInfo_ = info;
- update();
-}
diff --git a/src/RoomInfoListItem.h b/src/RoomInfoListItem.h
deleted file mode 100644
index a5e0009e..00000000
--- a/src/RoomInfoListItem.h
+++ /dev/null
@@ -1,210 +0,0 @@
-// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#pragma once
-
-#include <QAction>
-#include <QDateTime>
-#include <QSharedPointer>
-#include <QWidget>
-
-#include <mtx/responses/sync.hpp>
-
-#include "CacheStructs.h"
-#include "UserSettingsPage.h"
-#include "ui/Avatar.h"
-
-class QMenu;
-class RippleOverlay;
-
-class RoomInfoListItem : public QWidget
-{
- Q_OBJECT
- Q_PROPERTY(QColor highlightedBackgroundColor READ highlightedBackgroundColor WRITE
- setHighlightedBackgroundColor)
- Q_PROPERTY(
- QColor hoverBackgroundColor READ hoverBackgroundColor WRITE setHoverBackgroundColor)
- Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)
-
- Q_PROPERTY(QColor bubbleBgColor READ bubbleBgColor WRITE setBubbleBgColor)
- Q_PROPERTY(QColor bubbleFgColor READ bubbleFgColor WRITE setBubbleFgColor)
-
- Q_PROPERTY(QColor titleColor READ titleColor WRITE setTitleColor)
- Q_PROPERTY(QColor subtitleColor READ subtitleColor WRITE setSubtitleColor)
-
- Q_PROPERTY(QColor timestampColor READ timestampColor WRITE setTimestampColor)
- Q_PROPERTY(QColor highlightedTimestampColor READ highlightedTimestampColor WRITE
- setHighlightedTimestampColor)
- Q_PROPERTY(QColor hoverTimestampColor READ hoverTimestampColor WRITE setHoverTimestampColor)
-
- Q_PROPERTY(
- QColor highlightedTitleColor READ highlightedTitleColor WRITE setHighlightedTitleColor)
- Q_PROPERTY(QColor highlightedSubtitleColor READ highlightedSubtitleColor WRITE
- setHighlightedSubtitleColor)
-
- Q_PROPERTY(QColor hoverTitleColor READ hoverTitleColor WRITE setHoverTitleColor)
- Q_PROPERTY(QColor hoverSubtitleColor READ hoverSubtitleColor WRITE setHoverSubtitleColor)
-
- Q_PROPERTY(QColor mentionedColor READ mentionedColor WRITE setMentionedColor)
- Q_PROPERTY(QColor btnColor READ btnColor WRITE setBtnColor)
- Q_PROPERTY(QColor btnTextColor READ btnTextColor WRITE setBtnTextColor)
-
-public:
- RoomInfoListItem(QString room_id, const RoomInfo &info, QWidget *parent = nullptr);
-
- void updateUnreadMessageCount(int count, int highlightedCount);
- void clearUnreadMessageCount() { updateUnreadMessageCount(0, 0); };
-
- short int calculateImportance() const;
-
- QString roomId() { return roomId_; }
- bool isPressed() const { return isPressed_; }
- int unreadMessageCount() const { return unreadMsgCount_; }
-
- void setAvatar(const QString &avatar_url);
- void setDescriptionMessage(const DescInfo &info);
- DescInfo lastMessageInfo() const { return lastMsgInfo_; }
-
- QColor highlightedBackgroundColor() const { return highlightedBackgroundColor_; }
- QColor hoverBackgroundColor() const { return hoverBackgroundColor_; }
- QColor hoverTitleColor() const { return hoverTitleColor_; }
- QColor hoverSubtitleColor() const { return hoverSubtitleColor_; }
- QColor hoverTimestampColor() const { return hoverTimestampColor_; }
- QColor backgroundColor() const { return backgroundColor_; }
-
- QColor highlightedTitleColor() const { return highlightedTitleColor_; }
- QColor highlightedSubtitleColor() const { return highlightedSubtitleColor_; }
- QColor highlightedTimestampColor() const { return highlightedTimestampColor_; }
-
- QColor titleColor() const { return titleColor_; }
- QColor subtitleColor() const { return subtitleColor_; }
- QColor timestampColor() const { return timestampColor_; }
- QColor btnColor() const { return btnColor_; }
- QColor btnTextColor() const { return btnTextColor_; }
-
- QColor bubbleFgColor() const { return bubbleFgColor_; }
- QColor bubbleBgColor() const { return bubbleBgColor_; }
- QColor mentionedColor() const { return mentionedFontColor_; }
-
- void setHighlightedBackgroundColor(QColor &color) { highlightedBackgroundColor_ = color; }
- void setHoverBackgroundColor(QColor &color) { hoverBackgroundColor_ = color; }
- void setHoverSubtitleColor(QColor &color) { hoverSubtitleColor_ = color; }
- void setHoverTitleColor(QColor &color) { hoverTitleColor_ = color; }
- void setHoverTimestampColor(QColor &color) { hoverTimestampColor_ = color; }
- void setBackgroundColor(QColor &color) { backgroundColor_ = color; }
- void setTimestampColor(QColor &color) { timestampColor_ = color; }
-
- void setHighlightedTitleColor(QColor &color) { highlightedTitleColor_ = color; }
- void setHighlightedSubtitleColor(QColor &color) { highlightedSubtitleColor_ = color; }
- void setHighlightedTimestampColor(QColor &color) { highlightedTimestampColor_ = color; }
-
- void setTitleColor(QColor &color) { titleColor_ = color; }
- void setSubtitleColor(QColor &color) { subtitleColor_ = color; }
-
- void setBtnColor(QColor &color) { btnColor_ = color; }
- void setBtnTextColor(QColor &color) { btnTextColor_ = color; }
-
- void setBubbleFgColor(QColor &color) { bubbleFgColor_ = color; }
- void setBubbleBgColor(QColor &color) { bubbleBgColor_ = color; }
- void setMentionedColor(QColor &color) { mentionedFontColor_ = color; }
-
- void setRoomName(const QString &name) { roomName_ = name; }
- void setRoomType(bool isInvite)
- {
- if (isInvite)
- roomType_ = RoomType::Invited;
- else
- roomType_ = RoomType::Joined;
- }
-
- bool isInvite() const { return roomType_ == RoomType::Invited; }
- void setReadState(bool hasUnreadMessages)
- {
- if (hasUnreadMessages_ != hasUnreadMessages) {
- hasUnreadMessages_ = hasUnreadMessages;
- update();
- }
- }
-
-signals:
- void clicked(const QString &room_id);
- void leaveRoom(const QString &room_id);
- void acceptInvite(const QString &room_id);
- void declineInvite(const QString &room_id);
-
-public slots:
- void setPressedState(bool state);
-
-protected:
- void mousePressEvent(QMouseEvent *event) override;
- void paintEvent(QPaintEvent *event) override;
- void resizeEvent(QResizeEvent *event) override;
- void contextMenuEvent(QContextMenuEvent *event) override;
-
-private:
- void init(QWidget *parent);
- QString roomName() { return roomName_; }
-
- RippleOverlay *ripple_overlay_;
- Avatar *avatar_;
-
- enum class RoomType
- {
- Joined,
- Invited,
- };
-
- RoomType roomType_ = RoomType::Joined;
-
- // State information for the invited rooms.
- mtx::responses::InvitedRoom invitedRoom_;
-
- QString roomId_;
- QString roomName_;
-
- DescInfo lastMsgInfo_;
-
- QMenu *menu_;
- QAction *leaveRoom_;
-
- bool isPressed_ = false;
- bool hasUnreadMessages_ = true;
-
- int unreadMsgCount_ = 0;
- int unreadHighlightedMsgCount_ = 0;
-
- QColor highlightedBackgroundColor_;
- QColor hoverBackgroundColor_;
- QColor backgroundColor_;
-
- QColor highlightedTitleColor_;
- QColor highlightedSubtitleColor_;
-
- QColor titleColor_;
- QColor subtitleColor_;
-
- QColor hoverTitleColor_;
- QColor hoverSubtitleColor_;
-
- QColor btnColor_;
- QColor btnTextColor_;
-
- QRectF acceptBtnRegion_;
- QRectF declineBtnRegion_;
-
- // Fonts
- QColor mentionedFontColor_;
- QFont unreadCountFont_;
- int bubbleDiameter_;
-
- QColor timestampColor_;
- QColor highlightedTimestampColor_;
- QColor hoverTimestampColor_;
-
- QColor bubbleBgColor_;
- QColor bubbleFgColor_;
-
- friend struct room_sort;
-};
diff --git a/src/RoomList.cpp b/src/RoomList.cpp
deleted file mode 100644
index 5839c4a0..00000000
--- a/src/RoomList.cpp
+++ /dev/null
@@ -1,535 +0,0 @@
-// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include <limits>
-#include <set>
-
-#include <QObject>
-#include <QPainter>
-#include <QScroller>
-#include <QStyle>
-#include <QStyleOption>
-#include <QTimer>
-
-#include "Logging.h"
-#include "MainWindow.h"
-#include "RoomInfoListItem.h"
-#include "RoomList.h"
-#include "UserSettingsPage.h"
-#include "Utils.h"
-#include "ui/OverlayModal.h"
-
-RoomList::RoomList(QSharedPointer<UserSettings> userSettings, QWidget *parent)
- : QWidget(parent)
-{
- topLayout_ = new QVBoxLayout(this);
- topLayout_->setSpacing(0);
- topLayout_->setMargin(0);
-
- scrollArea_ = new QScrollArea(this);
- scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- scrollArea_->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
- scrollArea_->setWidgetResizable(true);
- scrollArea_->setAlignment(Qt::AlignLeading | Qt::AlignTop | Qt::AlignVCenter);
- scrollArea_->setAttribute(Qt::WA_AcceptTouchEvents);
-
- QScroller::grabGesture(scrollArea_, QScroller::TouchGesture);
- QScroller::grabGesture(scrollArea_, QScroller::LeftMouseButtonGesture);
-
-// The scrollbar on macOS will hide itself when not active so it won't interfere
-// with the content.
-#if not defined(Q_OS_MAC)
- scrollArea_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-#endif
-
- scrollAreaContents_ = new QWidget(this);
- scrollAreaContents_->setObjectName("roomlist_area");
-
- contentsLayout_ = new QVBoxLayout(scrollAreaContents_);
- contentsLayout_->setAlignment(Qt::AlignTop);
- contentsLayout_->setSpacing(0);
- contentsLayout_->setMargin(0);
-
- scrollArea_->setWidget(scrollAreaContents_);
- topLayout_->addWidget(scrollArea_);
-
- connect(this, &RoomList::updateRoomAvatarCb, this, &RoomList::updateRoomAvatar);
- connect(userSettings.data(),
- &UserSettings::roomSortingChanged,
- this,
- &RoomList::sortRoomsByLastMessage);
-}
-
-void
-RoomList::addRoom(const QString &room_id, const RoomInfo &info)
-{
- auto room_item = new RoomInfoListItem(room_id, info, scrollArea_);
- room_item->setRoomName(QString::fromStdString(std::move(info.name)));
-
- connect(room_item, &RoomInfoListItem::clicked, this, &RoomList::highlightSelectedRoom);
- connect(room_item, &RoomInfoListItem::leaveRoom, this, [](const QString &room_id) {
- MainWindow::instance()->openLeaveRoomDialog(room_id);
- });
-
- QSharedPointer<RoomInfoListItem> roomWidget(room_item, &QObject::deleteLater);
- rooms_.emplace(room_id, roomWidget);
- rooms_sort_cache_.push_back(roomWidget);
-
- if (!info.avatar_url.empty())
- updateAvatar(room_id, QString::fromStdString(info.avatar_url));
-
- int pos = contentsLayout_->count() - 1;
- contentsLayout_->insertWidget(pos, room_item);
-}
-
-void
-RoomList::updateAvatar(const QString &room_id, const QString &url)
-{
- emit updateRoomAvatarCb(room_id, url);
-}
-
-void
-RoomList::removeRoom(const QString &room_id, bool reset)
-{
- auto roomIt = rooms_.find(room_id);
- if (roomIt == rooms_.end()) {
- return;
- }
-
- for (auto roomSortIt = rooms_sort_cache_.begin(); roomSortIt != rooms_sort_cache_.end();
- ++roomSortIt) {
- if (roomIt->second == *roomSortIt) {
- rooms_sort_cache_.erase(roomSortIt);
- break;
- }
- }
- rooms_.erase(room_id);
-
- if (rooms_.empty() || !reset)
- return;
-
- auto room = firstRoom();
-
- if (room.second.isNull())
- return;
-
- room.second->setPressedState(true);
- emit roomChanged(room.first);
-}
-
-void
-RoomList::updateUnreadMessageCount(const QString &roomid, int count, int highlightedCount)
-{
- if (!roomExists(roomid)) {
- nhlog::ui()->warn("updateUnreadMessageCount: unknown room_id {}",
- roomid.toStdString());
- return;
- }
-
- rooms_[roomid]->updateUnreadMessageCount(count, highlightedCount);
-
- calculateUnreadMessageCount();
-
- sortRoomsByLastMessage();
-}
-
-void
-RoomList::calculateUnreadMessageCount()
-{
- int total_unread_msgs = 0;
-
- for (const auto &room : rooms_) {
- if (!room.second.isNull())
- total_unread_msgs += room.second->unreadMessageCount();
- }
-
- emit totalUnreadMessageCountUpdated(total_unread_msgs);
-}
-
-void
-RoomList::initialize(const QMap<QString, RoomInfo> &info)
-{
- nhlog::ui()->info("initialize room list");
-
- rooms_.clear();
-
- // prevent flickering and save time sorting over and over again
- setUpdatesEnabled(false);
- for (auto it = info.begin(); it != info.end(); it++) {
- if (it.value().is_invite)
- addInvitedRoom(it.key(), it.value());
- else
- addRoom(it.key(), it.value());
- }
-
- for (auto it = info.begin(); it != info.end(); it++)
- updateRoomDescription(it.key(), it.value().msgInfo);
-
- setUpdatesEnabled(true);
-
- if (rooms_.empty())
- return;
-
- sortRoomsByLastMessage();
-
- auto room = firstRoom();
- if (room.second.isNull())
- return;
-
- room.second->setPressedState(true);
- emit roomChanged(room.first);
-}
-
-void
-RoomList::cleanupInvites(const QHash<QString, RoomInfo> &invites)
-{
- if (invites.size() == 0)
- return;
-
- utils::erase_if(rooms_, [invites](auto &room) {
- auto room_id = room.first;
- auto item = room.second;
-
- if (!item)
- return false;
-
- return item->isInvite() && (invites.find(room_id) == invites.end());
- });
-}
-
-void
-RoomList::sync(const std::map<QString, RoomInfo> &info)
-
-{
- for (const auto &room : info)
- updateRoom(room.first, room.second);
-
- if (!info.empty())
- sortRoomsByLastMessage();
-}
-
-void
-RoomList::highlightSelectedRoom(const QString &room_id)
-{
- emit roomChanged(room_id);
-
- if (!roomExists(room_id)) {
- nhlog::ui()->warn("roomlist: clicked unknown room_id");
- return;
- }
-
- for (auto const &room : rooms_) {
- if (room.second.isNull())
- continue;
-
- if (room.first != room_id) {
- room.second->setPressedState(false);
- } else {
- room.second->setPressedState(true);
- scrollArea_->ensureWidgetVisible(room.second.data());
- }
- }
-
- selectedRoom_ = room_id;
-}
-
-void
-RoomList::nextRoom()
-{
- for (int ii = 0; ii < contentsLayout_->count() - 1; ++ii) {
- auto room = qobject_cast<RoomInfoListItem *>(contentsLayout_->itemAt(ii)->widget());
-
- if (!room)
- continue;
-
- if (room->roomId() == selectedRoom_) {
- auto nextRoom = qobject_cast<RoomInfoListItem *>(
- contentsLayout_->itemAt(ii + 1)->widget());
-
- // Not a room message.
- if (!nextRoom || nextRoom->isInvite())
- return;
-
- emit roomChanged(nextRoom->roomId());
- if (!roomExists(nextRoom->roomId())) {
- nhlog::ui()->warn("roomlist: clicked unknown room_id");
- return;
- }
-
- room->setPressedState(false);
- nextRoom->setPressedState(true);
-
- scrollArea_->ensureWidgetVisible(nextRoom);
- selectedRoom_ = nextRoom->roomId();
- return;
- }
- }
-}
-
-void
-RoomList::previousRoom()
-{
- for (int ii = 1; ii < contentsLayout_->count(); ++ii) {
- auto room = qobject_cast<RoomInfoListItem *>(contentsLayout_->itemAt(ii)->widget());
-
- if (!room)
- continue;
-
- if (room->roomId() == selectedRoom_) {
- auto nextRoom = qobject_cast<RoomInfoListItem *>(
- contentsLayout_->itemAt(ii - 1)->widget());
-
- // Not a room message.
- if (!nextRoom || nextRoom->isInvite())
- return;
-
- emit roomChanged(nextRoom->roomId());
- if (!roomExists(nextRoom->roomId())) {
- nhlog::ui()->warn("roomlist: clicked unknown room_id");
- return;
- }
-
- room->setPressedState(false);
- nextRoom->setPressedState(true);
-
- scrollArea_->ensureWidgetVisible(nextRoom);
- selectedRoom_ = nextRoom->roomId();
- return;
- }
- }
-}
-
-void
-RoomList::updateRoomAvatar(const QString &roomid, const QString &img)
-{
- if (!roomExists(roomid)) {
- return;
- }
-
- rooms_[roomid]->setAvatar(img);
-
- // Used to inform other widgets for the new image data.
- emit roomAvatarChanged(roomid, img);
-}
-
-void
-RoomList::updateRoomDescription(const QString &roomid, const DescInfo &info)
-{
- if (!roomExists(roomid)) {
- return;
- }
-
- rooms_[roomid]->setDescriptionMessage(info);
-
- if (underMouse()) {
- // When the user hover out of the roomlist a sort will be triggered.
- isSortPending_ = true;
- return;
- }
-
- isSortPending_ = false;
-
- emit sortRoomsByLastMessage();
-}
-
-struct room_sort
-{
- bool operator()(const QSharedPointer<RoomInfoListItem> &a,
- const QSharedPointer<RoomInfoListItem> &b) const
- {
- // Sort by "importance" (i.e. invites before mentions before
- // notifs before new events before old events), then secondly
- // by recency.
-
- // Checking importance first
- const auto a_importance = a->calculateImportance();
- const auto b_importance = b->calculateImportance();
- if (a_importance != b_importance) {
- return a_importance > b_importance;
- }
-
- // Now sort by recency
- // Zero if empty, otherwise the time that the event occured
- const uint64_t a_recency =
- a->lastMsgInfo_.userid.isEmpty() ? 0 : a->lastMsgInfo_.timestamp;
- const uint64_t b_recency =
- b->lastMsgInfo_.userid.isEmpty() ? 0 : b->lastMsgInfo_.timestamp;
- return a_recency > b_recency;
- }
-};
-
-void
-RoomList::sortRoomsByLastMessage()
-{
- isSortPending_ = false;
-
- std::stable_sort(begin(rooms_sort_cache_), end(rooms_sort_cache_), room_sort{});
-
- int newIndex = 0;
- for (const auto &roomWidget : rooms_sort_cache_) {
- const auto currentIndex = contentsLayout_->indexOf(roomWidget.data());
-
- if (currentIndex != newIndex) {
- contentsLayout_->removeWidget(roomWidget.data());
- contentsLayout_->insertWidget(newIndex, roomWidget.data());
- }
- newIndex++;
- }
-}
-
-void
-RoomList::leaveEvent(QEvent *event)
-{
- if (isSortPending_)
- QTimer::singleShot(700, this, &RoomList::sortRoomsByLastMessage);
-
- QWidget::leaveEvent(event);
-}
-
-void
-RoomList::closeJoinRoomDialog(bool isJoining, QString roomAlias)
-{
- joinRoomModal_->hide();
-
- if (isJoining)
- emit joinRoom(roomAlias);
-}
-
-void
-RoomList::removeFilter(const std::set<QString> &roomsToHide)
-{
- setUpdatesEnabled(false);
- for (int i = 0; i < contentsLayout_->count(); i++) {
- auto widget =
- qobject_cast<RoomInfoListItem *>(contentsLayout_->itemAt(i)->widget());
- if (widget) {
- if (roomsToHide.find(widget->roomId()) == roomsToHide.end())
- widget->show();
- else
- widget->hide();
- }
- }
- setUpdatesEnabled(true);
-}
-
-void
-RoomList::applyFilter(const std::set<QString> &filter)
-{
- // Disabling paint updates will resolve issues with screen flickering on big room lists.
- setUpdatesEnabled(false);
-
- for (int i = 0; i < contentsLayout_->count(); i++) {
- // If filter contains the room for the current RoomInfoListItem,
- // show the list item, otherwise hide it
- auto listitem =
- qobject_cast<RoomInfoListItem *>(contentsLayout_->itemAt(i)->widget());
-
- if (!listitem)
- continue;
-
- if (filter.find(listitem->roomId()) != filter.end())
- listitem->show();
- else
- listitem->hide();
- }
-
- setUpdatesEnabled(true);
-
- // If the already selected room is part of the group, make sure it's visible.
- if (!selectedRoom_.isEmpty() && (filter.find(selectedRoom_) != filter.end()))
- return;
-
- selectFirstVisibleRoom();
-}
-
-void
-RoomList::selectFirstVisibleRoom()
-{
- for (int i = 0; i < contentsLayout_->count(); i++) {
- auto item = qobject_cast<RoomInfoListItem *>(contentsLayout_->itemAt(i)->widget());
-
- if (item && item->isVisible()) {
- highlightSelectedRoom(item->roomId());
- break;
- }
- }
-}
-
-void
-RoomList::paintEvent(QPaintEvent *)
-{
- QStyleOption opt;
- opt.init(this);
- QPainter p(this);
- style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
-}
-
-void
-RoomList::updateRoom(const QString &room_id, const RoomInfo &info)
-{
- if (!roomExists(room_id)) {
- if (info.is_invite)
- addInvitedRoom(room_id, info);
- else
- addRoom(room_id, info);
-
- return;
- }
-
- auto room = rooms_[room_id];
- updateAvatar(room_id, QString::fromStdString(info.avatar_url));
- room->setRoomName(QString::fromStdString(info.name));
- room->setRoomType(info.is_invite);
- room->update();
-}
-
-void
-RoomList::addInvitedRoom(const QString &room_id, const RoomInfo &info)
-{
- auto room_item = new RoomInfoListItem(room_id, info, scrollArea_);
-
- connect(room_item, &RoomInfoListItem::acceptInvite, this, &RoomList::acceptInvite);
- connect(room_item, &RoomInfoListItem::declineInvite, this, &RoomList::declineInvite);
-
- QSharedPointer<RoomInfoListItem> roomWidget(room_item);
- rooms_.emplace(room_id, roomWidget);
- rooms_sort_cache_.push_back(roomWidget);
-
- updateAvatar(room_id, QString::fromStdString(info.avatar_url));
-
- int pos = contentsLayout_->count() - 1;
- contentsLayout_->insertWidget(pos, room_item);
-}
-
-std::pair<QString, QSharedPointer<RoomInfoListItem>>
-RoomList::firstRoom() const
-{
- for (int i = 0; i < contentsLayout_->count(); i++) {
- auto item = qobject_cast<RoomInfoListItem *>(contentsLayout_->itemAt(i)->widget());
-
- if (item) {
- auto topRoom = rooms_.find(item->roomId());
- if (topRoom != rooms_.end()) {
- return std::pair<QString, QSharedPointer<RoomInfoListItem>>(
- item->roomId(), topRoom->second);
- }
- }
- }
-
- return {};
-}
-
-void
-RoomList::updateReadStatus(const std::map<QString, bool> &status)
-{
- for (const auto &room : status) {
- if (roomExists(room.first)) {
- auto item = rooms_.at(room.first);
-
- if (item)
- item->setReadState(room.second);
- }
- }
-}
diff --git a/src/RoomList.h b/src/RoomList.h
deleted file mode 100644
index af792fd7..00000000
--- a/src/RoomList.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#pragma once
-
-#include <QPushButton>
-#include <QScrollArea>
-#include <QSharedPointer>
-#include <QVBoxLayout>
-#include <QWidget>
-
-#include <set>
-
-#include "CacheStructs.h"
-#include "UserSettingsPage.h"
-
-class LeaveRoomDialog;
-class OverlayModal;
-class RoomInfoListItem;
-class Sync;
-struct DescInfo;
-struct RoomInfo;
-
-class RoomList : public QWidget
-{
- Q_OBJECT
-
-public:
- explicit RoomList(QSharedPointer<UserSettings> userSettings, QWidget *parent = nullptr);
-
- void initialize(const QMap<QString, RoomInfo> &info);
- void sync(const std::map<QString, RoomInfo> &info);
-
- void clear()
- {
- rooms_.clear();
- rooms_sort_cache_.clear();
- };
- void updateAvatar(const QString &room_id, const QString &url);
-
- void addRoom(const QString &room_id, const RoomInfo &info);
- void addInvitedRoom(const QString &room_id, const RoomInfo &info);
- void removeRoom(const QString &room_id, bool reset);
- //! Hide rooms that are not present in the given filter.
- void applyFilter(const std::set<QString> &rooms);
- //! Show all the available rooms.
- void removeFilter(const std::set<QString> &roomsToHide);
- void updateRoom(const QString &room_id, const RoomInfo &info);
- void cleanupInvites(const QHash<QString, RoomInfo> &invites);
-
-signals:
- void roomChanged(const QString &room_id);
- void totalUnreadMessageCountUpdated(int count);
- void acceptInvite(const QString &room_id);
- void declineInvite(const QString &room_id);
- void roomAvatarChanged(const QString &room_id, const QString &img);
- void joinRoom(const QString &room_id);
- void updateRoomAvatarCb(const QString &room_id, const QString &img);
-
-public slots:
- void updateRoomAvatar(const QString &roomid, const QString &img);
- void highlightSelectedRoom(const QString &room_id);
- void updateUnreadMessageCount(const QString &roomid, int count, int highlightedCount);
- void updateRoomDescription(const QString &roomid, const DescInfo &info);
- void closeJoinRoomDialog(bool isJoining, QString roomAlias);
- void updateReadStatus(const std::map<QString, bool> &status);
- void nextRoom();
- void previousRoom();
-
-protected:
- void paintEvent(QPaintEvent *event) override;
- void leaveEvent(QEvent *event) override;
-
-private slots:
- void sortRoomsByLastMessage();
-
-private:
- //! Return the first non-null room.
- std::pair<QString, QSharedPointer<RoomInfoListItem>> firstRoom() const;
- void calculateUnreadMessageCount();
- bool roomExists(const QString &room_id) { return rooms_.find(room_id) != rooms_.end(); }
- //! Select the first visible room in the room list.
- void selectFirstVisibleRoom();
-
- QVBoxLayout *topLayout_;
- QVBoxLayout *contentsLayout_;
- QScrollArea *scrollArea_;
- QWidget *scrollAreaContents_;
-
- QPushButton *joinRoomButton_;
-
- OverlayModal *joinRoomModal_;
-
- std::map<QString, QSharedPointer<RoomInfoListItem>> rooms_;
- std::vector<QSharedPointer<RoomInfoListItem>> rooms_sort_cache_;
- QString selectedRoom_;
-
- bool isSortPending_ = false;
-};
diff --git a/src/popups/PopupItem.cpp b/src/popups/PopupItem.cpp
deleted file mode 100644
index 2daa6143..00000000
--- a/src/popups/PopupItem.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include <QLabel>
-#include <QPaintEvent>
-#include <QPainter>
-#include <QStyleOption>
-
-#include "../Utils.h"
-#include "../ui/Avatar.h"
-#include "PopupItem.h"
-
-constexpr int PopupHMargin = 4;
-constexpr int PopupItemMargin = 3;
-
-PopupItem::PopupItem(QWidget *parent)
- : QWidget(parent)
- , avatar_{new Avatar(this, conf::popup::avatar)}
- , hovering_{false}
-{
- setMouseTracking(true);
- setAttribute(Qt::WA_Hover);
-
- topLayout_ = new QHBoxLayout(this);
- topLayout_->setContentsMargins(
- PopupHMargin, PopupItemMargin, PopupHMargin, PopupItemMargin);
-
- setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
-}
-
-void
-PopupItem::paintEvent(QPaintEvent *)
-{
- QStyleOption opt;
- opt.init(this);
- QPainter p(this);
- style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
-
- if (underMouse() || hovering_)
- p.fillRect(rect(), hoverColor_);
-}
-
-RoomItem::RoomItem(QWidget *parent, const RoomSearchResult &res)
- : PopupItem(parent)
- , roomId_{QString::fromStdString(res.room_id)}
-{
- auto name = QFontMetrics(QFont()).elidedText(
- QString::fromStdString(res.info.name), Qt::ElideRight, parentWidget()->width() - 10);
-
- avatar_->setLetter(utils::firstChar(name));
-
- roomName_ = new QLabel(name, this);
- roomName_->setMargin(0);
-
- topLayout_->addWidget(avatar_);
- topLayout_->addWidget(roomName_, 1);
-
- if (!res.info.avatar_url.empty())
- avatar_->setImage(QString::fromStdString(res.info.avatar_url));
-}
-
-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 there is not an avatar set for the room, we want to at least show the letter
- // correctly!
- avatar_->setLetter(utils::firstChar(name));
- if (!result.info.avatar_url.empty())
- avatar_->setImage(QString::fromStdString(result.info.avatar_url));
-}
-
-void
-RoomItem::mousePressEvent(QMouseEvent *event)
-{
- if (event->buttons() != Qt::RightButton)
- emit clicked(selectedText());
-
- QWidget::mousePressEvent(event);
-}
diff --git a/src/popups/PopupItem.h b/src/popups/PopupItem.h
deleted file mode 100644
index fc24915e..00000000
--- a/src/popups/PopupItem.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#pragma once
-
-#include <QWidget>
-
-#include "../AvatarProvider.h"
-#include "../ChatPage.h"
-
-class Avatar;
-struct SearchResult;
-class QLabel;
-class QHBoxLayout;
-
-class PopupItem : public QWidget
-{
- Q_OBJECT
-
- Q_PROPERTY(QColor hoverColor READ hoverColor WRITE setHoverColor)
- Q_PROPERTY(bool hovering READ hovering WRITE setHovering)
-
-public:
- PopupItem(QWidget *parent);
-
- QString selectedText() const { return QString(); }
- QColor hoverColor() const { return hoverColor_; }
- void setHoverColor(QColor &color) { hoverColor_ = color; }
-
- bool hovering() const { return hovering_; }
- void setHovering(const bool hover) { hovering_ = hover; };
-
-protected:
- void paintEvent(QPaintEvent *event) override;
-
-signals:
- void clicked(const QString &text);
-
-protected:
- QHBoxLayout *topLayout_;
- Avatar *avatar_;
- QColor hoverColor_;
-
- //! Set if the item is currently being
- //! hovered during tab completion (cycling).
- bool hovering_;
-};
-
-class RoomItem : public PopupItem
-{
- Q_OBJECT
-
-public:
- RoomItem(QWidget *parent, const RoomSearchResult &res);
- QString selectedText() const { return roomId_; }
- void updateItem(const RoomSearchResult &res);
-
-protected:
- void mousePressEvent(QMouseEvent *event) override;
-
-private:
- QLabel *roomName_;
- QString roomId_;
- RoomSearchResult info_;
-};
diff --git a/src/popups/SuggestionsPopup.cpp b/src/popups/SuggestionsPopup.cpp
deleted file mode 100644
index 7b545d61..00000000
--- a/src/popups/SuggestionsPopup.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include <QPaintEvent>
-#include <QPainter>
-#include <QStyleOption>
-
-#include "../Config.h"
-#include "../Utils.h"
-#include "../ui/Avatar.h"
-#include "../ui/DropShadow.h"
-#include "ChatPage.h"
-#include "PopupItem.h"
-#include "SuggestionsPopup.h"
-
-SuggestionsPopup::SuggestionsPopup(QWidget *parent)
- : QWidget(parent)
-{
- setAttribute(Qt::WA_ShowWithoutActivating, true);
- setWindowFlags(Qt::ToolTip | Qt::NoDropShadowWindowHint);
-
- layout_ = new QVBoxLayout(this);
- layout_->setMargin(0);
- layout_->setSpacing(0);
-}
-
-QString
-SuggestionsPopup::displayName(QString room, QString user)
-{
- return cache::displayName(room, user);
-}
-
-void
-SuggestionsPopup::addRooms(const std::vector<RoomSearchResult> &rooms)
-{
- if (rooms.empty()) {
- hide();
- return;
- }
-
- const int layoutCount = (int)layout_->count();
- const int roomCount = (int)rooms.size();
-
- // Remove the extra widgets from the layout.
- if (roomCount < layoutCount)
- removeLayoutItemsAfter(roomCount - 1);
-
- for (int 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();
- adjustSize();
-
- resize(geometry().width(), 40 * (int)rooms.size());
-
- selectNextSuggestion();
-}
-
-void
-SuggestionsPopup::hoverSelection()
-{
- resetHovering();
- setHovering(selectedItem_);
- update();
-}
-
-void
-SuggestionsPopup::selectHoveredSuggestion()
-{
- const auto item = layout_->itemAt(selectedItem_);
- if (!item)
- return;
-
- const auto &widget = qobject_cast<RoomItem *>(item->widget());
- emit itemSelected(displayName(ChatPage::instance()->currentRoom(), widget->selectedText()));
-
- resetSelection();
-}
-
-void
-SuggestionsPopup::selectNextSuggestion()
-{
- selectedItem_++;
- if (selectedItem_ >= layout_->count())
- selectFirstItem();
-
- hoverSelection();
-}
-
-void
-SuggestionsPopup::selectPreviousSuggestion()
-{
- selectedItem_--;
- if (selectedItem_ < 0)
- selectLastItem();
-
- hoverSelection();
-}
-
-void
-SuggestionsPopup::resetHovering()
-{
- for (int i = 0; i < layout_->count(); ++i) {
- const auto item = qobject_cast<PopupItem *>(layout_->itemAt(i)->widget());
-
- if (item)
- item->setHovering(false);
- }
-}
-
-void
-SuggestionsPopup::setHovering(int pos)
-{
- const auto &item = layout_->itemAt(pos);
- const auto &widget = qobject_cast<PopupItem *>(item->widget());
-
- if (widget)
- widget->setHovering(true);
-}
-
-void
-SuggestionsPopup::paintEvent(QPaintEvent *)
-{
- QStyleOption opt;
- opt.init(this);
- QPainter p(this);
- style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
-}
-
-void
-SuggestionsPopup::selectLastItem()
-{
- selectedItem_ = layout_->count() - 1;
-}
-
-void
-SuggestionsPopup::removeLayoutItemsAfter(size_t startingPos)
-{
- size_t posToRemove = layout_->count() - 1;
-
- QLayoutItem *item;
- while (startingPos <= posToRemove &&
- (item = layout_->takeAt((int)posToRemove)) != nullptr) {
- delete item->widget();
- delete item;
-
- posToRemove = layout_->count() - 1;
- }
-}
diff --git a/src/popups/SuggestionsPopup.h b/src/popups/SuggestionsPopup.h
deleted file mode 100644
index 281edddb..00000000
--- a/src/popups/SuggestionsPopup.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#pragma once
-
-#include <QWidget>
-
-#include "CacheStructs.h"
-
-class QVBoxLayout;
-class QLayoutItem;
-
-class SuggestionsPopup : public QWidget
-{
- Q_OBJECT
-
-public:
- explicit SuggestionsPopup(QWidget *parent = nullptr);
-
- void selectHoveredSuggestion();
-
-public slots:
- void addRooms(const std::vector<RoomSearchResult> &rooms);
-
- //! Move to the next available suggestion item.
- void selectNextSuggestion();
- //! Move to the previous available suggestion item.
- void selectPreviousSuggestion();
- //! Remove hovering from all items.
- void resetHovering();
- //! Set hovering to the item in the given layout position.
- void setHovering(int pos);
-
-protected:
- void paintEvent(QPaintEvent *event) override;
-
-signals:
- void itemSelected(const QString &user);
-
-private:
- QString displayName(QString roomid, QString userid);
- void hoverSelection();
- void resetSelection() { selectedItem_ = -1; }
- void selectFirstItem() { selectedItem_ = 0; }
- void selectLastItem();
- void removeLayoutItemsAfter(size_t startingPos);
-
- QVBoxLayout *layout_;
-
- //! Counter for tab completion (cycling).
- int selectedItem_ = -1;
-};
diff --git a/src/popups/UserMentions.cpp b/src/popups/UserMentions.cpp
deleted file mode 100644
index 56b57503..00000000
--- a/src/popups/UserMentions.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include <QPaintEvent>
-#include <QPainter>
-#include <QScrollArea>
-#include <QStyleOption>
-#include <QTabWidget>
-#include <QTimer>
-#include <QVBoxLayout>
-
-#include "Cache.h"
-#include "ChatPage.h"
-#include "EventAccessors.h"
-#include "Logging.h"
-#include "UserMentions.h"
-
-using namespace popups;
-
-UserMentions::UserMentions(QWidget *parent)
- : QWidget{parent}
-{
- setAttribute(Qt::WA_ShowWithoutActivating, true);
- setWindowFlags(Qt::FramelessWindowHint | Qt::Popup);
-
- tab_layout_ = new QTabWidget(this);
-
- top_layout_ = new QVBoxLayout(this);
- top_layout_->setSpacing(0);
- top_layout_->setMargin(0);
-
- local_scroll_area_ = new QScrollArea(this);
- local_scroll_area_->setWidgetResizable(true);
- local_scroll_area_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-
- local_scroll_widget_ = new QWidget(this);
- local_scroll_widget_->setObjectName("local_scroll_widget");
-
- all_scroll_area_ = new QScrollArea(this);
- all_scroll_area_->setWidgetResizable(true);
- all_scroll_area_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-
- all_scroll_widget_ = new QWidget(this);
- all_scroll_widget_->setObjectName("all_scroll_widget");
-
- // Height of the typing display.
- QFont f;
- f.setPointSizeF(f.pointSizeF() * 0.9);
- const int bottomMargin = QFontMetrics(f).height() + 6;
-
- local_scroll_layout_ = new QVBoxLayout(local_scroll_widget_);
- local_scroll_layout_->setContentsMargins(4, 0, 15, bottomMargin);
- local_scroll_layout_->setSpacing(0);
- local_scroll_layout_->setObjectName("localscrollarea");
-
- all_scroll_layout_ = new QVBoxLayout(all_scroll_widget_);
- all_scroll_layout_->setContentsMargins(4, 0, 15, bottomMargin);
- all_scroll_layout_->setSpacing(0);
- all_scroll_layout_->setObjectName("allscrollarea");
-
- local_scroll_area_->setWidget(local_scroll_widget_);
- local_scroll_area_->setAlignment(Qt::AlignBottom);
-
- all_scroll_area_->setWidget(all_scroll_widget_);
- all_scroll_area_->setAlignment(Qt::AlignBottom);
-
- tab_layout_->addTab(local_scroll_area_, tr("This Room"));
- tab_layout_->addTab(all_scroll_area_, tr("All Rooms"));
- top_layout_->addWidget(tab_layout_);
-
- setLayout(top_layout_);
-}
-
-void
-UserMentions::initializeMentions(const QMap<QString, mtx::responses::Notifications> ¬ifs)
-{
- nhlog::ui()->debug("Initializing " + std::to_string(notifs.size()) + " notifications.");
-
- for (const auto &item : notifs) {
- for (const auto ¬if : item.notifications) {
- const auto event_id =
- QString::fromStdString(mtx::accessors::event_id(notif.event));
-
- try {
- const auto room_id = QString::fromStdString(notif.room_id);
- const auto user_id =
- QString::fromStdString(mtx::accessors::sender(notif.event));
- const auto body =
- QString::fromStdString(mtx::accessors::body(notif.event));
-
- pushItem(event_id,
- user_id,
- body,
- room_id,
- ChatPage::instance()->currentRoom());
-
- } catch (const lmdb::error &e) {
- nhlog::db()->warn("error while sending desktop notification: {}",
- e.what());
- }
- }
- }
-}
-
-void
-UserMentions::showPopup()
-{
- for (auto widget : all_scroll_layout_->findChildren<QWidget *>()) {
- delete widget;
- }
- for (auto widget : local_scroll_layout_->findChildren<QWidget *>()) {
- delete widget;
- }
-
- auto notifs = cache::getTimelineMentions();
-
- initializeMentions(notifs);
- show();
-}
-
-void
-UserMentions::pushItem(const QString &event_id,
- const QString &user_id,
- const QString &body,
- const QString &room_id,
- const QString ¤t_room_id)
-{
- (void)event_id;
- (void)user_id;
- (void)body;
- (void)room_id;
- (void)current_room_id;
- // setUpdatesEnabled(false);
- //
- // // Add to the 'all' section
- // TimelineItem *view_item = new TimelineItem(
- // mtx::events::MessageType::Text, user_id, body, true, room_id,
- // all_scroll_widget_);
- // view_item->setEventId(event_id);
- // view_item->hide();
- //
- // all_scroll_layout_->addWidget(view_item);
- // QTimer::singleShot(0, this, [view_item, this]() {
- // view_item->show();
- // view_item->adjustSize();
- // setUpdatesEnabled(true);
- // });
- //
- // // if it matches the current room... add it to the current room as well.
- // if (QString::compare(room_id, current_room_id, Qt::CaseInsensitive) == 0) {
- // // Add to the 'local' section
- // TimelineItem *local_view_item = new
- // TimelineItem(mtx::events::MessageType::Text,
- // user_id,
- // body,
- // true,
- // room_id,
- // local_scroll_widget_);
- // local_view_item->setEventId(event_id);
- // local_view_item->hide();
- // local_scroll_layout_->addWidget(local_view_item);
- //
- // QTimer::singleShot(0, this, [local_view_item]() {
- // local_view_item->show();
- // local_view_item->adjustSize();
- // });
- // }
-}
-
-void
-UserMentions::paintEvent(QPaintEvent *)
-{
- QStyleOption opt;
- opt.init(this);
- QPainter p(this);
- style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
-}
diff --git a/src/popups/UserMentions.h b/src/popups/UserMentions.h
deleted file mode 100644
index f0b662d8..00000000
--- a/src/popups/UserMentions.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#pragma once
-
-#include <mtx/responses/notifications.hpp>
-
-#include <QMap>
-#include <QString>
-#include <QWidget>
-
-class QPaintEvent;
-class QTabWidget;
-class QScrollArea;
-class QVBoxLayout;
-
-namespace popups {
-
-class UserMentions : public QWidget
-{
- Q_OBJECT
-public:
- UserMentions(QWidget *parent = nullptr);
-
- void initializeMentions(const QMap<QString, mtx::responses::Notifications> ¬ifs);
- void showPopup();
-
-protected:
- void paintEvent(QPaintEvent *) override;
-
-private:
- void pushItem(const QString &event_id,
- const QString &user_id,
- const QString &body,
- const QString &room_id,
- const QString ¤t_room_id);
- QTabWidget *tab_layout_;
- QVBoxLayout *top_layout_;
- QVBoxLayout *local_scroll_layout_;
- QVBoxLayout *all_scroll_layout_;
-
- QScrollArea *local_scroll_area_;
- QWidget *local_scroll_widget_;
-
- QScrollArea *all_scroll_area_;
- QWidget *all_scroll_widget_;
-};
-}
diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp
index a283d24e..c309daab 100644
--- a/src/timeline/InputBar.cpp
+++ b/src/timeline/InputBar.cpp
@@ -20,6 +20,7 @@
#include "Cache.h"
#include "ChatPage.h"
#include "CompletionProxyModel.h"
+#include "Config.h"
#include "Logging.h"
#include "MainWindow.h"
#include "MatrixClient.h"
diff --git a/src/timeline/RoomlistModel.cpp b/src/timeline/RoomlistModel.cpp
index ad4177a4..9f926d2b 100644
--- a/src/timeline/RoomlistModel.cpp
+++ b/src/timeline/RoomlistModel.cpp
@@ -530,3 +530,33 @@ FilteredRoomlistModel::toggleTag(QString roomid, QString tag, bool on)
});
}
}
+
+void
+FilteredRoomlistModel::nextRoom()
+{
+ auto r = currentRoom();
+
+ if (r) {
+ int idx = roomidToIndex(r->roomId());
+ idx++;
+ if (idx < rowCount()) {
+ setCurrentRoom(
+ data(index(idx, 0), RoomlistModel::Roles::RoomId).toString());
+ }
+ }
+}
+
+void
+FilteredRoomlistModel::previousRoom()
+{
+ auto r = currentRoom();
+
+ if (r) {
+ int idx = roomidToIndex(r->roomId());
+ idx--;
+ if (idx > 0) {
+ setCurrentRoom(
+ data(index(idx, 0), RoomlistModel::Roles::RoomId).toString());
+ }
+ }
+}
diff --git a/src/timeline/RoomlistModel.h b/src/timeline/RoomlistModel.h
index 1c6fa833..d3e1e1f9 100644
--- a/src/timeline/RoomlistModel.h
+++ b/src/timeline/RoomlistModel.h
@@ -118,6 +118,9 @@ public slots:
TimelineModel *currentRoom() const { return roomlistmodel->currentRoom(); }
void setCurrentRoom(QString roomid) { roomlistmodel->setCurrentRoom(std::move(roomid)); }
+ void nextRoom();
+ void previousRoom();
+
signals:
void currentRoomChanged();
|