summary refs log tree commit diff
diff options
context:
space:
mode:
authorKonstantinos Sideris <sideris.konstantin@gmail.com>2018-04-30 21:41:47 +0300
committerKonstantinos Sideris <sideris.konstantin@gmail.com>2018-04-30 21:41:47 +0300
commit3097037c3dc882be2efe64dce6aefeea43d5f040 (patch)
tree1e3375fbd423c3bd18513e6d2a502b7fa1e4cfb8
parentShow room tooltips when the sidebar is collapsed (diff)
downloadnheko-3097037c3dc882be2efe64dce6aefeea43d5f040.tar.xz
Add prototype room settings menu
-rw-r--r--CMakeLists.txt2
-rw-r--r--include/Cache.h8
-rw-r--r--include/ChatPage.h1
-rw-r--r--include/MainWindow.h6
-rw-r--r--include/TopRoomBar.h4
-rw-r--r--include/dialogs/RoomSettings.hpp88
-rw-r--r--include/ui/Painter.h2
-rw-r--r--resources/styles/nheko-dark.qss5
-rw-r--r--resources/styles/nheko.qss5
-rw-r--r--src/Cache.cc22
-rw-r--r--src/CommunitiesListItem.cc3
-rw-r--r--src/MainWindow.cc22
-rw-r--r--src/TopRoomBar.cc6
-rw-r--r--src/dialogs/RoomSettings.cpp147
14 files changed, 309 insertions, 12 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt

