From 36b010e04616867495aa239956cdb6b7e11592a9 Mon Sep 17 00:00:00 2001 From: fourtf Date: Wed, 24 Jan 2018 15:08:22 +0100 Subject: [PATCH] added custom window frame for windows --- src/singletons/windowmanager.cpp | 31 ++++++++ src/singletons/windowmanager.hpp | 3 + src/widgets/basewindow.cpp | 81 +++++++++++++------- src/widgets/basewindow.hpp | 14 ++-- src/widgets/helper/rippleeffectbutton.cpp | 2 + src/widgets/notebook.cpp | 26 +------ src/widgets/settingspages/appearancepage.cpp | 3 + src/widgets/settingspages/moderationpage.cpp | 28 +++++-- src/widgets/window.cpp | 9 ++- 9 files changed, 134 insertions(+), 63 deletions(-) diff --git a/src/singletons/windowmanager.cpp b/src/singletons/windowmanager.cpp index 5f0f85007..578879f07 100644 --- a/src/singletons/windowmanager.cpp +++ b/src/singletons/windowmanager.cpp @@ -2,6 +2,8 @@ #include "debug/log.hpp" #include "singletons/fontmanager.hpp" #include "singletons/thememanager.hpp" +#include "widgets/accountswitchpopupwidget.hpp" +#include "widgets/settingsdialog.hpp" #include @@ -14,6 +16,35 @@ WindowManager &WindowManager::getInstance() return instance; } +void WindowManager::showSettingsDialog() +{ + QTimer::singleShot(80, [] { widgets::SettingsDialog::showDialog(); }); +} + +void WindowManager::showAccountSelectPopup(QPoint point) +{ + // static QWidget *lastFocusedWidget = nullptr; + static widgets::AccountSwitchPopupWidget *w = new widgets::AccountSwitchPopupWidget(); + + if (w->hasFocus()) { + w->hide(); + // if (lastFocusedWidget) { + // lastFocusedWidget->setFocus(); + // } + return; + } + + // lastFocusedWidget = this->focusWidget(); + + w->refresh(); + + QPoint buttonPos = point; + w->move(buttonPos.x(), buttonPos.y()); + + w->show(); + w->setFocus(); +} + WindowManager::WindowManager(ThemeManager &_themeManager) : themeManager(_themeManager) { diff --git a/src/singletons/windowmanager.hpp b/src/singletons/windowmanager.hpp index a59284fea..8ff0a4604 100644 --- a/src/singletons/windowmanager.hpp +++ b/src/singletons/windowmanager.hpp @@ -14,6 +14,9 @@ class WindowManager public: static WindowManager &getInstance(); + void showSettingsDialog(); + void showAccountSelectPopup(QPoint point); + void initMainWindow(); void layoutVisibleChatWidgets(Channel *channel = nullptr); void repaintVisibleChatWidgets(Channel *channel = nullptr); diff --git a/src/widgets/basewindow.cpp b/src/widgets/basewindow.cpp index f27f5a8bf..d6ec127c4 100644 --- a/src/widgets/basewindow.cpp +++ b/src/widgets/basewindow.cpp @@ -59,16 +59,17 @@ void BaseWindow::init() // CUSTOM WINDOW FRAME QVBoxLayout *layout = new QVBoxLayout; layout->setMargin(1); + layout->setSpacing(0); this->setLayout(layout); { - QHBoxLayout *buttons = this->titlebarBox = new QHBoxLayout; - buttons->setMargin(0); - layout->addLayout(buttons); + QHBoxLayout *buttonLayout = this->titlebarBox = new QHBoxLayout; + buttonLayout->setMargin(0); + layout->addLayout(buttonLayout); // title - QLabel *titleLabel = new QLabel("Chatterino"); - buttons->addWidget(titleLabel); - this->titleLabel = titleLabel; + QLabel *title = new QLabel(" Chatterino"); + buttonLayout->addWidget(title); + this->titleLabel = title; // buttons RippleEffectLabel *min = new RippleEffectLabel; @@ -81,21 +82,31 @@ void BaseWindow::init() exit->setFixedSize(46, 30); exit->getLabel().setText("exit"); + QObject::connect(min, &RippleEffectLabel::clicked, this, [this] { + this->setWindowState(Qt::WindowMinimized | this->windowState()); + }); + QObject::connect(max, &RippleEffectLabel::clicked, this, [this] { + this->setWindowState(this->windowState() == Qt::WindowMaximized + ? Qt::WindowActive + : Qt::WindowMaximized); + }); + QObject::connect(exit, &RippleEffectLabel::clicked, this, [this] { this->close(); }); + this->minButton = min; this->maxButton = max; this->exitButton = exit; - this->widgets.push_back(min); - this->widgets.push_back(max); - this->widgets.push_back(exit); + this->buttons.push_back(min); + this->buttons.push_back(max); + this->buttons.push_back(exit); - buttons->addStretch(1); - buttons->addWidget(min); - buttons->addWidget(max); - buttons->addWidget(exit); + buttonLayout->addStretch(1); + buttonLayout->addWidget(min); + buttonLayout->addWidget(max); + buttonLayout->addWidget(exit); + buttonLayout->setSpacing(0); } this->layoutBase = new QWidget(this); - this->widgets.push_back(this->layoutBase); layout->addWidget(this->layoutBase); } @@ -136,8 +147,8 @@ QWidget *BaseWindow::getLayoutContainer() bool BaseWindow::hasCustomWindowFrame() { #ifdef Q_OS_WIN - // return this->enableCustomFrame; - return false; + return this->enableCustomFrame; +// return false; #else return false; #endif @@ -149,14 +160,19 @@ void BaseWindow::refreshTheme() palette.setColor(QPalette::Background, this->themeManager.windowBg); palette.setColor(QPalette::Foreground, this->themeManager.windowText); this->setPalette(palette); + + for (RippleEffectLabel *label : this->buttons) { + label->setMouseEffectColor(this->themeManager.windowText); + } } -void BaseWindow::addTitleBarButton(const QString &text) +void BaseWindow::addTitleBarButton(const QString &text, std::function onClicked) { RippleEffectLabel *label = new RippleEffectLabel; label->getLabel().setText(text); - this->widgets.push_back(label); + this->buttons.push_back(label); this->titlebarBox->insertWidget(2, label); + QObject::connect(label, &RippleEffectLabel::clicked, this, [onClicked] { onClicked(); }); } void BaseWindow::changeEvent(QEvent *) @@ -303,12 +319,16 @@ bool BaseWindow::nativeEvent(const QByteArray &eventType, void *message, long *r bool client = false; QPoint point(x - winrect.left, y - winrect.top); - for (QWidget *widget : this->widgets) { + for (QWidget *widget : this->buttons) { if (widget->geometry().contains(point)) { client = true; } } + if (this->layoutBase->geometry().contains(point)) { + client = true; + } + if (client) { *result = HTCLIENT; } else { @@ -325,9 +345,10 @@ bool BaseWindow::nativeEvent(const QByteArray &eventType, void *message, long *r break; } // end case WM_NCHITTEST case WM_CLOSE: { - if (this->enableCustomFrame) { - return close(); - } + // if (this->enableCustomFrame) { + // this->close(); + // } + return QWidget::nativeEvent(eventType, message, result); break; } default: @@ -335,9 +356,10 @@ bool BaseWindow::nativeEvent(const QByteArray &eventType, void *message, long *r } } -void BaseWindow::showEvent(QShowEvent *) +void BaseWindow::showEvent(QShowEvent *event) { - if (this->isVisible() && this->hasCustomWindowFrame()) { + if (!this->shown && this->isVisible() && this->hasCustomWindowFrame()) { + this->shown = true; SetWindowLongPtr((HWND)this->winId(), GWL_STYLE, WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_MAXIMIZEBOX | WS_MINIMIZEBOX); @@ -347,6 +369,8 @@ void BaseWindow::showEvent(QShowEvent *) SetWindowPos((HWND)this->winId(), 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); } + + BaseWidget::showEvent(event); } void BaseWindow::paintEvent(QPaintEvent *event) @@ -358,11 +382,16 @@ void BaseWindow::paintEvent(QPaintEvent *event) bool windowFocused = this->window() == QApplication::activeWindow(); + QLinearGradient gradient(0, 0, 10, 250); + gradient.setColorAt(1, this->themeManager.tabs.selected.backgrounds.unfocused.color()); + if (windowFocused) { - painter.setPen(this->themeManager.tabs.selected.backgrounds.regular.color()); + gradient.setColorAt(.4, this->themeManager.tabs.selected.backgrounds.regular.color()); } else { - painter.setPen(this->themeManager.tabs.selected.backgrounds.unfocused.color()); + gradient.setColorAt(.4, this->themeManager.tabs.selected.backgrounds.unfocused.color()); } + painter.setPen(QPen(QBrush(gradient), 1)); + painter.drawRect(0, 0, this->width() - 1, this->height() - 1); } } diff --git a/src/widgets/basewindow.hpp b/src/widgets/basewindow.hpp index a0024b7f1..16e2f2a2a 100644 --- a/src/widgets/basewindow.hpp +++ b/src/widgets/basewindow.hpp @@ -2,10 +2,13 @@ #include "basewidget.hpp" +#include + class QHBoxLayout; namespace chatterino { namespace widgets { +class RippleEffectLabel; class BaseWindow : public BaseWidget { @@ -17,7 +20,7 @@ public: QWidget *getLayoutContainer(); bool hasCustomWindowFrame(); - void addTitleBarButton(const QString &text); + void addTitleBarButton(const QString &text, std::function onClicked); void setStayInScreenRect(bool value); bool getStayInScreenRect() const; @@ -43,14 +46,15 @@ private: bool enableCustomFrame; bool stayInScreenRect = false; + bool shown = false; QHBoxLayout *titlebarBox; QWidget *titleLabel; - QWidget *minButton; - QWidget *maxButton; - QWidget *exitButton; + RippleEffectLabel *minButton; + RippleEffectLabel *maxButton; + RippleEffectLabel *exitButton; QWidget *layoutBase; - std::vector widgets; + std::vector buttons; }; } // namespace widgets } // namespace chatterino diff --git a/src/widgets/helper/rippleeffectbutton.cpp b/src/widgets/helper/rippleeffectbutton.cpp index a2c46c8fe..6ce8d243f 100644 --- a/src/widgets/helper/rippleeffectbutton.cpp +++ b/src/widgets/helper/rippleeffectbutton.cpp @@ -57,6 +57,8 @@ void RippleEffectButton::paintEvent(QPaintEvent *) void RippleEffectButton::fancyPaint(QPainter &painter) { + painter.setRenderHint(QPainter::HighQualityAntialiasing); + painter.setRenderHint(QPainter::Antialiasing); QColor c; if (this->mouseEffectColor) { diff --git a/src/widgets/notebook.cpp b/src/widgets/notebook.cpp index e9b2248f1..1849f6341 100644 --- a/src/widgets/notebook.cpp +++ b/src/widgets/notebook.cpp @@ -1,7 +1,7 @@ #include "widgets/notebook.hpp" #include "debug/log.hpp" #include "singletons/thememanager.hpp" -#include "widgets/accountswitchpopupwidget.hpp" +#include "singletons/windowmanager.hpp" #include "widgets/helper/notebookbutton.hpp" #include "widgets/helper/notebooktab.hpp" #include "widgets/settingsdialog.hpp" @@ -277,31 +277,13 @@ void Notebook::resizeEvent(QResizeEvent *) void Notebook::settingsButtonClicked() { - QTimer::singleShot(80, [this] { SettingsDialog::showDialog(); }); + singletons::WindowManager::getInstance().showSettingsDialog(); } void Notebook::usersButtonClicked() { - static QWidget *lastFocusedWidget = nullptr; - static AccountSwitchPopupWidget *w = new AccountSwitchPopupWidget(this); - - if (w->hasFocus()) { - w->hide(); - if (lastFocusedWidget) { - lastFocusedWidget->setFocus(); - } - return; - } - - lastFocusedWidget = this->focusWidget(); - - w->refresh(); - - QPoint buttonPos = this->userButton.rect().bottomRight(); - w->move(buttonPos.x(), buttonPos.y()); - - w->show(); - w->setFocus(); + singletons::WindowManager::getInstance().showAccountSelectPopup( + this->mapToGlobal(this->userButton.rect().bottomRight())); } void Notebook::addPageButtonClicked() diff --git a/src/widgets/settingspages/appearancepage.cpp b/src/widgets/settingspages/appearancepage.cpp index 3847479f9..db080d632 100644 --- a/src/widgets/settingspages/appearancepage.cpp +++ b/src/widgets/settingspages/appearancepage.cpp @@ -44,8 +44,10 @@ AppearancePage::AppearancePage() form->addRow("Font:", this->createFontChanger()); form->addRow("Tab bar:", this->createCheckBox(TAB_X, settings.hideTabX)); +#ifndef USEWINSDK form->addRow("", this->createCheckBox(TAB_PREF, settings.hidePreferencesButton)); form->addRow("", this->createCheckBox(TAB_USER, settings.hideUserButton)); +#endif form->addRow("Scrolling:", this->createCheckBox(SCROLL_SMOOTH, settings.enableSmoothScrolling)); form->addRow("", this->createCheckBox(SCROLL_NEWMSG, settings.enableSmoothScrollingNewMessages)); @@ -59,6 +61,7 @@ AppearancePage::AppearancePage() { tbox.emplace("timestamp format (a = am/pm):"); tbox.append(this->createComboBox({TIMESTAMP_FORMATS}, settings.timestampFormat)); + tbox->addStretch(1); } messages.append(this->createCheckBox("Show badges", settings.showBadges)); messages.append(this->createCheckBox("Seperate messages", settings.seperateMessages)); diff --git a/src/widgets/settingspages/moderationpage.cpp b/src/widgets/settingspages/moderationpage.cpp index 0ab611288..625661643 100644 --- a/src/widgets/settingspages/moderationpage.cpp +++ b/src/widgets/settingspages/moderationpage.cpp @@ -1,5 +1,6 @@ #include "moderationpage.hpp" +#include #include #include #include @@ -18,22 +19,33 @@ ModerationPage::ModerationPage() singletons::SettingManager &settings = singletons::SettingManager::getInstance(); util::LayoutCreator layoutCreator(this); - auto layout = layoutCreator.emplace().withoutMargin(); + auto layout = layoutCreator.setLayoutType(); { // clang-format off - auto label = layout.emplace("In channels that you moderate there is a button to enable moderation mode.\n\nOne action per line. {user} will be replaced with the username.\nExample `/timeout {user} 120`"); + auto label = layout.emplace("Click the moderation mod button () in a channel that you moderate to enable moderator mode.
"); label->setWordWrap(true); + label->setStyleSheet("color: #bbb"); // clang-format on - auto text = layout.emplace().getElement(); + auto modButtons = + layout.emplace("Custom moderator buttons").setLayoutType(); + { + auto label2 = + modButtons.emplace("One action per line. {user} will be replaced with the " + "username.
Example `/timeout {user} 120`
"); + label2->setWordWrap(true); - text->setPlainText(settings.moderationActions); + auto text = modButtons.emplace().getElement(); - QObject::connect(text, &QTextEdit::textChanged, this, - [this] { this->itemsChangedTimer.start(200); }); + text->setPlainText(settings.moderationActions); - QObject::connect(&this->itemsChangedTimer, &QTimer::timeout, this, - [text, &settings]() { settings.moderationActions = text->toPlainText(); }); + QObject::connect(text, &QTextEdit::textChanged, this, + [this] { this->itemsChangedTimer.start(200); }); + + QObject::connect(&this->itemsChangedTimer, &QTimer::timeout, this, [text, &settings]() { + settings.moderationActions = text->toPlainText(); + }); + } } // ---- misc diff --git a/src/widgets/window.cpp b/src/widgets/window.cpp index 8a5030430..8c27e3d46 100644 --- a/src/widgets/window.cpp +++ b/src/widgets/window.cpp @@ -4,6 +4,8 @@ #include "singletons/ircmanager.hpp" #include "singletons/settingsmanager.hpp" #include "singletons/thememanager.hpp" +#include "singletons/windowmanager.hpp" +#include "widgets/accountswitchpopupwidget.hpp" #include "widgets/helper/shortcut.hpp" #include "widgets/notebook.hpp" #include "widgets/settingsdialog.hpp" @@ -35,8 +37,11 @@ Window::Window(const QString &windowName, singletons::ThemeManager &_themeManage }); if (this->hasCustomWindowFrame()) { - this->addTitleBarButton("Preferences"); - this->addTitleBarButton("User"); + this->addTitleBarButton( + "preferences", [] { singletons::WindowManager::getInstance().showSettingsDialog(); }); + this->addTitleBarButton("user", [this] { + singletons::WindowManager::getInstance().showAccountSelectPopup(QCursor::pos()); + }); } QVBoxLayout *layout = new QVBoxLayout(this);