From c480f8f4bcef551eddcddeb5a4304de33c146732 Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Fri, 19 May 2017 19:55:38 +0300 Subject: [PATCH] Snappy sidebar --- CMakeLists.txt | 2 - forms/ChatPage.ui | 153 --------------------------------------- include/ChatPage.h | 21 ++++-- include/Splitter.h | 5 +- include/UserInfoWidget.h | 3 + include/ui/Theme.h | 5 ++ src/ChatPage.cc | 76 ++++++++++++++++--- src/RoomInfoListItem.cc | 95 +++++++++++++----------- src/RoomList.cc | 4 +- src/Splitter.cc | 21 ++---- src/UserInfoWidget.cc | 27 ++++++- 11 files changed, 174 insertions(+), 238 deletions(-) delete mode 100644 forms/ChatPage.ui diff --git a/CMakeLists.txt b/CMakeLists.txt index e45c3560..98b3edff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,8 +149,6 @@ include_directories(include/ui) include_directories(include/events) include_directories(include/events/messages) -qt5_wrap_ui (UI_HEADERS forms/ChatPage.ui) - qt5_wrap_cpp(MOC_HEADERS include/ChatPage.h include/EmojiCategory.h diff --git a/forms/ChatPage.ui b/forms/ChatPage.ui deleted file mode 100644 index 3fe664bd..00000000 --- a/forms/ChatPage.ui +++ /dev/null @@ -1,153 +0,0 @@ - - - ChatPage - - - - 0 - 0 - 798 - 519 - - - - - 0 - 0 - - - - Form - - - background-color: #f8fbfe; - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - - 0 - - - 0 - - - - - - 300 - 0 - - - - - 300 - 16777215 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - - background-color: #d6dde3; -color: #ebebeb; - - - - 0 - - - - - 0 - - - - - - - - - - - - 0 - - - - - - - - - - - - 0 - - - - - 0 - - - - - - - 0 - - - - - - - - - - - - - - diff --git a/include/ChatPage.h b/include/ChatPage.h index 5ad22584..7e8bc9e9 100644 --- a/include/ChatPage.h +++ b/include/ChatPage.h @@ -24,16 +24,12 @@ #include "MatrixClient.h" #include "RoomList.h" #include "RoomState.h" +#include "Splitter.h" #include "TextInputWidget.h" #include "TimelineViewManager.h" #include "TopRoomBar.h" #include "UserInfoWidget.h" -namespace Ui -{ -class ChatPage; -} - class ChatPage : public QWidget { Q_OBJECT @@ -64,7 +60,20 @@ private slots: private: void updateRoomState(RoomState &room_state, const QJsonArray &events); - Ui::ChatPage *ui; + QHBoxLayout *topLayout_; + Splitter *splitter; + + QWidget *sideBar_; + QVBoxLayout *sideBarLayout_; + QVBoxLayout *sideBarTopLayout_; + QVBoxLayout *sideBarMainLayout_; + QWidget *sideBarTopWidget_; + QVBoxLayout *sideBarTopWidgetLayout_; + + QWidget *content_; + QVBoxLayout *contentLayout_; + QHBoxLayout *topBarLayout_; + QVBoxLayout *mainContentLayout_; RoomList *room_list_; TimelineViewManager *view_manager_; diff --git a/include/Splitter.h b/include/Splitter.h index d9610730..fdaca8f7 100644 --- a/include/Splitter.h +++ b/include/Splitter.h @@ -23,14 +23,11 @@ class Splitter : public QSplitter { Q_OBJECT public: - explicit Splitter(int first_step, int second_step, QWidget *parent = nullptr); + explicit Splitter(QWidget *parent = nullptr); private: void onSplitterMoved(int pos, int index); - int firstStep_ = 60; - int secondStep_ = 300; - int moveEventLimit_ = 50; int leftMoveCount_ = 0; diff --git a/include/UserInfoWidget.h b/include/UserInfoWidget.h index e7dfbe25..1b819577 100644 --- a/include/UserInfoWidget.h +++ b/include/UserInfoWidget.h @@ -42,6 +42,9 @@ public: signals: void logout(); +protected: + void resizeEvent(QResizeEvent *event) override; + private: Avatar *userAvatar_; diff --git a/include/ui/Theme.h b/include/ui/Theme.h index 95eb5277..e63d8fc5 100644 --- a/include/ui/Theme.h +++ b/include/ui/Theme.h @@ -12,6 +12,11 @@ enum class AvatarType { Letter }; +namespace sidebar +{ +static const int SmallSize = 60; +static const int NormalSize = 300; +} // Default font size. const int FontSize = 16; diff --git a/src/ChatPage.cc b/src/ChatPage.cc index b1c4e890..bd4d6568 100644 --- a/src/ChatPage.cc +++ b/src/ChatPage.cc @@ -15,14 +15,13 @@ * along with this program. If not, see . */ -#include "ui_ChatPage.h" - #include -#include #include #include "ChatPage.h" +#include "Splitter.h" #include "Sync.h" +#include "Theme.h" #include "TimelineViewManager.h" #include "UserInfoWidget.h" @@ -43,26 +42,80 @@ namespace events = matrix::events; ChatPage::ChatPage(QSharedPointer client, QWidget *parent) : QWidget(parent) - , ui(new Ui::ChatPage) , sync_interval_(2000) , client_(client) { - ui->setupUi(this); + resize(798, 519); + setStyleSheet("background-color: #f8fbfe;"); + + topLayout_ = new QHBoxLayout(this); + topLayout_->setSpacing(0); + topLayout_->setMargin(0); + + auto splitter = new Splitter(this); + splitter->setHandleWidth(0); + + topLayout_->addWidget(splitter); + + // SideBar + sideBar_ = new QWidget(this); + sideBar_->setMinimumSize(QSize(ui::sidebar::NormalSize, 0)); + sideBarLayout_ = new QVBoxLayout(sideBar_); + sideBarLayout_->setSpacing(0); + sideBarLayout_->setMargin(0); + + sideBarTopLayout_ = new QVBoxLayout(); + sideBarTopLayout_->setSpacing(0); + sideBarTopLayout_->setMargin(0); + sideBarMainLayout_ = new QVBoxLayout(); + sideBarMainLayout_->setSpacing(0); + sideBarMainLayout_->setMargin(0); + + sideBarLayout_->addLayout(sideBarTopLayout_); + sideBarLayout_->addLayout(sideBarMainLayout_); + + sideBarTopWidget_ = new QWidget(sideBar_); + sideBarTopWidget_->setStyleSheet("background-color: #d6dde3; color: #ebebeb;"); + + sideBarTopLayout_->addWidget(sideBarTopWidget_); + + sideBarTopWidgetLayout_ = new QVBoxLayout(sideBarTopWidget_); + sideBarTopWidgetLayout_->setSpacing(0); + sideBarTopWidgetLayout_->setMargin(0); + + // Content + content_ = new QWidget(this); + contentLayout_ = new QVBoxLayout(content_); + contentLayout_->setSpacing(0); + contentLayout_->setMargin(0); + + topBarLayout_ = new QHBoxLayout(); + topBarLayout_->setSpacing(0); + mainContentLayout_ = new QVBoxLayout(); + mainContentLayout_->setSpacing(0); + mainContentLayout_->setMargin(0); + + contentLayout_->addLayout(topBarLayout_); + contentLayout_->addLayout(mainContentLayout_); + + // Splitter + splitter->addWidget(sideBar_); + splitter->addWidget(content_); room_list_ = new RoomList(client, this); - ui->sideBarMainLayout->addWidget(room_list_); + sideBarMainLayout_->addWidget(room_list_); top_bar_ = new TopRoomBar(this); - ui->topBarLayout->addWidget(top_bar_); + topBarLayout_->addWidget(top_bar_); view_manager_ = new TimelineViewManager(client, this); - ui->mainContentLayout->addWidget(view_manager_); + mainContentLayout_->addWidget(view_manager_); text_input_ = new TextInputWidget(this); - ui->contentLayout->addWidget(text_input_); + contentLayout_->addWidget(text_input_); - user_info_widget_ = new UserInfoWidget(ui->sideBarTopWidget); - ui->sideBarTopUserInfoLayout->addWidget(user_info_widget_); + user_info_widget_ = new UserInfoWidget(sideBarTopWidget_); + sideBarTopWidgetLayout_->addWidget(user_info_widget_); sync_timer_ = new QTimer(this); sync_timer_->setSingleShot(true); @@ -366,5 +419,4 @@ void ChatPage::updateRoomState(RoomState &room_state, const QJsonArray &events) ChatPage::~ChatPage() { sync_timer_->stop(); - delete ui; } diff --git a/src/RoomInfoListItem.cc b/src/RoomInfoListItem.cc index a7c90055..59cf986f 100644 --- a/src/RoomInfoListItem.cc +++ b/src/RoomInfoListItem.cc @@ -22,6 +22,7 @@ #include "Ripple.h" #include "RoomInfoListItem.h" #include "RoomState.h" +#include "Theme.h" RoomInfoListItem::RoomInfoListItem(RoomState state, QString room_id, QWidget *parent) : QWidget(parent) @@ -36,7 +37,6 @@ RoomInfoListItem::RoomInfoListItem(RoomState state, QString room_id, QWidget *pa setAttribute(Qt::WA_Hover); setFixedHeight(maxHeight_); - setMaximumSize(parent->width(), maxHeight_); QPainterPath path; path.addRect(0, 0, parent->width(), height()); @@ -69,30 +69,61 @@ void RoomInfoListItem::paintEvent(QPaintEvent *event) QRect avatarRegion(Padding, Padding, IconSize, IconSize); - if (isPressed_) { - QPen pen(QColor("white")); - p.setPen(pen); - } - - auto name = metrics.elidedText(state_.resolveName(), Qt::ElideRight, (width() - IconSize - 2 * Padding) * 0.8); - p.drawText(QPoint(2 * Padding + IconSize, avatarRegion.center().y() - metrics.height() / 2), name); - - if (!isPressed_) { - QPen pen(QColor("#5d6565")); - p.setPen(pen); - } - + // Description line int bottom_y = avatarRegion.center().y() + metrics.height() / 2 + Padding / 2; - double descPercentage = 0.95; - if (unreadMsgCount_ > 0) - descPercentage = 0.8; + if (width() > ui::sidebar::SmallSize) { + if (isPressed_) { + QPen pen(QColor("white")); + p.setPen(pen); + } - auto description = metrics.elidedText(state_.resolveTopic(), Qt::ElideRight, width() * descPercentage - 2 * Padding - IconSize); - p.drawText(QPoint(2 * Padding + IconSize, bottom_y), description); + auto name = metrics.elidedText(state_.resolveName(), Qt::ElideRight, (width() - IconSize - 2 * Padding) * 0.8); + p.drawText(QPoint(2 * Padding + IconSize, avatarRegion.center().y() - metrics.height() / 2), name); + + if (!isPressed_) { + QPen pen(QColor("#5d6565")); + p.setPen(pen); + } + + double descPercentage = 0.95; + + if (unreadMsgCount_ > 0) + descPercentage = 0.8; + + auto description = metrics.elidedText(state_.resolveTopic(), Qt::ElideRight, width() * descPercentage - 2 * Padding - IconSize); + p.drawText(QPoint(2 * Padding + IconSize, bottom_y), description); + } p.setPen(Qt::NoPen); + // We using the first letter of room's name. + if (roomAvatar_.isNull()) { + QBrush brush; + brush.setStyle(Qt::SolidPattern); + brush.setColor("#eee"); + + p.setPen(Qt::NoPen); + p.setBrush(brush); + + p.drawEllipse(avatarRegion.center(), IconSize / 2, IconSize / 2); + + font.setPixelSize(13); + p.setFont(font); + p.setPen(QColor("#333")); + p.setBrush(Qt::NoBrush); + p.drawText(avatarRegion.translated(0, -1), Qt::AlignCenter, QChar(state_.resolveName()[0])); + } else { + p.save(); + + QPainterPath path; + path.addEllipse(Padding, Padding, IconSize, IconSize); + p.setClipPath(path); + + p.drawPixmap(avatarRegion, roomAvatar_); + p.restore(); + } + if (unreadMsgCount_ > 0) { QColor textColor("white"); QColor backgroundColor("#38A3D8"); @@ -116,6 +147,9 @@ void RoomInfoListItem::paintEvent(QPaintEvent *event) QRectF r(width() - diameter - Padding, bottom_y - diameter / 2 - 5, diameter, diameter); + if (width() == ui::sidebar::SmallSize) + r = QRectF(width() - diameter - 5, height() - diameter - 5, diameter, diameter); + p.setPen(Qt::NoPen); p.drawEllipse(r); @@ -127,29 +161,6 @@ void RoomInfoListItem::paintEvent(QPaintEvent *event) p.setBrush(Qt::NoBrush); p.drawText(r.translated(0, -0.5), Qt::AlignCenter, QString::number(unreadMsgCount_)); } - - // We using the first letter of room's name. - if (roomAvatar_.isNull()) { - QBrush brush; - brush.setStyle(Qt::SolidPattern); - brush.setColor("#eee"); - - p.setPen(Qt::NoPen); - p.setBrush(brush); - - p.drawEllipse(avatarRegion.center(), IconSize / 2, IconSize / 2); - - font.setPixelSize(13); - p.setFont(font); - p.setPen(QColor("#333")); - p.setBrush(Qt::NoBrush); - p.drawText(avatarRegion.translated(0, -1), Qt::AlignCenter, QChar(state_.resolveName()[0])); - } else { - QPainterPath path; - path.addEllipse(Padding, Padding, IconSize, IconSize); - p.setClipPath(path); - p.drawPixmap(avatarRegion, roomAvatar_); - } } void RoomInfoListItem::updateUnreadMessageCount(int count) diff --git a/src/RoomList.cc b/src/RoomList.cc index c3fe16a2..f9957bd3 100644 --- a/src/RoomList.cc +++ b/src/RoomList.cc @@ -31,13 +31,11 @@ RoomList::RoomList(QSharedPointer client, QWidget *parent) "QWidget { border: none; }" "QScrollBar:vertical { width: 4px; margin: 2px 0; }"); - QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); sizePolicy.setHorizontalStretch(0); sizePolicy.setVerticalStretch(0); setSizePolicy(sizePolicy); - setMinimumSize(QSize(0, 500)); - topLayout_ = new QVBoxLayout(this); topLayout_->setSpacing(0); topLayout_->setMargin(0); diff --git a/src/Splitter.cc b/src/Splitter.cc index 0a3ea416..2564c434 100644 --- a/src/Splitter.cc +++ b/src/Splitter.cc @@ -18,11 +18,10 @@ #include #include "Splitter.h" +#include "Theme.h" -Splitter::Splitter(int first_step, int second_step, QWidget *parent) +Splitter::Splitter(QWidget *parent) : QSplitter(parent) - , firstStep_{first_step} - , secondStep_{second_step} { connect(this, &QSplitter::splitterMoved, this, &Splitter::onSplitterMoved); } @@ -39,7 +38,7 @@ void Splitter::onSplitterMoved(int pos, int index) return; } - if (s[0] == secondStep_) { + if (s[0] == ui::sidebar::NormalSize) { rightMoveCount_ += 1; if (rightMoveCount_ > moveEventLimit_) { @@ -49,15 +48,13 @@ void Splitter::onSplitterMoved(int pos, int index) // if we are coming from the right, the cursor should // end up on the first widget. if (left->rect().contains(pos)) { - qDebug() << "Resizing left"; - - left->setMinimumWidth(firstStep_); - left->setMaximumWidth(firstStep_); + left->setMinimumWidth(ui::sidebar::SmallSize); + left->setMaximumWidth(ui::sidebar::SmallSize); rightMoveCount_ = 0; } } - } else if (s[0] == firstStep_) { + } else if (s[0] == ui::sidebar::SmallSize) { leftMoveCount_ += 1; if (leftMoveCount_ > moveEventLimit_) { @@ -72,10 +69,8 @@ void Splitter::onSplitterMoved(int pos, int index) // if we are coming from the left, the cursor should // end up on the second widget. if (extended.contains(pos)) { - qDebug() << "Resizing Right"; - - left->setMinimumWidth(secondStep_); - left->setMaximumWidth(2 * secondStep_); + left->setMinimumWidth(ui::sidebar::NormalSize); + left->setMaximumWidth(2 * ui::sidebar::NormalSize); leftMoveCount_ = 0; } diff --git a/src/UserInfoWidget.cc b/src/UserInfoWidget.cc index 82ff822f..2fca8925 100644 --- a/src/UserInfoWidget.cc +++ b/src/UserInfoWidget.cc @@ -15,8 +15,10 @@ * along with this program. If not, see . */ -#include "UserInfoWidget.h" +#include + #include "FlatButton.h" +#include "UserInfoWidget.h" UserInfoWidget::UserInfoWidget(QWidget *parent) : QWidget(parent) @@ -29,7 +31,7 @@ UserInfoWidget::UserInfoWidget(QWidget *parent) topLayout_ = new QHBoxLayout(this); topLayout_->setSpacing(0); - topLayout_->setContentsMargins(5, 5, 5, 5); + topLayout_->setMargin(5); avatarLayout_ = new QHBoxLayout(); textLayout_ = new QVBoxLayout(); @@ -65,11 +67,12 @@ UserInfoWidget::UserInfoWidget(QWidget *parent) topLayout_->addStretch(1); buttonLayout_ = new QHBoxLayout(); + buttonLayout_->setSpacing(0); + buttonLayout_->setMargin(0); logoutButton_ = new FlatButton(this); logoutButton_->setForegroundColor(QColor("#555459")); logoutButton_->setCursor(QCursor(Qt::PointingHandCursor)); - logoutButton_->setStyleSheet("width: 30px; height: 30px;"); QIcon icon; icon.addFile(":/icons/icons/power-button-off.png", QSize(), QIcon::Normal, QIcon::Off); @@ -88,6 +91,24 @@ UserInfoWidget::~UserInfoWidget() { } +void UserInfoWidget::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + + if (width() <= ui::sidebar::SmallSize) { + topLayout_->setContentsMargins(0, 0, 10, 0); + + userAvatar_->hide(); + displayNameLabel_->hide(); + userIdLabel_->hide(); + } else { + topLayout_->setMargin(5); + userAvatar_->show(); + displayNameLabel_->show(); + userIdLabel_->show(); + } +} + void UserInfoWidget::reset() { displayNameLabel_->setText("");