index 864f42a1..e1d835f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -106,6 +106,7 @@ set(SRC_FILES src/dialogs/Logout.cc src/dialogs/ReadReceipts.cc src/dialogs/ReCaptcha.cpp + src/dialogs/RoomSettings.cpp # Emoji src/emoji/Category.cc @@ -222,6 +223,7 @@ qt5_wrap_cpp(MOC_HEADERS include/dialogs/Logout.h include/dialogs/ReadReceipts.h include/dialogs/ReCaptcha.hpp + include/dialogs/RoomSettings.hpp # Emoji include/emoji/Category.h diff --git a/include/Cache.h b/include/Cache.h
index a92f6bc5..db5dba00 100644 --- a/include/Cache.h +++ b/include/Cache.h
@@ -64,6 +64,8 @@ struct RoomInfo std::string avatar_url; //! Whether or not the room is an invite. bool is_invite = false; + //! Total number of members in the room. + int16_t member_count = 0; }; inline void @@ -73,6 +75,9 @@ to_json(json &j, const RoomInfo &info) j["topic"] = info.topic; j["avatar_url"] = info.avatar_url; j["is_invite"] = info.is_invite; + + if (info.member_count != 0) + j["member_count"] = info.member_count; } inline void @@ -82,6 +87,9 @@ from_json(const json &j, RoomInfo &info) info.topic = j.at("topic"); info.avatar_url = j.at("avatar_url"); info.is_invite = j.at("is_invite"); + + if (j.count("member_count")) + info.member_count = j.at("member_count"); } //! Basic information per member; diff --git a/include/ChatPage.h b/include/ChatPage.h
index 831f3933..1582db06 100644 --- a/include/ChatPage.h +++ b/include/ChatPage.h
@@ -80,6 +80,7 @@ public: } QSharedPointer<UserSettings> userSettings() { return userSettings_; } + QSharedPointer<Cache> cache() { return cache_; } signals: void contentLoaded(); diff --git a/include/MainWindow.h b/include/MainWindow.h
index d747f9b4..08d7e53e 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h
@@ -50,6 +50,7 @@ class JoinRoom; class LeaveRoom; class Logout; class ReCaptcha; +class RoomSettings; } class MainWindow : public QMainWindow @@ -68,6 +69,7 @@ public: std::function<void(const mtx::requests::CreateRoom &request)> callback); void openJoinRoomDialog(std::function<void(const QString &room_id)> callback); void openLogoutDialog(std::function<void()> callback); + void openRoomSettings(const QString &room_id = ""); protected: void closeEvent(QCloseEvent *event); @@ -147,4 +149,8 @@ private: QSharedPointer<OverlayModal> logoutModal_; //! Logout dialog. QSharedPointer<dialogs::Logout> logoutDialog_; + //! Room settings modal. + QSharedPointer<OverlayModal> roomSettingsModal_; + //! Room settings dialog. + QSharedPointer<dialogs::RoomSettings> roomSettingsDialog_; }; diff --git a/include/TopRoomBar.h b/include/TopRoomBar.h
index 12fd0645..37a0b61b 100644 --- a/include/TopRoomBar.h +++ b/include/TopRoomBar.h
@@ -21,7 +21,6 @@ #include <QIcon> #include <QImage> #include <QLabel> -#include <QMenu> #include <QPaintEvent> #include <QSharedPointer> #include <QVBoxLayout> @@ -66,8 +65,9 @@ private: QLabel *nameLabel_; Label *topicLabel_; - QMenu *menu_; + Menu *menu_; QAction *leaveRoom_; + QAction *roomSettings_; QAction *inviteUsers_; FlatButton *settingsBtn_; diff --git a/include/dialogs/RoomSettings.hpp b/include/dialogs/RoomSettings.hpp new file mode 100644
index 00000000..fbbc2e02 --- /dev/null +++ b/include/dialogs/RoomSettings.hpp
@@ -0,0 +1,88 @@ +#pragma once + +#include <QFrame> +#include <QImage> + +#include "Cache.h" + +class FlatButton; +class TextField; +class Avatar; +class QPixmap; +class QLayout; +class QLabel; + +template<class T> +class QSharedPointer; + +class TopSection : public QWidget +{ + Q_OBJECT + + Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor) + +public: + TopSection(const RoomInfo &info, const QImage &img, QWidget *parent = nullptr) + : QWidget{parent} + , info_{std::move(info)} + { + textColor_ = palette().color(QPalette::Text); + avatar_ = QPixmap::fromImage(img.scaled( + AvatarSize, AvatarSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + } + + QSize sizeHint() const override + { + QFont font; + font.setPixelSize(18); + return QSize(200, AvatarSize + QFontMetrics(font).ascent() + 6 * Padding); + } + + QColor textColor() const { return textColor_; } + void setTextColor(QColor &color) { textColor_ = color; } + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + static constexpr int AvatarSize = 72; + static constexpr int Padding = 5; + + RoomInfo info_; + QPixmap avatar_; + QColor textColor_; +}; + +namespace dialogs { + +class RoomSettings : public QFrame +{ + Q_OBJECT +public: + RoomSettings(const QString &room_id, + QSharedPointer<Cache> cache, + QWidget *parent = nullptr); + +signals: + void closing(); + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + static constexpr int AvatarSize = 64; + + void setAvatar(const QImage &img) { avatarImg_ = img; } + + QSharedPointer<Cache> cache_; + + // Button section + FlatButton *saveBtn_; + FlatButton *cancelBtn_; + + RoomInfo info_; + QString room_id_; + QImage avatarImg_; +}; + +} // dialogs diff --git a/include/ui/Painter.h b/include/ui/Painter.h
index 9558b004..8de39651 100644 --- a/include/ui/Painter.h +++ b/include/ui/Painter.h
@@ -103,7 +103,7 @@ public: drawPixmap(region, pix); } - void drawLetterAvatar(const QChar &c, + void drawLetterAvatar(const QString &c, const QColor &penColor, const QColor &brushColor, int w, diff --git a/resources/styles/nheko-dark.qss b/resources/styles/nheko-dark.qss
index 28850711..89582348 100644 --- a/resources/styles/nheko-dark.qss +++ b/resources/styles/nheko-dark.qss
@@ -136,6 +136,7 @@ dialogs--Logout, dialogs--ReCaptcha, dialogs--LeaveRoom, dialogs--CreateRoom, +dialogs--RoomSettings, dialogs--InviteUsers, dialogs--ReadReceipts, dialogs--JoinRoom, @@ -147,6 +148,10 @@ dialogs--JoinRoom > QLineEdit { color: #caccd1; } +TopSection { + qproperty-textColor: #caccd1; +} + QListWidget, WelcomePage, LoginPage, diff --git a/resources/styles/nheko.qss b/resources/styles/nheko.qss
index e1cb839f..6538a780 100644 --- a/resources/styles/nheko.qss +++ b/resources/styles/nheko.qss
@@ -138,6 +138,7 @@ dialogs--Logout, dialogs--ReCaptcha, dialogs--LeaveRoom, dialogs--CreateRoom, +dialogs--RoomSettings, dialogs--InviteUsers, dialogs--ReadReceipts, dialogs--JoinRoom, @@ -147,6 +148,10 @@ QListWidget { color: #333; } +TopSection { + qproperty-textColor: #333; +} + WelcomePage, LoginPage, RegisterPage { diff --git a/src/Cache.cc b/src/Cache.cc
index 699774ce..60181afc 100644 --- a/src/Cache.cc +++ b/src/Cache.cc
@@ -538,9 +538,10 @@ Cache::getRoomInfo(const std::vector<std::string> &rooms) // Check if the room is joined. if (lmdb::dbi_get(txn, roomsDb_, lmdb::val(room), data)) { try { - room_info.emplace( - QString::fromStdString(room), - json::parse(std::string(data.data(), data.size()))); + RoomInfo tmp = json::parse(std::string(data.data(), data.size())); + tmp.member_count = getMembersDb(txn, room).size(txn); + + room_info.emplace(QString::fromStdString(room), std::move(tmp)); } catch (const json::exception &e) { qWarning() << "failed to parse room info:" << QString::fromStdString(room) @@ -550,9 +551,12 @@ Cache::getRoomInfo(const std::vector<std::string> &rooms) // Check if the room is an invite. if (lmdb::dbi_get(txn, invitesDb_, lmdb::val(room), data)) { try { - room_info.emplace( - QString::fromStdString(room), - json::parse(std::string(data.data(), data.size()))); + RoomInfo tmp = + json::parse(std::string(data.data(), data.size())); + tmp.member_count = getInviteMembersDb(txn, room).size(txn); + + room_info.emplace(QString::fromStdString(room), + std::move(tmp)); } catch (const json::exception &e) { qWarning() << "failed to parse room info for invite:" << QString::fromStdString(room) @@ -581,7 +585,8 @@ Cache::roomInfo(bool withInvites) // Gather info about the joined rooms. auto roomsCursor = lmdb::cursor::open(txn, roomsDb_); while (roomsCursor.get(room_id, room_data, MDB_NEXT)) { - RoomInfo tmp = json::parse(std::move(room_data)); + RoomInfo tmp = json::parse(std::move(room_data)); + tmp.member_count = getMembersDb(txn, room_id).size(txn); result.insert(QString::fromStdString(std::move(room_id)), std::move(tmp)); } roomsCursor.close(); @@ -590,7 +595,8 @@ Cache::roomInfo(bool withInvites) // Gather info about the invites. auto invitesCursor = lmdb::cursor::open(txn, invitesDb_); while (invitesCursor.get(room_id, room_data, MDB_NEXT)) { - RoomInfo tmp = json::parse(room_data); + RoomInfo tmp = json::parse(room_data); + tmp.member_count = getInviteMembersDb(txn, room_id).size(txn); result.insert(QString::fromStdString(std::move(room_id)), std::move(tmp)); } invitesCursor.close(); diff --git a/src/CommunitiesListItem.cc b/src/CommunitiesListItem.cc
index e86216e8..0650c0cf 100644 --- a/src/CommunitiesListItem.cc +++ b/src/CommunitiesListItem.cc
@@ -2,6 +2,7 @@ #include "Painter.h" #include "Ripple.h" #include "RippleOverlay.h" +#include "Utils.h" CommunitiesListItem::CommunitiesListItem(QSharedPointer<Community> community, QString community_id, @@ -74,7 +75,7 @@ CommunitiesListItem::paintEvent(QPaintEvent *) font.setPixelSize(conf::roomlist::fonts::communityBubble); p.setFont(font); - p.drawLetterAvatar(community_->getName()[0], + p.drawLetterAvatar(utils::firstChar(community_->getName()), avatarFgColor_, avatarBgColor_, width(), diff --git a/src/MainWindow.cc b/src/MainWindow.cc
index c59ce2d9..66f956a5 100644 --- a/src/MainWindow.cc +++ b/src/MainWindow.cc
@@ -41,6 +41,7 @@ #include "dialogs/JoinRoom.h" #include "dialogs/LeaveRoom.h" #include "dialogs/Logout.h" +#include "dialogs/RoomSettings.hpp" MainWindow *MainWindow::instance_ = nullptr; @@ -263,6 +264,27 @@ MainWindow::hasActiveUser() } void +MainWindow::openRoomSettings(const QString &room_id) +{ + const auto roomToSearch = room_id.isEmpty() ? chat_page_->currentRoom() : ""; + + qDebug() << "room settings" << roomToSearch; + + roomSettingsDialog_ = QSharedPointer<dialogs::RoomSettings>( + new dialogs::RoomSettings(roomToSearch, chat_page_->cache(), this)); + + connect(roomSettingsDialog_.data(), &dialogs::RoomSettings::closing, this, [this]() { + roomSettingsModal_->hide(); + }); + + roomSettingsModal_ = + QSharedPointer<OverlayModal>(new OverlayModal(this, roomSettingsDialog_.data())); + roomSettingsModal_->setColor(QColor(30, 30, 30, 170)); + + roomSettingsModal_->show(); +} + +void MainWindow::openLeaveRoomDialog(const QString &room_id) { auto roomToLeave = room_id.isEmpty() ? chat_page_->currentRoom() : room_id; diff --git a/src/TopRoomBar.cc b/src/TopRoomBar.cc
index 3b60ab6a..beca1d51 100644 --- a/src/TopRoomBar.cc +++ b/src/TopRoomBar.cc
@@ -95,8 +95,14 @@ TopRoomBar::TopRoomBar(QWidget *parent) MainWindow::instance()->openLeaveRoomDialog(); }); + roomSettings_ = new QAction(tr("Settings"), this); + connect(roomSettings_, &QAction::triggered, this, []() { + MainWindow::instance()->openRoomSettings(); + }); + menu_->addAction(inviteUsers_); menu_->addAction(leaveRoom_); + menu_->addAction(roomSettings_); connect(settingsBtn_, &QPushButton::clicked, this, [this]() { auto pos = mapToGlobal(settingsBtn_->pos()); diff --git a/src/dialogs/RoomSettings.cpp b/src/dialogs/RoomSettings.cpp new file mode 100644
index 00000000..8fcbc82f --- /dev/null +++ b/src/dialogs/RoomSettings.cpp
@@ -0,0 +1,147 @@ +#include "Avatar.h" +#include "Config.h" +#include "FlatButton.h" +#include "Painter.h" +#include "Utils.h" +#include "dialogs/RoomSettings.hpp" + +#include <QComboBox> +#include <QLabel> +#include <QPainter> +#include <QPixmap> +#include <QSharedPointer> +#include <QStyleOption> +#include <QVBoxLayout> + +using namespace dialogs; + +RoomSettings::RoomSettings(const QString &room_id, QSharedPointer<Cache> cache, QWidget *parent) + : QFrame(parent) + , cache_{cache} + , room_id_{std::move(room_id)} +{ + setMaximumWidth(385); + + try { + auto res = cache_->getRoomInfo({room_id_.toStdString()}); + info_ = res[room_id_]; + + setAvatar(QImage::fromData(cache_->image(info_.avatar_url))); + } catch (const lmdb::error &e) { + qWarning() << "failed to retrieve room info from cache" << room_id; + } + + auto layout = new QVBoxLayout(this); + layout->setSpacing(30); + layout->setMargin(20); + + saveBtn_ = new FlatButton("SAVE", this); + saveBtn_->setFontSize(conf::btn::fontSize); + cancelBtn_ = new FlatButton(tr("CANCEL"), this); + cancelBtn_->setFontSize(conf::btn::fontSize); + + auto btnLayout = new QHBoxLayout(); + btnLayout->setSpacing(0); + btnLayout->setMargin(0); + btnLayout->addStretch(1); + btnLayout->addWidget(saveBtn_); + btnLayout->addWidget(cancelBtn_); + + auto notifOptionLayout_ = new QHBoxLayout; + notifOptionLayout_->setMargin(5); + auto themeLabel_ = new QLabel(tr("Notifications"), this); + auto notifCombo = new QComboBox(this); + notifCombo->addItem("Nothing"); + notifCombo->addItem("Mentions only"); + notifCombo->addItem("All messages"); + themeLabel_->setStyleSheet("font-size: 15px;"); + + notifOptionLayout_->addWidget(themeLabel_); + notifOptionLayout_->addWidget(notifCombo, 0, Qt::AlignBottom | Qt::AlignRight); + + layout->addWidget(new TopSection(info_, avatarImg_, this)); + layout->addLayout(notifOptionLayout_); + layout->addLayout(btnLayout); + + connect(cancelBtn_, &FlatButton::clicked, this, &RoomSettings::closing); + connect(saveBtn_, &FlatButton::clicked, this, [this]() { emit closing(); }); +} + +void +RoomSettings::paintEvent(QPaintEvent *) +{ + QStyleOption opt; + opt.init(this); + QPainter p(this); + style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); +} + +void +TopSection::paintEvent(QPaintEvent *) +{ + Painter p(this); + PainterHighQualityEnabler hq(p); + + constexpr int textPadding = 23; + constexpr int textStartX = AvatarSize + 5 * Padding; + const int availableTextWidth = width() - textStartX; + + constexpr int nameFont = 15; + constexpr int membersFont = 14; + constexpr int labelFont = 18; + + QFont font; + font.setPixelSize(labelFont); + font.setWeight(70); + + p.setFont(font); + p.setPen(textColor()); + p.drawTextLeft(Padding, Padding, "Room settings"); + p.translate(0, textPadding + QFontMetrics(p.font()).ascent()); + + p.save(); + p.translate(textStartX, 2 * Padding); + + // Draw the name. + font.setPixelSize(membersFont); + const auto members = QString("%1 members").arg(info_.member_count); + + font.setPixelSize(nameFont); + const auto name = QFontMetrics(font).elidedText( + QString::fromStdString(info_.name), Qt::ElideRight, availableTextWidth - 4 * Padding); + + font.setWeight(60); + p.setFont(font); + p.drawTextLeft(0, 0, name); + + // Draw the number of members + p.translate(0, QFontMetrics(p.font()).ascent() + 2 * Padding); + + font.setPixelSize(membersFont); + font.setWeight(50); + p.setFont(font); + p.drawTextLeft(0, 0, members); + p.restore(); + + if (avatar_.isNull()) { + font.setPixelSize(AvatarSize / 2); + font.setWeight(60); + p.setFont(font); + + p.translate(Padding, Padding); + p.drawLetterAvatar(utils::firstChar(name), + QColor("white"), + QColor("black"), + AvatarSize + Padding, + AvatarSize + Padding, + AvatarSize); + } else { + QRect avatarRegion(Padding, Padding, AvatarSize, AvatarSize); + + QPainterPath pp; + pp.addEllipse(avatarRegion.center(), AvatarSize, AvatarSize); + + p.setClipPath(pp); + p.drawPixmap(avatarRegion, avatar_); + } +}