added custom window frame for windows

This commit is contained in:
fourtf 2018-01-24 15:08:22 +01:00
parent 2b94c4cd33
commit 36b010e046
9 changed files with 134 additions and 63 deletions

View file

@ -2,6 +2,8 @@
#include "debug/log.hpp" #include "debug/log.hpp"
#include "singletons/fontmanager.hpp" #include "singletons/fontmanager.hpp"
#include "singletons/thememanager.hpp" #include "singletons/thememanager.hpp"
#include "widgets/accountswitchpopupwidget.hpp"
#include "widgets/settingsdialog.hpp"
#include <QDebug> #include <QDebug>
@ -14,6 +16,35 @@ WindowManager &WindowManager::getInstance()
return instance; 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) WindowManager::WindowManager(ThemeManager &_themeManager)
: themeManager(_themeManager) : themeManager(_themeManager)
{ {

View file

@ -14,6 +14,9 @@ class WindowManager
public: public:
static WindowManager &getInstance(); static WindowManager &getInstance();
void showSettingsDialog();
void showAccountSelectPopup(QPoint point);
void initMainWindow(); void initMainWindow();
void layoutVisibleChatWidgets(Channel *channel = nullptr); void layoutVisibleChatWidgets(Channel *channel = nullptr);
void repaintVisibleChatWidgets(Channel *channel = nullptr); void repaintVisibleChatWidgets(Channel *channel = nullptr);

View file

@ -59,16 +59,17 @@ void BaseWindow::init()
// CUSTOM WINDOW FRAME // CUSTOM WINDOW FRAME
QVBoxLayout *layout = new QVBoxLayout; QVBoxLayout *layout = new QVBoxLayout;
layout->setMargin(1); layout->setMargin(1);
layout->setSpacing(0);
this->setLayout(layout); this->setLayout(layout);
{ {
QHBoxLayout *buttons = this->titlebarBox = new QHBoxLayout; QHBoxLayout *buttonLayout = this->titlebarBox = new QHBoxLayout;
buttons->setMargin(0); buttonLayout->setMargin(0);
layout->addLayout(buttons); layout->addLayout(buttonLayout);
// title // title
QLabel *titleLabel = new QLabel("Chatterino"); QLabel *title = new QLabel(" Chatterino");
buttons->addWidget(titleLabel); buttonLayout->addWidget(title);
this->titleLabel = titleLabel; this->titleLabel = title;
// buttons // buttons
RippleEffectLabel *min = new RippleEffectLabel; RippleEffectLabel *min = new RippleEffectLabel;
@ -81,21 +82,31 @@ void BaseWindow::init()
exit->setFixedSize(46, 30); exit->setFixedSize(46, 30);
exit->getLabel().setText("exit"); 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->minButton = min;
this->maxButton = max; this->maxButton = max;
this->exitButton = exit; this->exitButton = exit;
this->widgets.push_back(min); this->buttons.push_back(min);
this->widgets.push_back(max); this->buttons.push_back(max);
this->widgets.push_back(exit); this->buttons.push_back(exit);
buttons->addStretch(1); buttonLayout->addStretch(1);
buttons->addWidget(min); buttonLayout->addWidget(min);
buttons->addWidget(max); buttonLayout->addWidget(max);
buttons->addWidget(exit); buttonLayout->addWidget(exit);
buttonLayout->setSpacing(0);
} }
this->layoutBase = new QWidget(this); this->layoutBase = new QWidget(this);
this->widgets.push_back(this->layoutBase);
layout->addWidget(this->layoutBase); layout->addWidget(this->layoutBase);
} }
@ -136,8 +147,8 @@ QWidget *BaseWindow::getLayoutContainer()
bool BaseWindow::hasCustomWindowFrame() bool BaseWindow::hasCustomWindowFrame()
{ {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
// return this->enableCustomFrame; return this->enableCustomFrame;
return false; // return false;
#else #else
return false; return false;
#endif #endif
@ -149,14 +160,19 @@ void BaseWindow::refreshTheme()
palette.setColor(QPalette::Background, this->themeManager.windowBg); palette.setColor(QPalette::Background, this->themeManager.windowBg);
palette.setColor(QPalette::Foreground, this->themeManager.windowText); palette.setColor(QPalette::Foreground, this->themeManager.windowText);
this->setPalette(palette); 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<void()> onClicked)
{ {
RippleEffectLabel *label = new RippleEffectLabel; RippleEffectLabel *label = new RippleEffectLabel;
label->getLabel().setText(text); label->getLabel().setText(text);
this->widgets.push_back(label); this->buttons.push_back(label);
this->titlebarBox->insertWidget(2, label); this->titlebarBox->insertWidget(2, label);
QObject::connect(label, &RippleEffectLabel::clicked, this, [onClicked] { onClicked(); });
} }
void BaseWindow::changeEvent(QEvent *) void BaseWindow::changeEvent(QEvent *)
@ -303,12 +319,16 @@ bool BaseWindow::nativeEvent(const QByteArray &eventType, void *message, long *r
bool client = false; bool client = false;
QPoint point(x - winrect.left, y - winrect.top); QPoint point(x - winrect.left, y - winrect.top);
for (QWidget *widget : this->widgets) { for (QWidget *widget : this->buttons) {
if (widget->geometry().contains(point)) { if (widget->geometry().contains(point)) {
client = true; client = true;
} }
} }
if (this->layoutBase->geometry().contains(point)) {
client = true;
}
if (client) { if (client) {
*result = HTCLIENT; *result = HTCLIENT;
} else { } else {
@ -325,9 +345,10 @@ bool BaseWindow::nativeEvent(const QByteArray &eventType, void *message, long *r
break; break;
} // end case WM_NCHITTEST } // end case WM_NCHITTEST
case WM_CLOSE: { case WM_CLOSE: {
if (this->enableCustomFrame) { // if (this->enableCustomFrame) {
return close(); // this->close();
} // }
return QWidget::nativeEvent(eventType, message, result);
break; break;
} }
default: 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, SetWindowLongPtr((HWND)this->winId(), GWL_STYLE,
WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_MAXIMIZEBOX | WS_MINIMIZEBOX); 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, SetWindowPos((HWND)this->winId(), 0, 0, 0, 0, 0,
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
} }
BaseWidget::showEvent(event);
} }
void BaseWindow::paintEvent(QPaintEvent *event) void BaseWindow::paintEvent(QPaintEvent *event)
@ -358,11 +382,16 @@ void BaseWindow::paintEvent(QPaintEvent *event)
bool windowFocused = this->window() == QApplication::activeWindow(); bool windowFocused = this->window() == QApplication::activeWindow();
QLinearGradient gradient(0, 0, 10, 250);
gradient.setColorAt(1, this->themeManager.tabs.selected.backgrounds.unfocused.color());
if (windowFocused) { if (windowFocused) {
painter.setPen(this->themeManager.tabs.selected.backgrounds.regular.color()); gradient.setColorAt(.4, this->themeManager.tabs.selected.backgrounds.regular.color());
} else { } 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); painter.drawRect(0, 0, this->width() - 1, this->height() - 1);
} }
} }

