From dafbda6a4a8cff655774faac78e0d08b799be839 Mon Sep 17 00:00:00 2001 From: fourtf Date: Wed, 23 May 2018 04:22:17 +0200 Subject: [PATCH] asdf --- src/messages/layouts/messagelayoutelement.cpp | 4 +- src/messages/messageelement.cpp | 4 +- src/messages/messageelement.hpp | 2 +- src/providers/twitch/twitchmessagebuilder.cpp | 8 +- src/singletons/fontmanager.cpp | 174 ++++--- src/singletons/fontmanager.hpp | 144 ++---- src/singletons/thememanager.cpp | 60 ++- src/singletons/thememanager.hpp | 11 +- src/singletons/windowmanager.cpp | 22 +- src/widgets/helper/label.hpp | 2 +- src/widgets/helper/notebookbutton.cpp | 6 +- src/widgets/helper/notebooktab.cpp | 486 +++--------------- src/widgets/helper/notebooktab.hpp | 77 +-- src/widgets/helper/splitinput.cpp | 33 +- src/widgets/notebook.cpp | 340 ++---------- src/widgets/notebook.hpp | 58 +-- src/widgets/settingspages/appearancepage.cpp | 14 +- src/widgets/splitcontainer.cpp | 37 +- src/widgets/splitcontainer.hpp | 8 +- src/widgets/tooltipwidget.cpp | 2 +- src/widgets/window.cpp | 9 +- src/widgets/window.hpp | 6 +- 22 files changed, 404 insertions(+), 1103 deletions(-) diff --git a/src/messages/layouts/messagelayoutelement.cpp b/src/messages/layouts/messagelayoutelement.cpp index d2c0d2ccc..788e23ee1 100644 --- a/src/messages/layouts/messagelayoutelement.cpp +++ b/src/messages/layouts/messagelayoutelement.cpp @@ -188,7 +188,7 @@ int TextLayoutElement::getMouseOverIndex(const QPoint &abs) auto app = getApp(); - QFontMetrics &metrics = app->fonts->getFontMetrics(this->style, this->scale); + QFontMetrics metrics = app->fonts->getFontMetrics(this->style, this->scale); int x = this->getRect().left(); @@ -209,7 +209,7 @@ int TextLayoutElement::getXFromIndex(int index) { auto app = getApp(); - QFontMetrics &metrics = app->fonts->getFontMetrics(this->style, this->scale); + QFontMetrics metrics = app->fonts->getFontMetrics(this->style, this->scale); if (index <= 0) { return this->getRect().left(); diff --git a/src/messages/messageelement.cpp b/src/messages/messageelement.cpp index dc288ed3a..4aa90c52e 100644 --- a/src/messages/messageelement.cpp +++ b/src/messages/messageelement.cpp @@ -139,7 +139,7 @@ void TextElement::addToContainer(MessageLayoutContainer &container, MessageEleme auto app = getApp(); if (_flags & this->getFlags()) { - QFontMetrics &metrics = app->fonts->getFontMetrics(this->style, container.getScale()); + QFontMetrics metrics = app->fonts->getFontMetrics(this->style, container.getScale()); for (Word &word : this->words) { auto getTextLayoutElement = [&](QString text, int width, bool trailingSpace) { @@ -242,7 +242,7 @@ TextElement *TimestampElement::formatTime(const QTime &time) QString format = locale.toString(time, getApp()->settings->timestampFormat); - return new TextElement(format, Flags::Timestamp, MessageColor::System, FontStyle::Medium); + return new TextElement(format, Flags::Timestamp, MessageColor::System, FontStyle::ChatMedium); } // TWITCH MODERATION diff --git a/src/messages/messageelement.hpp b/src/messages/messageelement.hpp index 79a78897e..fc2be5928 100644 --- a/src/messages/messageelement.hpp +++ b/src/messages/messageelement.hpp @@ -158,7 +158,7 @@ class TextElement : public MessageElement public: TextElement(const QString &text, MessageElement::Flags flags, const MessageColor &color = MessageColor::Text, - FontStyle style = FontStyle::Medium); + FontStyle style = FontStyle::ChatMedium); ~TextElement() override = default; void addToContainer(MessageLayoutContainer &container, MessageElement::Flags flags) override; diff --git a/src/providers/twitch/twitchmessagebuilder.cpp b/src/providers/twitch/twitchmessagebuilder.cpp index 760979dcc..2c6282736 100644 --- a/src/providers/twitch/twitchmessagebuilder.cpp +++ b/src/providers/twitch/twitchmessagebuilder.cpp @@ -361,14 +361,14 @@ void TwitchMessageBuilder::appendUsername() } else if (this->args.isReceivedWhisper) { // Sender username this->emplace(usernameText, MessageElement::Text, this->usernameColor, - FontStyle::MediumBold) + FontStyle::ChatMediumBold) ->setLink({Link::UserInfo, this->userName}); auto currentUser = app->accounts->Twitch.getCurrent(); // Separator this->emplace("->", MessageElement::Text, - app->themes->messages.textColors.system, FontStyle::Medium); + app->themes->messages.textColors.system, FontStyle::ChatMedium); QColor selfColor = currentUser->color; if (!selfColor.isValid()) { @@ -377,14 +377,14 @@ void TwitchMessageBuilder::appendUsername() // Your own username this->emplace(currentUser->getUserName() + ":", MessageElement::Text, - selfColor, FontStyle::MediumBold); + selfColor, FontStyle::ChatMediumBold); } else { if (!this->action) { usernameText += ":"; } this->emplace(usernameText, MessageElement::Text, this->usernameColor, - FontStyle::MediumBold) + FontStyle::ChatMediumBold) ->setLink({Link::UserInfo, this->userName}); } } diff --git a/src/singletons/fontmanager.cpp b/src/singletons/fontmanager.cpp index 59a5e874e..b25bc8b28 100644 --- a/src/singletons/fontmanager.cpp +++ b/src/singletons/fontmanager.cpp @@ -3,6 +3,8 @@ #include #include +#include "util/assertinguithread.hpp" + #ifdef Q_OS_WIN32 #define DEFAULT_FONT_FAMILY "Segoe UI" #define DEFAULT_FONT_SIZE 10 @@ -20,86 +22,110 @@ namespace chatterino { namespace singletons { FontManager::FontManager() - : currentFontFamily("/appearance/currentFontFamily", DEFAULT_FONT_FAMILY) - , currentFontSize("/appearance/currentFontSize", DEFAULT_FONT_SIZE) -// , currentFont(this->currentFontFamily.getValue().c_str(), currentFontSize.getValue()) + : chatFontFamily("/appearance/currentFontFamily", DEFAULT_FONT_FAMILY) + , chatFontSize("/appearance/currentFontSize", DEFAULT_FONT_SIZE) { qDebug() << "init FontManager"; - this->currentFontFamily.connect([this](const std::string &newValue, auto) { + this->chatFontFamily.connect([this](const std::string &newValue, auto) { + util::assertInGuiThread(); + this->incGeneration(); - // this->currentFont.setFamily(newValue.c_str()); - this->currentFontByScale.clear(); - this->fontChanged.invoke(); - }); - - this->currentFontSize.connect([this](const int &newValue, auto) { - this->incGeneration(); - // this->currentFont.setSize(newValue); - this->currentFontByScale.clear(); - this->fontChanged.invoke(); - }); -} - -QFont &FontManager::getFont(FontManager::Type type, float scale) -{ - // return this->currentFont.getFont(type); - return this->getCurrentFont(scale).getFont(type); -} - -QFontMetrics &FontManager::getFontMetrics(FontManager::Type type, float scale) -{ - // return this->currentFont.getFontMetrics(type); - return this->getCurrentFont(scale).getFontMetrics(type); -} - -FontManager::FontData &FontManager::Font::getFontData(FontManager::Type type) -{ - switch (type) { - case Tiny: - return this->tiny; - case Small: - return this->small; - case MediumSmall: - return this->mediumSmall; - case Medium: - return this->medium; - case MediumBold: - return this->mediumBold; - case MediumItalic: - return this->mediumItalic; - case Large: - return this->large; - case VeryLarge: - return this->veryLarge; - default: - qDebug() << "Unknown font type:" << type << ", defaulting to medium"; - return this->medium; - } -} - -QFont &FontManager::Font::getFont(Type type) -{ - return this->getFontData(type).font; -} - -QFontMetrics &FontManager::Font::getFontMetrics(Type type) -{ - return this->getFontData(type).metrics; -} - -FontManager::Font &FontManager::getCurrentFont(float scale) -{ - for (auto it = this->currentFontByScale.begin(); it != this->currentFontByScale.end(); it++) { - if (it->first == scale) { - return it->second; + for (auto &map : this->fontsByType) { + map.clear(); } - } - this->currentFontByScale.push_back( - std::make_pair(scale, Font(this->currentFontFamily.getValue().c_str(), - this->currentFontSize.getValue() * scale))); + this->fontChanged.invoke(); + }); - return this->currentFontByScale.back().second; + this->chatFontSize.connect([this](const int &newValue, auto) { + util::assertInGuiThread(); + + this->incGeneration(); + for (auto &map : this->fontsByType) { + map.clear(); + } + this->fontChanged.invoke(); + }); + + this->fontsByType.resize((size_t)EndType); +} + +QFont FontManager::getFont(FontManager::Type type, float scale) +{ + return this->getOrCreateFontData(type, scale).font; +} + +QFontMetrics FontManager::getFontMetrics(FontManager::Type type, float scale) +{ + return this->getOrCreateFontData(type, scale).metrics; +} + +int FontManager::getGeneration() const +{ + return this->generation; +} + +void FontManager::incGeneration() +{ + this->generation++; +} + +FontManager::FontData &FontManager::getOrCreateFontData(Type type, float scale) +{ + util::assertInGuiThread(); + + assert(type >= 0 && type < EndType); + + auto &map = this->fontsByType[(size_t)type]; + + // find element + auto it = map.find(scale); + if (it != map.end()) { + // return if found + + qDebug() << it->second.font; + return it->second; + } + + // emplace new element + auto result = map.emplace(scale, this->createFontData(type, scale)); + assert(result.second); + + return result.first->second; +} + +FontManager::FontData FontManager::createFontData(Type type, float scale) +{ + // check if it's a chat (scale the setting) + if (type >= ChatStart && type <= ChatEnd) { + static std::unordered_map sizeScale{ + {ChatSmall, {0.6f, false, QFont::Normal}}, + {ChatMediumSmall, {0.8f, false, QFont::Normal}}, + {ChatMedium, {1, false, QFont::Normal}}, + {ChatMediumBold, {1, false, QFont::Medium}}, + {ChatMediumItalic, {1, true, QFont::Normal}}, + {ChatLarge, {1.2f, false, QFont::Normal}}, + {ChatVeryLarge, {1.4f, false, QFont::Normal}}, + }; + + auto data = sizeScale[type]; + return FontData(QFont(QString::fromStdString(this->chatFontFamily.getValue()), + this->chatFontSize.getValue() * data.scale * scale, data.weight, + data.italic)); + } + + // normal Ui font (use pt size) + { + static std::unordered_map defaultSize{ + {Tiny, {8, "Monospace", false, QFont::Normal}}, + {UiMedium, {12, DEFAULT_FONT_FAMILY, false, QFont::Normal}}, + {UiTabs, {9, "Segoe UI", false, QFont::Normal}}, + }; + + UiFontData &data = defaultSize[type]; + QFont font(data.name, data.size * scale, data.weight, data.italic); + return FontData(font); + } } } // namespace singletons diff --git a/src/singletons/fontmanager.hpp b/src/singletons/fontmanager.hpp index 8f7d4eaab..1a6ddf811 100644 --- a/src/singletons/fontmanager.hpp +++ b/src/singletons/fontmanager.hpp @@ -3,136 +3,82 @@ #include #include #include +#include +#include #include #include +#include namespace chatterino { namespace singletons { -class FontManager +class FontManager : boost::noncopyable { public: FontManager(); - FontManager(const FontManager &) = delete; - FontManager(FontManager &&) = delete; - ~FontManager() = delete; - + // font data gets set in createFontData(...) enum Type : uint8_t { Tiny, - Small, - MediumSmall, - Medium, - MediumBold, - MediumItalic, - Large, - VeryLarge, + ChatSmall, + ChatMediumSmall, + ChatMedium, + ChatMediumBold, + ChatMediumItalic, + ChatLarge, + ChatVeryLarge, + + UiMedium, + UiTabs, + + // don't remove this value + EndType, + + // make sure to update these values accordingly! + ChatStart = ChatSmall, + ChatEnd = ChatVeryLarge, }; - QFont &getFont(Type type, float scale); - QFontMetrics &getFontMetrics(Type type, float scale); + QFont getFont(Type type, float scale); + QFontMetrics getFontMetrics(Type type, float scale); - int getGeneration() const - { - return this->generation; - } + int getGeneration() const; + void incGeneration(); - void incGeneration() - { - this->generation++; - } - - pajlada::Settings::Setting currentFontFamily; - pajlada::Settings::Setting currentFontSize; + pajlada::Settings::Setting chatFontFamily; + pajlada::Settings::Setting chatFontSize; pajlada::Signals::NoArgSignal fontChanged; private: struct FontData { - FontData(QFont &&_font) + FontData(const QFont &_font) : font(_font) - , metrics(this->font) + , metrics(_font) { } - QFont font; - QFontMetrics metrics; + const QFont font; + const QFontMetrics metrics; }; - struct Font { - Font() = delete; - - Font(const char *fontFamilyName, int mediumSize) - : tiny(QFont("Monospace", 8)) - , small(QFont(fontFamilyName, mediumSize - 4)) - , mediumSmall(QFont(fontFamilyName, mediumSize - 2)) - , medium(QFont(fontFamilyName, mediumSize)) - , mediumBold(QFont(fontFamilyName, mediumSize, QFont::DemiBold)) - , mediumItalic(QFont(fontFamilyName, mediumSize, -1, true)) - , large(QFont(fontFamilyName, mediumSize)) - , veryLarge(QFont(fontFamilyName, mediumSize)) - { - tiny.font.setStyleHint(QFont::TypeWriter); - } - - void setFamily(const char *newFamily) - { - this->small.font.setFamily(newFamily); - this->mediumSmall.font.setFamily(newFamily); - this->medium.font.setFamily(newFamily); - this->mediumBold.font.setFamily(newFamily); - this->mediumItalic.font.setFamily(newFamily); - this->large.font.setFamily(newFamily); - this->veryLarge.font.setFamily(newFamily); - - this->updateMetrics(); - } - - void setSize(int newMediumSize) - { - this->small.font.setPointSize(newMediumSize - 4); - this->mediumSmall.font.setPointSize(newMediumSize - 2); - this->medium.font.setPointSize(newMediumSize); - this->mediumBold.font.setPointSize(newMediumSize); - this->mediumItalic.font.setPointSize(newMediumSize); - this->large.font.setPointSize(newMediumSize + 2); - this->veryLarge.font.setPointSize(newMediumSize + 4); - - this->updateMetrics(); - } - - void updateMetrics() - { - this->small.metrics = QFontMetrics(this->small.font); - this->mediumSmall.metrics = QFontMetrics(this->mediumSmall.font); - this->medium.metrics = QFontMetrics(this->medium.font); - this->mediumBold.metrics = QFontMetrics(this->mediumBold.font); - this->mediumItalic.metrics = QFontMetrics(this->mediumItalic.font); - this->large.metrics = QFontMetrics(this->large.font); - this->veryLarge.metrics = QFontMetrics(this->veryLarge.font); - } - - FontData &getFontData(Type type); - - QFont &getFont(Type type); - QFontMetrics &getFontMetrics(Type type); - - FontData tiny; - FontData small; - FontData mediumSmall; - FontData medium; - FontData mediumBold; - FontData mediumItalic; - FontData large; - FontData veryLarge; + struct ChatFontData { + float scale; + bool italic; + QFont::Weight weight; }; - Font &getCurrentFont(float scale); + struct UiFontData { + float size; + const char *name; + bool italic; + QFont::Weight weight; + }; - // Future plans: - // Could have multiple fonts in here, such as "Menu font", "Application font", "Chat font" + FontData &getOrCreateFontData(Type type, float scale); + FontData createFontData(Type type, float scale); - std::list> currentFontByScale; + std::vector> fontsByType; int generation = 0; }; diff --git a/src/singletons/thememanager.cpp b/src/singletons/thememanager.cpp index 8296dbefc..c2a81860d 100644 --- a/src/singletons/thememanager.cpp +++ b/src/singletons/thememanager.cpp @@ -52,7 +52,6 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) isLight = multiplier > 0; bool lightWin = isLight; - QColor none(0, 0, 0, 0); QColor themeColor = QColor::fromHslF(hue, 0.43, 0.5); QColor themeColorNoSat = QColor::fromHslF(hue, 0, 0.5); @@ -69,7 +68,7 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) #ifdef Q_OS_LINUX this->window.background = lightWin ? "#fff" : QColor(61, 60, 56); #else - this->window.background = lightWin ? "#fff" : "#444"; + this->window.background = lightWin ? "#fff" : "#111"; #endif QColor fg = this->window.text = lightWin ? "#000" : "#eee"; @@ -89,27 +88,48 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) /// TABS if (lightWin) { - this->tabs.regular = {fg, {bg, QColor("#ccc"), bg}}; + this->tabs.regular = {QColor("#444"), + {QColor("#fff"), QColor("#fff"), QColor("#fff")}, + {QColor("#fff"), QColor("#fff"), QColor("#fff")}}; this->tabs.newMessage = { - fg, - {QBrush(blendColors(themeColor, "#ccc", 0.9), Qt::FDiagPattern), - QBrush(blendColors(themeColor, "#ccc", 0.9), Qt::FDiagPattern), - QBrush(blendColors(themeColorNoSat, "#ccc", 0.9), Qt::FDiagPattern)}}; - this->tabs.highlighted = {fg, {QColor("#ccc"), QColor("#ccc"), QColor("#bbb")}}; - this->tabs.selected = {QColor("#fff"), - {QColor("#777"), QColor("#777"), QColor("#888")}}; - } else { - this->tabs.regular = {fg, {bg, QColor("#555"), bg}}; - this->tabs.newMessage = { - fg, - {QBrush(blendColors(themeColor, "#666", 0.7), Qt::FDiagPattern), - QBrush(blendColors(themeColor, "#666", 0.5), Qt::FDiagPattern), - QBrush(blendColors(themeColorNoSat, "#666", 0.7), Qt::FDiagPattern)}}; - this->tabs.highlighted = {fg, {QColor("#777"), QColor("#777"), QColor("#666")}}; + fg, {bg, QColor("#ccc"), bg}, {QColor("#aaa"), QColor("#aaa"), QColor("#aaa")}}; + this->tabs.highlighted = {fg, + {bg, QColor("#ccc"), bg}, + {QColor("#b60505"), QColor("#b60505"), QColor("#b60505")}}; this->tabs.selected = {QColor("#000"), - {QColor("#999"), QColor("#999"), QColor("#888")}}; + {QColor("#b4d7ff"), QColor("#b4d7ff"), QColor("#b4d7ff")}, + {QColor("#00aeef"), QColor("#00aeef"), QColor("#00aeef")}}; + } else { + this->tabs.regular = {QColor("#aaa"), + {QColor("#252525"), QColor("#252525"), QColor("#252525")}, + {QColor("#444"), QColor("#444"), QColor("#444")}}; + this->tabs.newMessage = {fg, + {QColor("#252525"), QColor("#252525"), QColor("#252525")}, + {QColor("#888"), QColor("#888"), QColor("#888")}}; + this->tabs.highlighted = {fg, + {QColor("#252525"), QColor("#252525"), QColor("#252525")}, + {QColor("#ee6166"), QColor("#ee6166"), QColor("#ee6166")}}; + + this->tabs.selected = {QColor("#fff"), + {QColor("#555555"), QColor("#555555"), QColor("#555555")}, + {QColor("#00aeef"), QColor("#00aeef"), QColor("#00aeef")}}; } + // this->tabs.newMessage = { + // fg, + // {QBrush(blendColors(themeColor, "#ccc", 0.9), Qt::FDiagPattern), + // QBrush(blendColors(themeColor, "#ccc", 0.9), Qt::FDiagPattern), + // QBrush(blendColors(themeColorNoSat, "#ccc", 0.9), Qt::FDiagPattern)}}; + + // this->tabs.newMessage = { + // fg, + // {QBrush(blendColors(themeColor, "#666", 0.7), Qt::FDiagPattern), + // QBrush(blendColors(themeColor, "#666", 0.5), Qt::FDiagPattern), + // QBrush(blendColors(themeColorNoSat, "#666", 0.7), + // Qt::FDiagPattern)}}; + // this->tabs.highlighted = {fg, {QColor("#777"), QColor("#777"), + // QColor("#666")}}; + this->tabs.bottomLine = this->tabs.selected.backgrounds.regular.color(); } @@ -163,7 +183,7 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) this->messages.selection = isLightTheme() ? QColor(0, 0, 0, 64) : QColor(255, 255, 255, 64); this->updated.invoke(); -} +} // namespace singletons QColor ThemeManager::blendColors(const QColor &color1, const QColor &color2, qreal ratio) { diff --git a/src/singletons/thememanager.hpp b/src/singletons/thememanager.hpp index 443f04824..5165600ad 100644 --- a/src/singletons/thememanager.hpp +++ b/src/singletons/thememanager.hpp @@ -25,11 +25,16 @@ public: struct TabColors { QColor text; - struct Backgrounds { + struct { QBrush regular; QBrush hover; QBrush unfocused; } backgrounds; + struct { + QColor regular; + QColor hover; + QColor unfocused; + } line; }; /// WINDOW @@ -43,9 +48,9 @@ public: /// TABS struct { TabColors regular; - TabColors selected; - TabColors highlighted; TabColors newMessage; + TabColors highlighted; + TabColors selected; QColor border; QColor bottomLine; } tabs; diff --git a/src/singletons/windowmanager.cpp b/src/singletons/windowmanager.cpp index a7716aae2..3cbfa9f5c 100644 --- a/src/singletons/windowmanager.cpp +++ b/src/singletons/windowmanager.cpp @@ -188,27 +188,27 @@ void WindowManager::initialize() // load tabs QJsonArray tabs = window_obj.value("tabs").toArray(); for (QJsonValue tab_val : tabs) { - widgets::SplitContainer *tab = window.getNotebook().addNewPage(); + widgets::SplitContainer *page = window.getNotebook().addPage(false); QJsonObject tab_obj = tab_val.toObject(); // set custom title QJsonValue title_val = tab_obj.value("title"); if (title_val.isString()) { - tab->getTab()->setTitle(title_val.toString()); - tab->getTab()->useDefaultTitle = false; + page->getTab()->setTitle(title_val.toString()); + page->getTab()->useDefaultTitle = false; } // selected if (tab_obj.value("selected").toBool(false)) { - window.getNotebook().select(tab); + window.getNotebook().select(page); } // load splits QJsonObject splitRoot = tab_obj.value("splits2").toObject(); if (!splitRoot.isEmpty()) { - tab->decodeFromJson(splitRoot); + page->decodeFromJson(splitRoot); continue; } @@ -217,12 +217,12 @@ void WindowManager::initialize() int colNr = 0; for (QJsonValue column_val : tab_obj.value("splits").toArray()) { for (QJsonValue split_val : column_val.toArray()) { - widgets::Split *split = new widgets::Split(tab); + widgets::Split *split = new widgets::Split(page); QJsonObject split_obj = split_val.toObject(); split->setChannel(decodeChannel(split_obj)); - tab->appendSplit(split); + page->appendSplit(split); } colNr++; } @@ -231,7 +231,7 @@ void WindowManager::initialize() if (mainWindow == nullptr) { mainWindow = &createWindow(widgets::Window::Main); - mainWindow->getNotebook().addNewPage(true); + mainWindow->getNotebook().addPage(true); } this->initialized = true; @@ -268,9 +268,11 @@ void WindowManager::save() // window tabs QJsonArray tabs_arr; - for (int tab_i = 0; tab_i < window->getNotebook().tabCount(); tab_i++) { + for (int tab_i = 0; tab_i < window->getNotebook().getPageCount(); tab_i++) { QJsonObject tab_obj; - widgets::SplitContainer *tab = window->getNotebook().tabAt(tab_i); + widgets::SplitContainer *tab = + dynamic_cast(window->getNotebook().getPageAt(tab_i)); + assert(tab != nullptr); // custom tab title if (!tab->getTab()->useDefaultTitle) { diff --git a/src/widgets/helper/label.hpp b/src/widgets/helper/label.hpp index 5afa0e003..3af4eadfb 100644 --- a/src/widgets/helper/label.hpp +++ b/src/widgets/helper/label.hpp @@ -27,7 +27,7 @@ protected: private: QSize preferedSize; QString text; - FontStyle fontStyle = FontStyle::Medium; + FontStyle fontStyle = FontStyle::ChatMedium; }; } // namespace widgets diff --git a/src/widgets/helper/notebookbutton.cpp b/src/widgets/helper/notebookbutton.cpp index a99fcc1ec..87783919a 100644 --- a/src/widgets/helper/notebookbutton.cpp +++ b/src/widgets/helper/notebookbutton.cpp @@ -136,10 +136,12 @@ void NotebookButton::dropEvent(QDropEvent *event) if (SplitContainer::isDraggingSplit) { event->acceptProposedAction(); - Notebook *notebook = dynamic_cast(this->parentWidget()); + Notebook2 *notebook = dynamic_cast(this->parentWidget()); if (notebook != nuuls) { - SplitContainer *page = notebook->addNewPage(); + SplitContainer *page = new SplitContainer(notebook); + auto *tab = notebook->addPage(page); + page->setTab(tab); SplitContainer::draggingSplit->setParent(page); page->appendSplit(SplitContainer::draggingSplit); diff --git a/src/widgets/helper/notebooktab.cpp b/src/widgets/helper/notebooktab.cpp index 8ff070645..34894bf17 100644 --- a/src/widgets/helper/notebooktab.cpp +++ b/src/widgets/helper/notebooktab.cpp @@ -61,17 +61,18 @@ NotebookTab2::NotebookTab2(Notebook2 *_notebook) } }); - QAction *enableHighlightsOnNewMessageAction = - new QAction("Enable highlights on new message", &this->menu); - enableHighlightsOnNewMessageAction->setCheckable(true); + // QAction *enableHighlightsOnNewMessageAction = + // new QAction("Enable highlights on new message", &this->menu); + // enableHighlightsOnNewMessageAction->setCheckable(true); this->menu.addAction("Close", [=]() { this->notebook->removePage(this->page); }); - this->menu.addAction(enableHighlightsOnNewMessageAction); + // this->menu.addAction(enableHighlightsOnNewMessageAction); - QObject::connect(enableHighlightsOnNewMessageAction, &QAction::toggled, [this](bool newValue) { - debug::Log("New value is {}", newValue); // - }); + // QObject::connect(enableHighlightsOnNewMessageAction, &QAction::toggled, [this](bool + // newValue) { + // debug::Log("New value is {}", newValue); // + // }); } void NotebookTab2::themeRefreshEvent() @@ -85,15 +86,20 @@ void NotebookTab2::updateSize() float scale = getScale(); int width; - QFontMetrics metrics(this->font()); + QFontMetrics metrics = getApp()->fonts->getFontMetrics(FontStyle::UiTabs, this->getScale()); - if (!app->settings->showTabCloseButton) { - width = (int)((metrics.width(this->title) + 16 /*+ 16*/) * scale); + if (this->hasXButton()) { + width = (int)((metrics.width(this->title) + 32) * scale); } else { - width = (int)((metrics.width(this->title) + 8 + 24 /*+ 16*/) * scale); + width = (int)((metrics.width(this->title) + 16) * scale); } - this->resize(std::min((int)(150 * scale), width), (int)(24 * scale)); + width = std::min((int)(150 * scale), width); + + if (this->width() != width) { + this->resize(width, (int)(NOTEBOOK_TAB_HEIGHT * scale)); + this->notebook->performLayout(); + } // if (this->parent() != nullptr) { // (static_cast(this->parent()))->performLayout(true); @@ -182,7 +188,9 @@ void NotebookTab2::paintEvent(QPaintEvent *) QPainter painter(this); float scale = this->getScale(); - int height = (int)(scale * 24); + painter.setFont(getApp()->fonts->getFont(FontStyle::UiTabs, scale)); + + int height = (int)(scale * NOTEBOOK_TAB_HEIGHT); // int fullHeight = (int)(scale * 48); // select the right tab colors @@ -206,48 +214,28 @@ void NotebookTab2::paintEvent(QPaintEvent *) : (windowFocused ? colors.backgrounds.regular : colors.backgrounds.unfocused); - if (true) { - painter.fillRect(rect(), this->mouseOver ? regular.backgrounds.hover - : (windowFocused ? regular.backgrounds.regular - : regular.backgrounds.unfocused)); + painter.fillRect(rect(), this->mouseOver ? regular.backgrounds.hover + : (windowFocused ? regular.backgrounds.regular + : regular.backgrounds.unfocused)); - // fill the tab background - painter.fillRect(rect(), tabBackground); + // fill the tab background + painter.fillRect(rect(), tabBackground); - // draw border - // painter.setPen(QPen("#ccc")); - // QPainterPath path(QPointF(0, height)); - // path.lineTo(0, 0); - // path.lineTo(this->width() - 1, 0); - // path.lineTo(this->width() - 1, this->height() - 1); - // path.lineTo(0, this->height() - 1); - // painter.drawPath(path); - } else { - // QPainterPath path(QPointF(0, height)); - // path.lineTo(8 * scale, 0); - // path.lineTo(this->width() - 8 * scale, 0); - // path.lineTo(this->width(), height); - // painter.fillPath(path, this->mouseOver ? regular.backgrounds.hover - // : (windowFocused ? - // regular.backgrounds.regular - // : - // regular.backgrounds.unfocused)); + // draw border + // painter.setPen(QPen("#fff")); + // QPainterPath path(QPointF(0, height)); + // path.lineTo(0, 0); + // path.lineTo(this->width() - 1, 0); + // path.lineTo(this->width() - 1, this->height() - 1); + // path.lineTo(0, this->height() - 1); + // painter.drawPath(path); - // // fill the tab background - // painter.fillPath(path, tabBackground); - // painter.setPen(QColor("#FFF")); - // painter.setRenderHint(QPainter::Antialiasing); - // painter.drawPath(path); - // // painter.setBrush(QColor("#000")); - - // QLinearGradient gradient(0, height, 0, fullHeight); - // gradient.setColorAt(0, tabBackground.color()); - // gradient.setColorAt(1, "#fff"); - - // QBrush brush(gradient); - // painter.fillRect(0, height, this->width(), fullHeight - height, - // brush); - } + // top line + painter.fillRect(QRectF(0, (this->selected ? 0.f : 1.f) * scale, this->width(), + (this->selected ? 2.f : 1.f) * scale), + this->mouseOver + ? colors.line.hover + : (windowFocused ? colors.line.regular : colors.line.unfocused)); // set the pen color painter.setPen(colors.text); @@ -260,7 +248,11 @@ void NotebookTab2::paintEvent(QPaintEvent *) if (true) { // legacy // painter.drawText(rect, this->getTitle(), QTextOption(Qt::AlignCenter)); int offset = (int)(scale * 8); - QRect textRect(offset, 0, this->width() - offset - offset, height); + QRect textRect(offset, this->selected ? 0 : 1, this->width() - offset - offset, height); + + if (this->shouldDrawXButton()) { + textRect.setRight(textRect.right() - this->height() / 2); + } QTextOption option(Qt::AlignLeft | Qt::AlignVCenter); option.setWrapMode(QTextOption::NoWrap); @@ -274,9 +266,11 @@ void NotebookTab2::paintEvent(QPaintEvent *) } // draw close x - if (!app->settings->showTabCloseButton && (mouseOver || selected)) { + if (this->shouldDrawXButton()) { QRect xRect = this->getXRect(); if (!xRect.isNull()) { + painter.setBrush(QColor("#fff")); + if (mouseOverX) { painter.fillRect(xRect, QColor(0, 0, 0, 64)); @@ -291,6 +285,21 @@ void NotebookTab2::paintEvent(QPaintEvent *) painter.drawLine(xRect.topRight() + QPoint(-a, a), xRect.bottomLeft() + QPoint(a, -a)); } } + + // draw line at bottom + if (!this->selected) { + painter.fillRect(0, this->height() - 1, this->width(), 1, app->themes->window.background); + } +} + +bool NotebookTab2::hasXButton() +{ + return getApp()->settings->showTabCloseButton && this->notebook->getAllowUserTabManagement(); +} + +bool NotebookTab2::shouldDrawXButton() +{ + return this->hasXButton() && (mouseOver || selected); } void NotebookTab2::mousePressEvent(QMouseEvent *event) @@ -320,8 +329,7 @@ void NotebookTab2::mouseReleaseEvent(QMouseEvent *event) this->notebook->removePage(this->page); } } else { - if (getApp()->settings->showTabCloseButton && this->mouseDownX && - this->getXRect().contains(event->pos())) { + if (this->hasXButton() && this->mouseDownX && this->getXRect().contains(event->pos())) { this->mouseDownX = false; this->notebook->removePage(this->page); @@ -377,7 +385,7 @@ void NotebookTab2::mouseMoveEvent(QMouseEvent *event) int index; QWidget *clickedPage = notebook->tabAt(relPoint, index, this->width()); - assert(clickedPage); + // assert(clickedPage); if (clickedPage != nullptr && clickedPage != this->page) { this->notebook->rearrangePage(this->page, index); @@ -387,370 +395,14 @@ void NotebookTab2::mouseMoveEvent(QMouseEvent *event) QRect NotebookTab2::getXRect() { - if (this->notebook->getAllowUserTabManagement()) { - return QRect(); - } + // if (!this->notebook->getAllowUserTabManagement()) { + // return QRect(); + // } float s = this->getScale(); - return QRect(this->width() - static_cast(20 * s), static_cast(4 * s), + return QRect(this->width() - static_cast(20 * s), static_cast(6 * s), static_cast(16 * s), static_cast(16 * s)); } -// 2 -NotebookTab::NotebookTab(Notebook *_notebook) - : BaseWidget(_notebook) - , positionChangedAnimation(this, "pos") - , notebook(_notebook) - , menu(this) -{ - auto app = getApp(); - - this->setAcceptDrops(true); - - this->positionChangedAnimation.setEasingCurve(QEasingCurve(QEasingCurve::InCubic)); - - app->settings->showTabCloseButton.connect(boost::bind(&NotebookTab::hideTabXChanged, this, _1), - this->managedConnections); - - this->setMouseTracking(true); - - this->menu.addAction("Rename", [this]() { - TextInputDialog d(this); - - d.setWindowTitle("Change tab title (Leave empty for default behaviour)"); - if (this->useDefaultTitle) { - d.setText(""); - } else { - d.setText(this->getTitle()); - d.highlightText(); - } - - if (d.exec() == QDialog::Accepted) { - QString newTitle = d.getText(); - if (newTitle.isEmpty()) { - this->useDefaultTitle = true; - this->page->refreshTabTitle(); - } else { - this->useDefaultTitle = false; - this->setTitle(newTitle); - } - } - }); - - QAction *enableHighlightsOnNewMessageAction = - new QAction("Enable highlights on new message", &this->menu); - enableHighlightsOnNewMessageAction->setCheckable(true); - - this->menu.addAction("Close", [=]() { this->notebook->removePage(this->page); }); - - this->menu.addAction(enableHighlightsOnNewMessageAction); - - QObject::connect(enableHighlightsOnNewMessageAction, &QAction::toggled, [](bool newValue) { - debug::Log("New value is {}", newValue); // - }); -} - -void NotebookTab::themeRefreshEvent() -{ - this->update(); -} - -void NotebookTab::updateSize() -{ - auto app = getApp(); - - float scale = getScale(); - - int width; - - if (!app->settings->showTabCloseButton) { - width = (int)((fontMetrics().width(this->title) + 16 /*+ 16*/) * scale); - } else { - width = (int)((fontMetrics().width(this->title) + 8 + 24 /*+ 16*/) * scale); - } - - this->resize(std::min((int)(150 * scale), width), (int)(24 * scale)); - - if (this->parent() != nullptr) { - (static_cast(this->parent()))->performLayout(true); - } -} - -const QString &NotebookTab::getTitle() const -{ - return this->title; -} - -void NotebookTab::setTitle(const QString &newTitle) -{ - if (this->title != newTitle) { - this->title = newTitle; - this->updateSize(); - this->update(); - } -} - -bool NotebookTab::isSelected() const -{ - return this->selected; -} - -void NotebookTab::setSelected(bool value) -{ - this->selected = value; - - this->highlightState = HighlightState::None; - - this->update(); -} - -void NotebookTab::setHighlightState(HighlightState newHighlightStyle) -{ - if (this->isSelected()) { - return; - } - - if (this->highlightState != HighlightState::Highlighted) { - this->highlightState = newHighlightStyle; - - this->update(); - } -} - -QRect NotebookTab::getDesiredRect() const -{ - return QRect(positionAnimationDesiredPoint, size()); -} - -void NotebookTab::hideTabXChanged(bool) -{ - this->updateSize(); - this->update(); -} - -void NotebookTab::moveAnimated(QPoint pos, bool animated) -{ - this->positionAnimationDesiredPoint = pos; - - QWidget *w = this->window(); - - if ((w != nullptr && !w->isVisible()) || !animated || !positionChangedAnimationRunning) { - this->move(pos); - - this->positionChangedAnimationRunning = true; - return; - } - - if (this->positionChangedAnimation.endValue() == pos) { - return; - } - - this->positionChangedAnimation.stop(); - this->positionChangedAnimation.setDuration(75); - this->positionChangedAnimation.setStartValue(this->pos()); - this->positionChangedAnimation.setEndValue(pos); - this->positionChangedAnimation.start(); -} - -void NotebookTab::paintEvent(QPaintEvent *) -{ - auto app = getApp(); - QPainter painter(this); - float scale = this->getScale(); - - int height = (int)(scale * 24); - // int fullHeight = (int)(scale * 48); - - // select the right tab colors - singletons::ThemeManager::TabColors colors; - singletons::ThemeManager::TabColors regular = this->themeManager->tabs.regular; - - if (this->selected) { - colors = this->themeManager->tabs.selected; - } else if (this->highlightState == HighlightState::Highlighted) { - colors = this->themeManager->tabs.highlighted; - } else if (this->highlightState == HighlightState::NewMessage) { - colors = this->themeManager->tabs.newMessage; - } else { - colors = this->themeManager->tabs.regular; - } - - bool windowFocused = this->window() == QApplication::activeWindow(); - // || SettingsDialog::getHandle() == QApplication::activeWindow(); - - QBrush tabBackground = this->mouseOver ? colors.backgrounds.hover - : (windowFocused ? colors.backgrounds.regular - : colors.backgrounds.unfocused); - - if (true) { - painter.fillRect(rect(), this->mouseOver ? regular.backgrounds.hover - : (windowFocused ? regular.backgrounds.regular - : regular.backgrounds.unfocused)); - - // fill the tab background - painter.fillRect(rect(), tabBackground); - - // draw border - // painter.setPen(QPen("#ccc")); - // QPainterPath path(QPointF(0, height)); - // path.lineTo(0, 0); - // path.lineTo(this->width() - 1, 0); - // path.lineTo(this->width() - 1, this->height() - 1); - // path.lineTo(0, this->height() - 1); - // painter.drawPath(path); - } else { - // QPainterPath path(QPointF(0, height)); - // path.lineTo(8 * scale, 0); - // path.lineTo(this->width() - 8 * scale, 0); - // path.lineTo(this->width(), height); - // painter.fillPath(path, this->mouseOver ? regular.backgrounds.hover - // : (windowFocused ? - // regular.backgrounds.regular - // : - // regular.backgrounds.unfocused)); - - // // fill the tab background - // painter.fillPath(path, tabBackground); - // painter.setPen(QColor("#FFF")); - // painter.setRenderHint(QPainter::Antialiasing); - // painter.drawPath(path); - // // painter.setBrush(QColor("#000")); - - // QLinearGradient gradient(0, height, 0, fullHeight); - // gradient.setColorAt(0, tabBackground.color()); - // gradient.setColorAt(1, "#fff"); - - // QBrush brush(gradient); - // painter.fillRect(0, height, this->width(), fullHeight - height, - // brush); - } - - // set the pen color - painter.setPen(colors.text); - - // set area for text - int rectW = (!app->settings->showTabCloseButton ? 0 : static_cast(16) * scale); - QRect rect(0, 0, this->width() - rectW, height); - - // draw text - if (true) { // legacy - // painter.drawText(rect, this->getTitle(), QTextOption(Qt::AlignCenter)); - int offset = (int)(scale * 8); - QRect textRect(offset, 0, this->width() - offset - offset, height); - - QTextOption option(Qt::AlignLeft | Qt::AlignVCenter); - option.setWrapMode(QTextOption::NoWrap); - painter.drawText(textRect, this->getTitle(), option); - } else { - // QTextOption option(Qt::AlignLeft | Qt::AlignVCenter); - // option.setWrapMode(QTextOption::NoWrap); - // int offset = (int)(scale * 16); - // QRect textRect(offset, 0, this->width() - offset - offset, height); - // painter.drawText(textRect, this->getTitle(), option); - } - - // draw close x - if (app->settings->showTabCloseButton && (mouseOver || selected)) { - QRect xRect = this->getXRect(); - if (mouseOverX) { - painter.fillRect(xRect, QColor(0, 0, 0, 64)); - - if (mouseDownX) { - painter.fillRect(xRect, QColor(0, 0, 0, 64)); - } - } - - int a = static_cast(scale * 4); - - painter.drawLine(xRect.topLeft() + QPoint(a, a), xRect.bottomRight() + QPoint(-a, -a)); - painter.drawLine(xRect.topRight() + QPoint(-a, a), xRect.bottomLeft() + QPoint(a, -a)); - } -} // namespace widgets - -void NotebookTab::mousePressEvent(QMouseEvent *event) -{ - this->mouseDown = true; - this->mouseDownX = this->getXRect().contains(event->pos()); - - this->update(); - - this->notebook->select(page); - - switch (event->button()) { - case Qt::RightButton: { - this->menu.popup(event->globalPos()); - } break; - } -} - -void NotebookTab::mouseReleaseEvent(QMouseEvent *event) -{ - auto app = getApp(); - - this->mouseDown = false; - - if (event->button() == Qt::MiddleButton) { - if (this->rect().contains(event->pos())) { - this->notebook->removePage(this->page); - } - } else { - if (app->settings->showTabCloseButton && this->mouseDownX && - this->getXRect().contains(event->pos())) { - this->mouseDownX = false; - - this->notebook->removePage(this->page); - } else { - this->update(); - } - } -} - -void NotebookTab::enterEvent(QEvent *) -{ - this->mouseOver = true; - - this->update(); -} - -void NotebookTab::leaveEvent(QEvent *) -{ - this->mouseOverX = false; - this->mouseOver = false; - - this->update(); -} - -void NotebookTab::dragEnterEvent(QDragEnterEvent *) -{ - this->notebook->select(this->page); -} - -void NotebookTab::mouseMoveEvent(QMouseEvent *event) -{ - auto app = getApp(); - - if (app->settings->showTabCloseButton) { - bool overX = this->getXRect().contains(event->pos()); - - if (overX != this->mouseOverX) { - // Over X state has been changed (we either left or entered it; - this->mouseOverX = overX; - - this->update(); - } - } - - QPoint relPoint = this->mapToParent(event->pos()); - - if (this->mouseDown && !this->getDesiredRect().contains(relPoint)) { - int index; - SplitContainer *clickedPage = notebook->tabAt(relPoint, index, this->width()); - - if (clickedPage != nullptr && clickedPage != this->page) { - this->notebook->rearrangePage(this->page, index); - } - } -} - } // namespace widgets } // namespace chatterino diff --git a/src/widgets/helper/notebooktab.hpp b/src/widgets/helper/notebooktab.hpp index 628b835b4..e65c758fe 100644 --- a/src/widgets/helper/notebooktab.hpp +++ b/src/widgets/helper/notebooktab.hpp @@ -11,7 +11,9 @@ namespace chatterino { namespace widgets { -class Notebook; +#define NOTEBOOK_TAB_HEIGHT 28 + +// class Notebook; class Notebook2; class SplitContainer; @@ -73,6 +75,9 @@ private: bool mouseOverX = false; bool mouseDownX = false; + bool hasXButton(); + bool shouldDrawXButton(); + HighlightState highlightState = HighlightState::None; QMenu menu; @@ -80,75 +85,5 @@ private: QRect getXRect(); }; -class NotebookTab : public BaseWidget -{ - Q_OBJECT - -public: - explicit NotebookTab(Notebook *_notebook); - - void updateSize(); - - SplitContainer *page; - - const QString &getTitle() const; - void setTitle(const QString &newTitle); - bool isSelected() const; - void setSelected(bool value); - - void setHighlightState(HighlightState style); - - void moveAnimated(QPoint pos, bool animated = true); - - QRect getDesiredRect() const; - void hideTabXChanged(bool); - -protected: - virtual void themeRefreshEvent() override; - - virtual void paintEvent(QPaintEvent *) override; - - virtual void mousePressEvent(QMouseEvent *event) override; - virtual void mouseReleaseEvent(QMouseEvent *event) override; - virtual void enterEvent(QEvent *) override; - virtual void leaveEvent(QEvent *) override; - - virtual void dragEnterEvent(QDragEnterEvent *event) override; - - virtual void mouseMoveEvent(QMouseEvent *event) override; - -private: - std::vector managedConnections; - - QPropertyAnimation positionChangedAnimation; - bool positionChangedAnimationRunning = false; - QPoint positionAnimationDesiredPoint; - - Notebook *notebook; - - QString title; - -public: - bool useDefaultTitle = true; - -private: - bool selected = false; - bool mouseOver = false; - bool mouseDown = false; - bool mouseOverX = false; - bool mouseDownX = false; - - HighlightState highlightState = HighlightState::None; - - QMenu menu; - - QRect getXRect() - { - float s = this->getScale(); - return QRect(this->width() - static_cast(20 * s), static_cast(4 * s), - static_cast(16 * s), static_cast(16 * s)); - } -}; - } // namespace widgets } // namespace chatterino diff --git a/src/widgets/helper/splitinput.cpp b/src/widgets/helper/splitinput.cpp index 2a086df64..facd70b6a 100644 --- a/src/widgets/helper/splitinput.cpp +++ b/src/widgets/helper/splitinput.cpp @@ -65,11 +65,11 @@ void SplitInput::initLayout() // set edit font this->ui.textEdit->setFont( - app->fonts->getFont(singletons::FontManager::Type::Medium, this->getScale())); + app->fonts->getFont(singletons::FontManager::Type::ChatMedium, this->getScale())); this->managedConnections.emplace_back(app->fonts->fontChanged.connect([=]() { this->ui.textEdit->setFont( - app->fonts->getFont(singletons::FontManager::Type::Medium, this->getScale())); + app->fonts->getFont(singletons::FontManager::Type::ChatMedium, this->getScale())); })); // open emote popup @@ -244,18 +244,18 @@ void SplitInput::installKeyPressedEvent() SplitContainer *page = static_cast(this->chatWidget->parentWidget()); - Notebook *notebook = static_cast(page->parentWidget()); + Notebook2 *notebook = static_cast(page->parentWidget()); - notebook->nextTab(); + notebook->selectNextTab(); } } else if (event->key() == Qt::Key_Backtab) { if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) { SplitContainer *page = static_cast(this->chatWidget->parentWidget()); - Notebook *notebook = static_cast(page->parentWidget()); + Notebook2 *notebook = static_cast(page->parentWidget()); - notebook->previousTab(); + notebook->selectPreviousTab(); } } else if (event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier) { if (this->chatWidget->view.hasSelection()) { @@ -316,14 +316,23 @@ void SplitInput::paintEvent(QPaintEvent *) { QPainter painter(this); - painter.fillRect(this->rect(), this->themeManager->splits.input.background); - - QPen pen(this->themeManager->splits.input.border); if (this->themeManager->isLightTheme()) { - pen.setWidth((int)(6 * this->getScale())); + int s = (int)(3 * this->getScale()); + QRect rect = this->rect().marginsRemoved(QMargins(s, s, s, s)); + + painter.fillRect(rect, this->themeManager->splits.input.background); + + painter.setPen(QColor("#ccc")); + painter.drawRect(rect); + } else { + int s = (int)(1 * this->getScale()); + QRect rect = this->rect().marginsRemoved(QMargins(s, s, s, s)); + + painter.fillRect(rect, this->themeManager->splits.input.background); + + painter.setPen(QColor("#333")); + painter.drawRect(rect); } - painter.setPen(pen); - painter.drawRect(0, 0, this->width() - 1, this->height() - 1); } void SplitInput::resizeEvent(QResizeEvent *) diff --git a/src/widgets/notebook.cpp b/src/widgets/notebook.cpp index 8ac53af8d..1acae1a7e 100644 --- a/src/widgets/notebook.cpp +++ b/src/widgets/notebook.cpp @@ -89,6 +89,8 @@ void Notebook2::removePage(QWidget *page) break; } } + + this->performLayout(); } void Notebook2::removeCurrentPage() @@ -179,6 +181,11 @@ int Notebook2::getPageCount() const return this->items.count(); } +QWidget *Notebook2::getPageAt(int index) const +{ + return this->items[index].page; +} + int Notebook2::getSelectedIndex() const { return this->indexOf(this->selectedPage); @@ -242,11 +249,11 @@ void Notebook2::setShowAddButton(bool value) void Notebook2::scaleChangedEvent(float scale) { - // float h = 24 * this->getScale(); + float h = NOTEBOOK_TAB_HEIGHT * this->getScale(); // this->settingsButton.setFixedSize(h, h); // this->userButton.setFixedSize(h, h); - // this->addButton.setFixedSize(h, h); + this->addButton.setFixedSize(h, h); for (auto &i : this->items) { i.tab->updateSize(); @@ -290,10 +297,12 @@ void Notebook2::performLayout(bool animated) // x += (int)(scale * 2); // } - int tabHeight = static_cast(24 * scale); + int tabHeight = static_cast(NOTEBOOK_TAB_HEIGHT * scale); bool first = true; for (auto i = this->items.begin(); i != this->items.end(); i++) { + // int yOffset = i->tab->isSelected() ? 0 : 1; + if (!first && (i == this->items.end() && this->showAddButton ? tabHeight : 0) + x + i->tab->width() > width()) // @@ -321,7 +330,7 @@ void Notebook2::performLayout(bool animated) this->update(); } - y += (int)(1 * scale); + y += (int)(3 * scale); for (auto &i : this->items) { i.tab->raise(); @@ -343,10 +352,15 @@ void Notebook2::paintEvent(QPaintEvent *event) BaseWidget::paintEvent(event); QPainter painter(this); - painter.fillRect(0, this->lineY, this->width(), (int)(1 * this->getScale()), + painter.fillRect(0, this->lineY, this->width(), (int)(3 * this->getScale()), this->themeManager->tabs.bottomLine); } +NotebookButton *Notebook2::getAddButton() +{ + return &this->addButton; +} + NotebookTab2 *Notebook2::getTabFromPage(QWidget *page) { for (auto &it : this->items) { @@ -358,318 +372,28 @@ NotebookTab2 *Notebook2::getTabFromPage(QWidget *page) return nullptr; } -// Notebook2::OLD NOTEBOOK -Notebook::Notebook(Window *parent, bool _showButtons) - : BaseWidget(parent) - , parentWindow(parent) - , addButton(this) - , settingsButton(this) - , userButton(this) - , showButtons(_showButtons) - , closeConfirmDialog(this) +SplitNotebook::SplitNotebook(QWidget *parent) + : Notebook2(parent) { - auto app = getApp(); - - this->connect(&this->settingsButton, SIGNAL(clicked()), this, SLOT(settingsButtonClicked())); - this->connect(&this->userButton, SIGNAL(clicked()), this, SLOT(usersButtonClicked())); - this->connect(&this->addButton, SIGNAL(clicked()), this, SLOT(addPageButtonClicked())); - - this->settingsButton.icon = NotebookButton::IconSettings; - - this->userButton.move(24, 0); - this->userButton.icon = NotebookButton::IconUser; - - app->settings->hidePreferencesButton.connectSimple([this](auto) { this->performLayout(); }); - app->settings->hideUserButton.connectSimple([this](auto) { this->performLayout(); }); - - closeConfirmDialog.setText("Are you sure you want to close this tab?"); - closeConfirmDialog.setIcon(QMessageBox::Icon::Question); - closeConfirmDialog.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); - closeConfirmDialog.setDefaultButton(QMessageBox::Yes); - - this->scaleChangedEvent(this->getScale()); - - // Window-wide hotkeys - // CTRL+T: Create new split in selected notebook page - // CreateWindowShortcut(this, "CTRL+T", [this]() { - // if (this->selectedPage == nullptr) { - // return; - // } - - // this->selectedPage->addChat(true); - // }); + this->connect(this->getAddButton(), &NotebookButton::clicked, + [this]() { QTimer::singleShot(80, this, [this] { this->addPage(true); }); }); } -SplitContainer *Notebook::addNewPage(bool select) +SplitContainer *SplitNotebook::addPage(bool select) { - auto tab = new NotebookTab(this); - auto page = new SplitContainer(this, tab); - + SplitContainer *container = new SplitContainer(this); + auto *tab = Notebook2::addPage(container, QString(), select); + container->setTab(tab); + tab->setParent(this); tab->show(); - - if (select || this->pages.count() == 0) { - this->select(page); - } - - this->pages.append(page); - - this->performLayout(); - - return page; + return container; } -void Notebook::removePage(SplitContainer *page) +SplitContainer *SplitNotebook::getOrAddSelectedPage() { - if (page->getSplitCount() > 0 && closeConfirmDialog.exec() != QMessageBox::Yes) { - return; - } + auto *selectedPage = this->getSelectedPage(); - int index = this->pages.indexOf(page); - - if (this->pages.size() == 1) { - select(nullptr); - } else if (index == this->pages.count() - 1) { - select(this->pages[index - 1]); - } else { - select(this->pages[index + 1]); - } - - page->getTab()->deleteLater(); - page->deleteLater(); - - this->pages.removeOne(page); - - if (this->pages.empty()) { - this->addNewPage(); - } - - this->performLayout(); -} - -void Notebook::removeCurrentPage() -{ - if (this->selectedPage == nullptr) { - return; - } - - this->removePage(this->selectedPage); -} - -SplitContainer *Notebook::getOrAddSelectedPage() -{ - if (selectedPage == nullptr) { - this->addNewPage(true); - } - - return selectedPage; -} - -SplitContainer *Notebook::getSelectedPage() -{ - return selectedPage; -} - -void Notebook::select(SplitContainer *page) -{ - if (page == this->selectedPage) { - return; - } - - if (page != nullptr) { - page->setHidden(false); - page->getTab()->setSelected(true); - page->getTab()->raise(); - } - - if (this->selectedPage != nullptr) { - this->selectedPage->setHidden(true); - this->selectedPage->getTab()->setSelected(false); - - for (Split *split : this->selectedPage->getSplits()) { - split->updateLastReadMessage(); - } - } - - this->selectedPage = page; - - this->performLayout(); -} - -void Notebook::selectIndex(int index) -{ - if (index < 0 || index >= this->pages.size()) { - return; - } - - this->select(this->pages.at(index)); -} - -int Notebook::tabCount() -{ - return this->pages.size(); -} - -SplitContainer *Notebook::tabAt(QPoint point, int &index, int maxWidth) -{ - int i = 0; - - for (auto *page : this->pages) { - QRect rect = page->getTab()->getDesiredRect(); - rect.setHeight((int)(this->getScale() * 24)); - - rect.setWidth(std::min(maxWidth, rect.width())); - - if (rect.contains(point)) { - index = i; - return page; - } - - i++; - } - - index = -1; - return nullptr; -} - -SplitContainer *Notebook::tabAt(int index) -{ - return this->pages[index]; -} - -void Notebook::rearrangePage(SplitContainer *page, int index) -{ - this->pages.move(this->pages.indexOf(page), index); - - this->performLayout(); -} - -void Notebook::nextTab() -{ - if (this->pages.size() <= 1) { - return; - } - - int index = (this->pages.indexOf(this->selectedPage) + 1) % this->pages.size(); - - this->select(this->pages[index]); -} - -void Notebook::previousTab() -{ - if (this->pages.size() <= 1) { - return; - } - - int index = (this->pages.indexOf(this->selectedPage) - 1); - - if (index < 0) { - index += this->pages.size(); - } - - this->select(this->pages[index]); -} - -void Notebook::performLayout(bool animated) -{ - auto app = getApp(); - - int x = 0, y = 0; - float scale = this->getScale(); - bool customFrame = this->parentWindow->hasCustomWindowFrame(); - - if (!this->showButtons || app->settings->hidePreferencesButton || customFrame) { - this->settingsButton.hide(); - } else { - this->settingsButton.show(); - x += settingsButton.width(); - } - if (!this->showButtons || app->settings->hideUserButton || customFrame) { - this->userButton.hide(); - } else { - this->userButton.move(x, 0); - this->userButton.show(); - x += userButton.width(); - } - - if (customFrame || !this->showButtons || - (app->settings->hideUserButton && app->settings->hidePreferencesButton)) { - x += (int)(scale * 2); - } - - int tabHeight = static_cast(24 * scale); - bool first = true; - - for (auto &i : this->pages) { - if (!first && - (i == this->pages.last() ? tabHeight : 0) + x + i->getTab()->width() > width()) { - y += i->getTab()->height(); - // y += 20; - i->getTab()->moveAnimated(QPoint(0, y), animated); - x = i->getTab()->width(); - } else { - i->getTab()->moveAnimated(QPoint(x, y), animated); - x += i->getTab()->width(); - } - - // x -= (int)(8 * scale); - x += 1; - - first = false; - } - - // x += (int)(8 * scale); - // x += 1; - - this->addButton.move(x, y); - - y -= 1; - - for (auto &i : this->pages) { - i->getTab()->raise(); - } - - this->addButton.raise(); - - if (this->selectedPage != nullptr) { - this->selectedPage->move(0, y + tabHeight); - this->selectedPage->resize(width(), height() - y - tabHeight); - this->selectedPage->raise(); - } -} - -void Notebook::resizeEvent(QResizeEvent *) -{ - this->performLayout(false); -} - -void Notebook::scaleChangedEvent(float) -{ - float h = 24 * this->getScale(); - - this->settingsButton.setFixedSize(h, h); - this->userButton.setFixedSize(h, h); - this->addButton.setFixedSize(h, h); - - for (auto &i : this->pages) { - i->getTab()->updateSize(); - } -} - -void Notebook::settingsButtonClicked() -{ - auto app = getApp(); - app->windows->showSettingsDialog(); -} - -void Notebook::usersButtonClicked() -{ - auto app = getApp(); - app->windows->showAccountSelectPopup(this->mapToGlobal(this->userButton.rect().bottomRight())); -} - -void Notebook::addPageButtonClicked() -{ - QTimer::singleShot(80, [this] { this->addNewPage(true); }); + return selectedPage != nullptr ? (SplitContainer *)selectedPage : this->addPage(); } } // namespace widgets diff --git a/src/widgets/notebook.hpp b/src/widgets/notebook.hpp index d82f26a58..dae526b4d 100644 --- a/src/widgets/notebook.hpp +++ b/src/widgets/notebook.hpp @@ -32,6 +32,7 @@ public: void selectPreviousTab(); int getPageCount() const; + QWidget *getPageAt(int index) const; int getSelectedIndex() const; QWidget *getSelectedPage() const; @@ -44,11 +45,15 @@ public: bool getShowAddButton() const; void setShowAddButton(bool value); + void performLayout(bool animate = true); + protected: virtual void scaleChangedEvent(float scale) override; virtual void resizeEvent(QResizeEvent *) override; virtual void paintEvent(QPaintEvent *) override; + NotebookButton *getAddButton(); + private: struct Item { NotebookTab2 *tab; @@ -64,63 +69,16 @@ private: bool showAddButton = false; int lineY = 20; - void performLayout(bool animate = true); - NotebookTab2 *getTabFromPage(QWidget *page); }; -class Notebook : public BaseWidget +class SplitNotebook : public Notebook2 { - Q_OBJECT - public: - explicit Notebook(Window *parent, bool _showButtons); - - SplitContainer *addNewPage(bool select = false); - - void removePage(SplitContainer *page); - void removeCurrentPage(); - void select(SplitContainer *page); - void selectIndex(int index); + SplitNotebook(QWidget *parent); + SplitContainer *addPage(bool select = false); SplitContainer *getOrAddSelectedPage(); - SplitContainer *getSelectedPage(); - - void performLayout(bool animate = true); - - int tabCount(); - SplitContainer *tabAt(QPoint point, int &index, int maxWidth = 2000000000); - SplitContainer *tabAt(int index); - void rearrangePage(SplitContainer *page, int index); - - void nextTab(); - void previousTab(); - -protected: - void scaleChangedEvent(float scale); - void resizeEvent(QResizeEvent *); - - void settingsButtonMouseReleased(QMouseEvent *event); - -public slots: - void settingsButtonClicked(); - void usersButtonClicked(); - void addPageButtonClicked(); - -private: - Window *parentWindow; - - QList pages; - - NotebookButton addButton; - NotebookButton settingsButton; - NotebookButton userButton; - - SplitContainer *selectedPage = nullptr; - - bool showButtons; - - QMessageBox closeConfirmDialog; }; } // namespace widgets diff --git a/src/widgets/settingspages/appearancepage.cpp b/src/widgets/settingspages/appearancepage.cpp index 6139e28d4..afabcc42d 100644 --- a/src/widgets/settingspages/appearancepage.cpp +++ b/src/widgets/settingspages/appearancepage.cpp @@ -165,12 +165,12 @@ QLayout *AppearancePage::createFontChanger() layout->addWidget(label); auto updateFontFamilyLabel = [=](auto) { - label->setText(QString::fromStdString(app->fonts->currentFontFamily.getValue()) + ", " + - QString::number(app->fonts->currentFontSize) + "pt"); + label->setText(QString::fromStdString(app->fonts->chatFontFamily.getValue()) + ", " + + QString::number(app->fonts->chatFontSize) + "pt"); }; - app->fonts->currentFontFamily.connectSimple(updateFontFamilyLabel, this->managedConnections); - app->fonts->currentFontSize.connectSimple(updateFontFamilyLabel, this->managedConnections); + app->fonts->chatFontFamily.connectSimple(updateFontFamilyLabel, this->managedConnections); + app->fonts->chatFontSize.connectSimple(updateFontFamilyLabel, this->managedConnections); // BUTTON QPushButton *button = new QPushButton("Select"); @@ -178,11 +178,11 @@ QLayout *AppearancePage::createFontChanger() button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Policy::Fixed); QObject::connect(button, &QPushButton::clicked, [=]() { - QFontDialog dialog(app->fonts->getFont(singletons::FontManager::Medium, 1.)); + QFontDialog dialog(app->fonts->getFont(singletons::FontManager::ChatMedium, 1.)); dialog.connect(&dialog, &QFontDialog::fontSelected, [=](const QFont &font) { - app->fonts->currentFontFamily = font.family().toStdString(); - app->fonts->currentFontSize = font.pointSize(); + app->fonts->chatFontFamily = font.family().toStdString(); + app->fonts->chatFontSize = font.pointSize(); }); dialog.show(); diff --git a/src/widgets/splitcontainer.cpp b/src/widgets/splitcontainer.cpp index dd6b517ea..dbc21e8df 100644 --- a/src/widgets/splitcontainer.cpp +++ b/src/widgets/splitcontainer.cpp @@ -29,15 +29,13 @@ namespace widgets { bool SplitContainer::isDraggingSplit = false; Split *SplitContainer::draggingSplit = nullptr; -SplitContainer::SplitContainer(Notebook *parent, NotebookTab *_tab) +SplitContainer::SplitContainer(Notebook2 *parent) : BaseWidget(parent) - , tab(_tab) + , tab(nullptr) , dropPreview(this) , mouseOverPoint(-10000, -10000) , overlay(this) { - this->tab->page = this; - this->refreshTabTitle(); this->managedConnect(Split::modifierStatusChanged, [this](auto modifiers) { @@ -69,11 +67,20 @@ SplitContainer::SplitContainer(Notebook *parent, NotebookTab *_tab) this->setAcceptDrops(true); } -NotebookTab *SplitContainer::getTab() const +NotebookTab2 *SplitContainer::getTab() const { return this->tab; } +void SplitContainer::setTab(NotebookTab2 *_tab) +{ + this->tab = _tab; + + this->tab->page = this; + + this->refreshTabTitle(); +} + void SplitContainer::appendNewSplit(bool openChannelNameDialog) { Split *split = new Split(this); @@ -131,6 +138,12 @@ void SplitContainer::insertSplit(Split *split, Direction direction, Node *relati this->refreshTabTitle(); + split->getChannelView().tabHighlightRequested.connect([this](HighlightState state) { + if (this->tab != nullptr) { + this->tab->setHighlightState(state); + } + }); + this->layout(); } @@ -149,6 +162,8 @@ SplitContainer::Position SplitContainer::releaseSplit(Split *split) this->refreshTabTitle(); + split->getChannelView().tabHighlightRequested.disconnectAll(); + return position; } @@ -265,10 +280,10 @@ void SplitContainer::paintEvent(QPaintEvent *) QString text = "Click to add a split"; - Notebook *notebook = dynamic_cast(this->parentWidget()); + Notebook2 *notebook = dynamic_cast(this->parentWidget()); if (notebook != nullptr) { - if (notebook->tabCount() > 1) { + if (notebook->getPageCount() > 1) { text += "\n\nTip: After adding a split you can hold to move it or split it " "further."; } @@ -276,7 +291,7 @@ void SplitContainer::paintEvent(QPaintEvent *) painter.drawText(rect(), text, QTextOption(Qt::AlignCenter)); } else { - painter.fillRect(rect(), this->themeManager->splits.messageSeperator); + painter.fillRect(rect(), QColor("#555")); } for (DropRect &dropRect : this->dropRects) { @@ -326,13 +341,15 @@ void SplitContainer::mouseMoveEvent(QMouseEvent *event) void SplitContainer::leaveEvent(QEvent *event) { - this->mouseOverPoint = QPoint(-1000, -10000); + this->mouseOverPoint = QPoint(-10000, -10000); this->update(); } void SplitContainer::refreshTabTitle() { - assert(this->tab != nullptr); + if (this->tab == nullptr) { + return; + } if (!this->tab->useDefaultTitle) { return; diff --git a/src/widgets/splitcontainer.hpp b/src/widgets/splitcontainer.hpp index c366850b2..b36fda190 100644 --- a/src/widgets/splitcontainer.hpp +++ b/src/widgets/splitcontainer.hpp @@ -165,7 +165,7 @@ private: }; public: - SplitContainer(Notebook *parent, NotebookTab *_tab); + SplitContainer(Notebook2 *parent); void appendNewSplit(bool openChannelNameDialog); void appendSplit(Split *split); @@ -189,12 +189,14 @@ public: void refreshTabTitle(); - NotebookTab *getTab() const; + NotebookTab2 *getTab() const; Node *getBaseNode() { return &this->baseNode; } + void setTab(NotebookTab2 *tab); + static bool isDraggingSplit; static Split *draggingSplit; @@ -232,7 +234,7 @@ private: Node baseNode; - NotebookTab *tab; + NotebookTab2 *tab; std::vector splits; bool isDragging = false; diff --git a/src/widgets/tooltipwidget.cpp b/src/widgets/tooltipwidget.cpp index 26026b6bd..6baa80526 100644 --- a/src/widgets/tooltipwidget.cpp +++ b/src/widgets/tooltipwidget.cpp @@ -58,7 +58,7 @@ void TooltipWidget::updateFont() auto app = getApp(); this->setFont( - app->fonts->getFont(singletons::FontManager::Type::MediumSmall, this->getScale())); + app->fonts->getFont(singletons::FontManager::Type::ChatMediumSmall, this->getScale())); } void TooltipWidget::setText(QString text) diff --git a/src/widgets/window.cpp b/src/widgets/window.cpp index ef667c50b..b159257d1 100644 --- a/src/widgets/window.cpp +++ b/src/widgets/window.cpp @@ -27,7 +27,7 @@ Window::Window(WindowType _type) : BaseWindow(nullptr, true) , type(_type) , dpi(this->getScale()) - , notebook(this, !this->hasCustomWindowFrame()) + , notebook(this) { auto app = getApp(); @@ -81,7 +81,7 @@ Window::Window(WindowType _type) CreateWindowShortcut(this, "CTRL+9", [this] { this->notebook.selectIndex(8); }); // CTRL+SHIFT+T: New tab - CreateWindowShortcut(this, "CTRL+SHIFT+T", [this] { this->notebook.addNewPage(true); }); + CreateWindowShortcut(this, "CTRL+SHIFT+T", [this] { this->notebook.addPage(true); }); // CTRL+SHIFT+W: Close current tab CreateWindowShortcut(this, "CTRL+SHIFT+W", [this] { this->notebook.removeCurrentPage(); }); @@ -106,6 +106,9 @@ Window::Window(WindowType _type) // }); this->setWindowTitle("Chatterino 2 Development Build"); + + this->notebook.setAllowUserTabManagement(true); + this->notebook.setShowAddButton(true); } Window::WindowType Window::getType() @@ -128,7 +131,7 @@ void Window::repaintVisibleChatWidgets(Channel *channel) } } -Notebook &Window::getNotebook() +SplitNotebook &Window::getNotebook() { return this->notebook; } diff --git a/src/widgets/window.hpp b/src/widgets/window.hpp index 5fa8eee12..02a774e04 100644 --- a/src/widgets/window.hpp +++ b/src/widgets/window.hpp @@ -29,7 +29,7 @@ public: void repaintVisibleChatWidgets(Channel *channel = nullptr); - Notebook &getNotebook(); + SplitNotebook &getNotebook(); void refreshWindowTitle(const QString &username); @@ -47,9 +47,9 @@ private: void loadGeometry(); - Notebook notebook; + SplitNotebook notebook; - friend class Notebook; + friend class Notebook2; public: void save();