View file

@ -2,10 +2,13 @@
#include "basewidget.hpp" #include "basewidget.hpp"
#include <functional>
class QHBoxLayout; class QHBoxLayout;
namespace chatterino { namespace chatterino {
namespace widgets { namespace widgets {
class RippleEffectLabel;
class BaseWindow : public BaseWidget class BaseWindow : public BaseWidget
{ {
@ -17,7 +20,7 @@ public:
QWidget *getLayoutContainer(); QWidget *getLayoutContainer();
bool hasCustomWindowFrame(); bool hasCustomWindowFrame();
void addTitleBarButton(const QString &text); void addTitleBarButton(const QString &text, std::function<void()> onClicked);
void setStayInScreenRect(bool value); void setStayInScreenRect(bool value);
bool getStayInScreenRect() const; bool getStayInScreenRect() const;
@ -43,14 +46,15 @@ private:
bool enableCustomFrame; bool enableCustomFrame;
bool stayInScreenRect = false; bool stayInScreenRect = false;
bool shown = false;
QHBoxLayout *titlebarBox; QHBoxLayout *titlebarBox;
QWidget *titleLabel; QWidget *titleLabel;
QWidget *minButton; RippleEffectLabel *minButton;
QWidget *maxButton; RippleEffectLabel *maxButton;
QWidget *exitButton; RippleEffectLabel *exitButton;
QWidget *layoutBase; QWidget *layoutBase;
std::vector<QWidget *> widgets; std::vector<RippleEffectLabel *> buttons;
}; };
} // namespace widgets } // namespace widgets
} // namespace chatterino } // namespace chatterino

View file

@ -57,6 +57,8 @@ void RippleEffectButton::paintEvent(QPaintEvent *)
void RippleEffectButton::fancyPaint(QPainter &painter) void RippleEffectButton::fancyPaint(QPainter &painter)
{ {
painter.setRenderHint(QPainter::HighQualityAntialiasing);
painter.setRenderHint(QPainter::Antialiasing);
QColor c; QColor c;
if (this->mouseEffectColor) { if (this->mouseEffectColor) {

View file

@ -1,7 +1,7 @@
#include "widgets/notebook.hpp" #include "widgets/notebook.hpp"
#include "debug/log.hpp" #include "debug/log.hpp"
#include "singletons/thememanager.hpp" #include "singletons/thememanager.hpp"
#include "widgets/accountswitchpopupwidget.hpp" #include "singletons/windowmanager.hpp"
#include "widgets/helper/notebookbutton.hpp" #include "widgets/helper/notebookbutton.hpp"
#include "widgets/helper/notebooktab.hpp" #include "widgets/helper/notebooktab.hpp"
#include "widgets/settingsdialog.hpp" #include "widgets/settingsdialog.hpp"
@ -277,31 +277,13 @@ void Notebook::resizeEvent(QResizeEvent *)
void Notebook::settingsButtonClicked() void Notebook::settingsButtonClicked()
{ {
QTimer::singleShot(80, [this] { SettingsDialog::showDialog(); }); singletons::WindowManager::getInstance().showSettingsDialog();
} }
void Notebook::usersButtonClicked() void Notebook::usersButtonClicked()
{ {
static QWidget *lastFocusedWidget = nullptr; singletons::WindowManager::getInstance().showAccountSelectPopup(
static AccountSwitchPopupWidget *w = new AccountSwitchPopupWidget(this); this->mapToGlobal(this->userButton.rect().bottomRight()));
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();
} }
void Notebook::addPageButtonClicked() void Notebook::addPageButtonClicked()

View file

@ -44,8 +44,10 @@ AppearancePage::AppearancePage()
form->addRow("Font:", this->createFontChanger()); form->addRow("Font:", this->createFontChanger());
form->addRow("Tab bar:", this->createCheckBox(TAB_X, settings.hideTabX)); 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_PREF, settings.hidePreferencesButton));
form->addRow("", this->createCheckBox(TAB_USER, settings.hideUserButton)); form->addRow("", this->createCheckBox(TAB_USER, settings.hideUserButton));
#endif
form->addRow("Scrolling:", this->createCheckBox(SCROLL_SMOOTH, settings.enableSmoothScrolling)); form->addRow("Scrolling:", this->createCheckBox(SCROLL_SMOOTH, settings.enableSmoothScrolling));
form->addRow("", this->createCheckBox(SCROLL_NEWMSG, settings.enableSmoothScrollingNewMessages)); form->addRow("", this->createCheckBox(SCROLL_NEWMSG, settings.enableSmoothScrollingNewMessages));
@ -59,6 +61,7 @@ AppearancePage::AppearancePage()
{ {
tbox.emplace<QLabel>("timestamp format (a = am/pm):"); tbox.emplace<QLabel>("timestamp format (a = am/pm):");
tbox.append(this->createComboBox({TIMESTAMP_FORMATS}, settings.timestampFormat)); tbox.append(this->createComboBox({TIMESTAMP_FORMATS}, settings.timestampFormat));
tbox->addStretch(1);
} }
messages.append(this->createCheckBox("Show badges", settings.showBadges)); messages.append(this->createCheckBox("Show badges", settings.showBadges));
messages.append(this->createCheckBox("Seperate messages", settings.seperateMessages)); messages.append(this->createCheckBox("Seperate messages", settings.seperateMessages));

View file

@ -1,5 +1,6 @@
#include "moderationpage.hpp" #include "moderationpage.hpp"
#include <QGroupBox>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
#include <QListView> #include <QListView>
@ -18,22 +19,33 @@ ModerationPage::ModerationPage()
singletons::SettingManager &settings = singletons::SettingManager::getInstance(); singletons::SettingManager &settings = singletons::SettingManager::getInstance();
util::LayoutCreator<ModerationPage> layoutCreator(this); util::LayoutCreator<ModerationPage> layoutCreator(this);
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin(); auto layout = layoutCreator.setLayoutType<QVBoxLayout>();
{ {
// clang-format off // clang-format off
auto label = layout.emplace<QLabel>("In channels that you moderate there is a button <insert image of button here> to enable moderation mode.\n\nOne action per line. {user} will be replaced with the username.\nExample `/timeout {user} 120`"); auto label = layout.emplace<QLabel>("Click the moderation mod button (<img width='18' height='18' src=':/images/moderatormode_disabled.png'>) in a channel that you moderate to enable moderator mode.<br>");
label->setWordWrap(true); label->setWordWrap(true);
label->setStyleSheet("color: #bbb");
// clang-format on // clang-format on
auto text = layout.emplace<QTextEdit>().getElement(); auto modButtons =
layout.emplace<QGroupBox>("Custom moderator buttons").setLayoutType<QVBoxLayout>();
{
auto label2 =
modButtons.emplace<QLabel>("One action per line. {user} will be replaced with the "
"username.<br>Example `/timeout {user} 120`<br>");
label2->setWordWrap(true);
auto text = modButtons.emplace<QTextEdit>().getElement();
text->setPlainText(settings.moderationActions); text->setPlainText(settings.moderationActions);
QObject::connect(text, &QTextEdit::textChanged, this, QObject::connect(text, &QTextEdit::textChanged, this,
[this] { this->itemsChangedTimer.start(200); }); [this] { this->itemsChangedTimer.start(200); });
QObject::connect(&this->itemsChangedTimer, &QTimer::timeout, this, QObject::connect(&this->itemsChangedTimer, &QTimer::timeout, this, [text, &settings]() {
[text, &settings]() { settings.moderationActions = text->toPlainText(); }); settings.moderationActions = text->toPlainText();
});
}
} }
// ---- misc // ---- misc

View file

@ -4,6 +4,8 @@
#include "singletons/ircmanager.hpp" #include "singletons/ircmanager.hpp"
#include "singletons/settingsmanager.hpp" #include "singletons/settingsmanager.hpp"
#include "singletons/thememanager.hpp" #include "singletons/thememanager.hpp"
#include "singletons/windowmanager.hpp"
#include "widgets/accountswitchpopupwidget.hpp"
#include "widgets/helper/shortcut.hpp" #include "widgets/helper/shortcut.hpp"
#include "widgets/notebook.hpp" #include "widgets/notebook.hpp"
#include "widgets/settingsdialog.hpp" #include "widgets/settingsdialog.hpp"
@ -35,8 +37,11 @@ Window::Window(const QString &windowName, singletons::ThemeManager &_themeManage
}); });
if (this->hasCustomWindowFrame()) { if (this->hasCustomWindowFrame()) {
this->addTitleBarButton("Preferences"); this->addTitleBarButton(
this->addTitleBarButton("User"); "preferences", [] { singletons::WindowManager::getInstance().showSettingsDialog(); });
this->addTitleBarButton("user", [this] {
singletons::WindowManager::getInstance().showAccountSelectPopup(QCursor::pos());
});
} }
QVBoxLayout *layout = new QVBoxLayout(this); QVBoxLayout *layout = new QVBoxLayout(this);