diff --git a/src/application.cpp b/src/application.cpp index 5f5f33c62..fbd8dacb7 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -21,10 +21,10 @@ Application::Application() singletons::LoggingManager::getInstance(); - singletons::SettingManager::getInstance().init(); + singletons::SettingManager::getInstance().initialize(); singletons::CommandManager::getInstance().loadCommands(); - singletons::WindowManager::getInstance().initMainWindow(); + singletons::WindowManager::getInstance().initialize(); // Initialize everything we need singletons::EmoteManager::getInstance().loadGlobalEmotes(); diff --git a/src/singletons/settingsmanager.cpp b/src/singletons/settingsmanager.cpp index 9c697b6e0..1c87499d8 100644 --- a/src/singletons/settingsmanager.cpp +++ b/src/singletons/settingsmanager.cpp @@ -47,7 +47,7 @@ bool SettingManager::isIgnoredEmote(const QString &) return false; } -void SettingManager::init() +void SettingManager::initialize() { QString settingsPath = PathManager::getInstance().settingsFolderPath + "/settings.json"; diff --git a/src/singletons/settingsmanager.hpp b/src/singletons/settingsmanager.hpp index 0e3979923..23b13b068 100644 --- a/src/singletons/settingsmanager.hpp +++ b/src/singletons/settingsmanager.hpp @@ -27,7 +27,7 @@ public: messages::MessageElement::Flags getWordFlags(); bool isIgnoredEmote(const QString &emote); - void init(); + void initialize(); /// Appearance BoolSetting showTimestamps = {"/appearance/messages/showTimestamps", true}; diff --git a/src/singletons/thememanager.cpp b/src/singletons/thememanager.cpp index 55d612122..1ef36383e 100644 --- a/src/singletons/thememanager.cpp +++ b/src/singletons/thememanager.cpp @@ -129,8 +129,8 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) this->messages.textColors.system = QColor(140, 127, 127); this->messages.backgrounds.regular = splits.background; - this->messages.backgrounds.highlighted = blendColors( - this->tabs.selected.backgrounds.regular.color(), this->messages.backgrounds.regular, 0.8); + this->messages.backgrounds.highlighted = + blendColors(themeColor, this->messages.backgrounds.regular, 0.8); // this->messages.backgrounds.resub // this->messages.backgrounds.whisper this->messages.disabled = getColor(0, sat, 1, 0.6); diff --git a/src/singletons/windowmanager.cpp b/src/singletons/windowmanager.cpp index bc601bec3..8f8ce007b 100644 --- a/src/singletons/windowmanager.cpp +++ b/src/singletons/windowmanager.cpp @@ -1,12 +1,19 @@ #include "windowmanager.hpp" #include "debug/log.hpp" +#include "providers/twitch/twitchserver.hpp" #include "singletons/fontmanager.hpp" +#include "singletons/pathmanager.hpp" #include "singletons/thememanager.hpp" #include "widgets/accountswitchpopupwidget.hpp" #include "widgets/settingsdialog.hpp" +#include +#include + #include +#define SETTINGS_FILENAME "/layout.json" + namespace chatterino { namespace singletons { @@ -51,11 +58,6 @@ WindowManager::WindowManager(ThemeManager &_themeManager) _themeManager.repaintVisibleChatWidgets.connect([this] { this->repaintVisibleChatWidgets(); }); } -void WindowManager::initMainWindow() -{ - this->selectedWindow = this->mainWindow = new widgets::Window("main", this->themeManager, true); -} - void WindowManager::layoutVisibleChatWidgets(Channel *channel) { this->layout.invoke(channel); @@ -90,12 +92,12 @@ widgets::Window &WindowManager::getSelectedWindow() return *this->selectedWindow; } -widgets::Window &WindowManager::createWindow() +widgets::Window &WindowManager::createWindow(widgets::Window::WindowType type) { - auto *window = new widgets::Window("external", this->themeManager, false); - window->getNotebook().addNewPage(); + auto *window = new widgets::Window(this->themeManager, type); this->windows.push_back(window); + window->show(); return *window; } @@ -115,14 +117,168 @@ widgets::Window *WindowManager::windowAt(int index) return this->windows.at(index); } +void WindowManager::initialize() +{ + assert(!this->initialized); + + // load file + QString settingsPath = PathManager::getInstance().settingsFolderPath + SETTINGS_FILENAME; + QFile file(settingsPath); + file.open(QIODevice::ReadOnly); + QByteArray data = file.readAll(); + QJsonDocument document = QJsonDocument::fromJson(data); + QJsonArray windows_arr = document.object().value("windows").toArray(); + + // "deserialize" + for (QJsonValue window_val : windows_arr) { + QJsonObject window_obj = window_val.toObject(); + + // get type + QString type_val = window_obj.value("type").toString(); + widgets::Window::WindowType type = + type_val == "main" ? widgets::Window::Main : widgets::Window::Popup; + + if (type == widgets::Window::Main && mainWindow != nullptr) { + type = widgets::Window::Popup; + } + + widgets::Window &window = createWindow(type); + + if (type == widgets::Window::Main) { + mainWindow = &window; + } + + // get geometry + { + int x = window_obj.value("x").toInt(-1); + int y = window_obj.value("y").toInt(-1); + int width = window_obj.value("width").toInt(-1); + int height = window_obj.value("height").toInt(-1); + + if (x != -1 && y != -1 && width != -1 && height != -1) { + window.setGeometry(x, y, width, height); + } + } + + // load tabs + QJsonArray tabs = window_obj.value("tabs").toArray(); + for (QJsonValue tab_val : tabs) { + widgets::SplitContainer *tab = window.getNotebook().addNewPage(); + + 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; + } + + // load splits + 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); + + QJsonObject split_obj = split_val.toObject(); + QJsonValue channelName_val = split_obj.value("channelName"); + if (channelName_val.isString()) { + split->setChannel(providers::twitch::TwitchServer::getInstance().addChannel( + channelName_val.toString())); + } + + tab->addToLayout(split, std::make_pair(colNr, -1)); + } + colNr++; + } + } + } + + if (mainWindow == nullptr) { + mainWindow = &createWindow(widgets::Window::Main); + mainWindow->getNotebook().addNewPage(true); + } + + this->initialized = true; +} + void WindowManager::save() { - assert(this->mainWindow); - - this->mainWindow->save(); + QJsonDocument document; + // "serialize" + QJsonArray window_arr; for (widgets::Window *window : this->windows) { - window->save(); + QJsonObject window_obj; + + // window type + switch (window->getType()) { + case widgets::Window::Main: + window_obj.insert("type", "main"); + break; + case widgets::Window::Popup: + window_obj.insert("type", "popup"); + break; + } + + // window geometry + window_obj.insert("x", window->x()); + window_obj.insert("y", window->y()); + window_obj.insert("width", window->width()); + window_obj.insert("height", window->height()); + + // window tabs + QJsonArray tabs_arr; + + for (int tab_i = 0; tab_i < window->getNotebook().tabCount(); tab_i++) { + QJsonObject tab_obj; + widgets::SplitContainer *tab = window->getNotebook().tabAt(tab_i); + + // custom tab title + if (!tab->getTab()->useDefaultTitle) { + tab_obj.insert("title", tab->getTab()->getTitle()); + } + + // splits + QJsonArray columns_arr; + std::vector> columns = tab->getColumns(); + + for (std::vector &cells : columns) { + QJsonArray cells_arr; + + for (widgets::Split *cell : cells) { + QJsonObject cell_obj; + cell_obj.insert("channelName", cell->getChannel()->name); + + cells_arr.append(cell_obj); + } + columns_arr.append(cells_arr); + } + + tab_obj.insert("splits", columns_arr); + tabs_arr.append(tab_obj); + } + + window_obj.insert("tabs", tabs_arr); + window_arr.append(window_obj); + } + + QJsonObject obj; + obj.insert("windows", window_arr); + document.setObject(obj); + + // save file + QString settingsPath = PathManager::getInstance().settingsFolderPath + SETTINGS_FILENAME; + QFile file(settingsPath); + file.open(QIODevice::WriteOnly | QIODevice::Truncate); + file.write(document.toJson()); + file.flush(); +} + +void WindowManager::closeAll() +{ + for (widgets::Window *window : windows) { + window->close(); } } diff --git a/src/singletons/windowmanager.hpp b/src/singletons/windowmanager.hpp index c95984d22..349de4cc6 100644 --- a/src/singletons/windowmanager.hpp +++ b/src/singletons/windowmanager.hpp @@ -17,7 +17,6 @@ public: void showSettingsDialog(); void showAccountSelectPopup(QPoint point); - void initMainWindow(); void layoutVisibleChatWidgets(Channel *channel = nullptr); void repaintVisibleChatWidgets(Channel *channel = nullptr); void repaintGifEmotes(); @@ -25,12 +24,14 @@ public: widgets::Window &getMainWindow(); widgets::Window &getSelectedWindow(); - widgets::Window &createWindow(); + widgets::Window &createWindow(widgets::Window::WindowType type); int windowCount(); widgets::Window *windowAt(int index); void save(); + void initialize(); + void closeAll(); pajlada::Signals::NoArgSignal repaintGifs; pajlada::Signals::Signal layout; @@ -38,6 +39,8 @@ public: private: ThemeManager &themeManager; + bool initialized = false; + std::vector windows; widgets::Window *mainWindow = nullptr; diff --git a/src/widgets/basewindow.cpp b/src/widgets/basewindow.cpp index 950fd6790..97e6483fa 100644 --- a/src/widgets/basewindow.cpp +++ b/src/widgets/basewindow.cpp @@ -69,7 +69,12 @@ void BaseWindow::init() layout->addLayout(buttonLayout); // title - QLabel *title = new QLabel(" Chatterino"); + // QLabel *title = new QLabel(" Chatterino"); + QLabel *title = new QLabel(""); + QSizePolicy policy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + policy.setHorizontalStretch(1); + title->setBaseSize(0, 0); + title->setSizePolicy(policy); buttonLayout->addWidget(title); this->titleLabel = title; diff --git a/src/widgets/helper/channelview.cpp b/src/widgets/helper/channelview.cpp index 177ecc882..a07337402 100644 --- a/src/widgets/helper/channelview.cpp +++ b/src/widgets/helper/channelview.cpp @@ -111,6 +111,7 @@ ChannelView::ChannelView(BaseWidget *parent) QObject::connect(this->layoutCooldown, &QTimer::timeout, [this] { if (this->layoutQueued) { this->layoutMessages(); + this->layoutQueued = false; } }); } @@ -137,15 +138,15 @@ void ChannelView::themeRefreshEvent() void ChannelView::queueUpdate() { - if (this->updateTimer.isActive()) { - this->updateQueued = true; - return; - } + // if (this->updateTimer.isActive()) { + // this->updateQueued = true; + // return; + // } // this->repaint(); this->update(); - this->updateTimer.start(); + // this->updateTimer.start(); } void ChannelView::layoutMessages() diff --git a/src/widgets/helper/notebooktab.cpp b/src/widgets/helper/notebooktab.cpp index de26c24c7..36870bc5d 100644 --- a/src/widgets/helper/notebooktab.cpp +++ b/src/widgets/helper/notebooktab.cpp @@ -17,14 +17,10 @@ namespace chatterino { namespace widgets { -NotebookTab::NotebookTab(Notebook *_notebook, const std::string &_uuid) +NotebookTab::NotebookTab(Notebook *_notebook) : BaseWidget(_notebook) - , uuid(_uuid) - , settingRoot(fS("/containers/{}/tab", this->uuid)) , positionChangedAnimation(this, "pos") , notebook(_notebook) - , title(fS("{}/title", this->settingRoot), "") - , useDefaultBehaviour(fS("{}/useDefaultBehaviour", this->settingRoot), true) , menu(this) { this->setAcceptDrops(true); @@ -40,7 +36,7 @@ NotebookTab::NotebookTab(Notebook *_notebook, const std::string &_uuid) TextInputDialog d(this); d.setWindowTitle("Change tab title (Leave empty for default behaviour)"); - if (this->useDefaultBehaviour) { + if (this->useDefaultTitle) { d.setText(""); } else { d.setText(this->getTitle()); @@ -49,10 +45,10 @@ NotebookTab::NotebookTab(Notebook *_notebook, const std::string &_uuid) if (d.exec() == QDialog::Accepted) { QString newTitle = d.getText(); if (newTitle.isEmpty()) { - this->useDefaultBehaviour = true; + this->useDefaultTitle = true; this->page->refreshTitle(); } else { - this->useDefaultBehaviour = false; + this->useDefaultTitle = false; this->setTitle(newTitle); } } @@ -82,11 +78,10 @@ void NotebookTab::updateSize() int width; - QString qTitle(qS(this->title)); if (singletons::SettingManager::getInstance().hideTabX) { - width = (int)((fontMetrics().width(qTitle) + 16 /*+ 16*/) * scale); + width = (int)((fontMetrics().width(this->title) + 16 /*+ 16*/) * scale); } else { - width = (int)((fontMetrics().width(qTitle) + 8 + 24 /*+ 16*/) * scale); + width = (int)((fontMetrics().width(this->title) + 8 + 24 /*+ 16*/) * scale); } this->resize(std::min((int)(150 * scale), width), (int)(24 * scale)); @@ -96,17 +91,15 @@ void NotebookTab::updateSize() } } -QString NotebookTab::getTitle() const +const QString &NotebookTab::getTitle() const { - return qS(this->title); + return this->title; } void NotebookTab::setTitle(const QString &newTitle) { - auto stdTitle = newTitle.toStdString(); - - if (this->title != stdTitle) { - this->title = stdTitle; + if (this->title != newTitle) { + this->title = newTitle; this->updateSize(); this->update(); } diff --git a/src/widgets/helper/notebooktab.hpp b/src/widgets/helper/notebooktab.hpp index c474e7059..2f871dd22 100644 --- a/src/widgets/helper/notebooktab.hpp +++ b/src/widgets/helper/notebooktab.hpp @@ -18,17 +18,14 @@ class NotebookTab : public BaseWidget { Q_OBJECT - const std::string uuid; - const std::string settingRoot; - public: - explicit NotebookTab(Notebook *_notebook, const std::string &_uuid); + explicit NotebookTab(Notebook *_notebook); void updateSize(); SplitContainer *page; - QString getTitle() const; + const QString &getTitle() const; void setTitle(const QString &newTitle); bool isSelected() const; void setSelected(bool value); @@ -63,10 +60,10 @@ private: Notebook *notebook; - pajlada::Settings::Setting title; + QString title; public: - pajlada::Settings::Setting useDefaultBehaviour; + bool useDefaultTitle = true; private: bool selected = false; diff --git a/src/widgets/helper/splitheader.cpp b/src/widgets/helper/splitheader.cpp index 3228e2f05..b6c198ab1 100644 --- a/src/widgets/helper/splitheader.cpp +++ b/src/widgets/helper/splitheader.cpp @@ -155,7 +155,7 @@ void SplitHeader::scaleChangedEvent(float scale) void SplitHeader::updateChannelText() { - const QString channelName = this->split->channelName; + const QString channelName = this->split->getChannel()->name; if (channelName.isEmpty()) { this->titleLabel->setText(""); return; diff --git a/src/widgets/notebook.cpp b/src/widgets/notebook.cpp index fd73921ae..e8f491f9b 100644 --- a/src/widgets/notebook.cpp +++ b/src/widgets/notebook.cpp @@ -22,15 +22,13 @@ namespace chatterino { namespace widgets { -Notebook::Notebook(Window *parent, bool _showButtons, const std::string &settingPrefix) +Notebook::Notebook(Window *parent, bool _showButtons) : BaseWidget(parent) - , settingRoot(fS("{}/notebook", settingPrefix)) , parentWindow(parent) , addButton(this) , settingsButton(this) , userButton(this) , showButtons(_showButtons) - , tabs(fS("{}/tabs", this->settingRoot)) , closeConfirmDialog(this) { this->connect(&this->settingsButton, SIGNAL(clicked()), this, SLOT(settingsButtonClicked())); @@ -47,8 +45,6 @@ Notebook::Notebook(Window *parent, bool _showButtons, const std::string &setting settingsManager.hidePreferencesButton.connectSimple([this](auto) { this->performLayout(); }); settingsManager.hideUserButton.connectSimple([this](auto) { this->performLayout(); }); - this->loadTabs(); - closeConfirmDialog.setText("Are you sure you want to close this tab?"); closeConfirmDialog.setIcon(QMessageBox::Icon::Question); closeConfirmDialog.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); @@ -57,15 +53,10 @@ Notebook::Notebook(Window *parent, bool _showButtons, const std::string &setting this->scaleChangedEvent(this->getScale()); } -SplitContainer *Notebook::addNewPage() +SplitContainer *Notebook::addNewPage(bool select) { - return this->addPage(CreateUUID().toStdString(), true); -} - -SplitContainer *Notebook::addPage(const std::string &uuid, bool select) -{ - auto tab = new NotebookTab(this, uuid); - auto page = new SplitContainer(this, tab, uuid); + auto tab = new NotebookTab(this); + auto page = new SplitContainer(this, tab); tab->show(); @@ -178,6 +169,11 @@ SplitContainer *Notebook::tabAt(QPoint point, int &index, int maxWidth) 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); @@ -244,7 +240,7 @@ void Notebook::performLayout(bool animated) for (auto &i : this->pages) { if (!first && (i == this->pages.last() ? tabHeight : 0) + x + i->getTab()->width() > width()) { - y += i->getTab()->height() - 1; + y += i->getTab()->height(); // y += 20; i->getTab()->moveAnimated(QPoint(0, y), animated); x = i->getTab()->width(); @@ -310,33 +306,7 @@ void Notebook::usersButtonClicked() void Notebook::addPageButtonClicked() { - QTimer::singleShot(80, [this] { this->addNewPage(); }); -} - -void Notebook::loadTabs() -{ - const std::vector tabArray = this->tabs.getValue(); - - if (tabArray.size() == 0) { - this->addNewPage(); - return; - } - - for (const std::string &tabUUID : tabArray) { - this->addPage(tabUUID); - } -} - -void Notebook::save() -{ - std::vector tabArray; - - for (const auto &page : this->pages) { - tabArray.push_back(page->getUUID()); - page->save(); - } - - this->tabs = tabArray; + QTimer::singleShot(80, [this] { this->addNewPage(true); }); } } // namespace widgets diff --git a/src/widgets/notebook.hpp b/src/widgets/notebook.hpp index 082768afd..9f0bd4f17 100644 --- a/src/widgets/notebook.hpp +++ b/src/widgets/notebook.hpp @@ -18,23 +18,24 @@ class Notebook : public BaseWidget { Q_OBJECT - std::string settingRoot; - public: enum HighlightType { none, highlighted, newMessage }; - explicit Notebook(Window *parent, bool _showButtons, const std::string &settingPrefix); + explicit Notebook(Window *parent, bool _showButtons); - SplitContainer *addNewPage(); - SplitContainer *addPage(const std::string &uuid, bool select = false); + SplitContainer *addNewPage(bool select = false); void removePage(SplitContainer *page); void removeCurrentPage(); void select(SplitContainer *page); void selectIndex(int index); - SplitContainer *getSelectedPage() const + SplitContainer *getOrAddSelectedPage() { + if (selectedPage == nullptr) { + this->addNewPage(true); + } + return selectedPage; } @@ -42,6 +43,7 @@ public: int tabCount(); SplitContainer *tabAt(QPoint point, int &index, int maxWidth = 2000000000); + SplitContainer *tabAt(int index); void rearrangePage(SplitContainer *page, int index); void nextTab(); @@ -71,14 +73,7 @@ private: bool showButtons; - pajlada::Settings::Setting> tabs; - - void loadTabs(); - QMessageBox closeConfirmDialog; - -public: - void save(); }; } // namespace widgets diff --git a/src/widgets/split.cpp b/src/widgets/split.cpp index 7cfad2b66..21d952aae 100644 --- a/src/widgets/split.cpp +++ b/src/widgets/split.cpp @@ -36,11 +36,8 @@ using namespace chatterino::messages; namespace chatterino { namespace widgets { -Split::Split(SplitContainer *parent, const std::string &_uuid) +Split::Split(SplitContainer *parent) : BaseWidget(parent) - , uuid(_uuid) - , settingRoot(fS("/splits/{}", this->uuid)) - , channelName(fS("{}/channelName", this->settingRoot)) , parentPage(*parent) , channel(Channel::getEmpty()) , vbox(this) @@ -86,11 +83,6 @@ Split::Split(SplitContainer *parent, const std::string &_uuid) // CreateShortcut(this, "ALT+SHIFT+UP", &Split::doIncFlexY); // CreateShortcut(this, "ALT+SHIFT+DOWN", &Split::doDecFlexY); - this->channelName.getValueChangedSignal().connect( - std::bind(&Split::channelNameUpdated, this, std::placeholders::_1)); - - this->channelNameUpdated(this->channelName.getValue()); - this->input.ui.textEdit->installEventFilter(parent); this->view.mouseDown.connect([this](QMouseEvent *) { this->giveFocus(Qt::MouseFocusReason); }); @@ -130,11 +122,6 @@ Split::~Split() this->channelIDChangedConnection.disconnect(); } -const std::string &Split::getUUID() const -{ - return this->uuid; -} - ChannelPtr Split::getChannel() const { return this->channel; @@ -156,6 +143,7 @@ void Split::setChannel(ChannelPtr _newChannel) } this->header.updateModerationModeIcon(); + this->header.updateChannelText(); this->channelChanged.invoke(); } @@ -196,19 +184,6 @@ bool Split::getModerationMode() const return this->moderationMode; } -void Split::channelNameUpdated(const QString &newChannelName) -{ - // update messages - if (newChannelName.isEmpty()) { - this->setChannel(Channel::getEmpty()); - } else { - this->setChannel(TwitchServer::getInstance().addChannel(newChannelName)); - } - - // update header - this->header.updateChannelText(); -} - bool Split::showChangeChannelPopup(const char *dialogTitle, bool empty) { // create new input dialog and execute it @@ -217,13 +192,13 @@ bool Split::showChangeChannelPopup(const char *dialogTitle, bool empty) dialog.setWindowTitle(dialogTitle); if (!empty) { - dialog.setText(this->channelName); + dialog.setText(this->channel->name); } if (dialog.exec() == QDialog::Accepted) { QString newChannelName = dialog.getText().trimmed(); - this->channelName = newChannelName; + this->setChannel(providers::twitch::TwitchServer::getInstance().addChannel(newChannelName)); this->parentPage.refreshTitle(); return true; @@ -328,12 +303,13 @@ void Split::doChangeChannel() void Split::doPopup() { - Window &window = singletons::WindowManager::getInstance().createWindow(); + Window &window = singletons::WindowManager::getInstance().createWindow(Window::Popup); - Split *split = new Split(static_cast(window.getNotebook().getSelectedPage()), - this->uuid); + Split *split = + new Split(static_cast(window.getNotebook().getOrAddSelectedPage())); - window.getNotebook().getSelectedPage()->addToLayout(split); + split->setChannel(this->getChannel()); + window.getNotebook().getOrAddSelectedPage()->addToLayout(split); window.show(); } @@ -366,7 +342,7 @@ void Split::doOpenPopupPlayer() void Split::doOpenStreamlink() { try { - streamlink::Start(this->channelName.getValue()); + streamlink::Start(this->channel->name); } catch (const streamlink::Exception &ex) { debug::Log("Error in doOpenStreamlink: {}", ex.what()); } diff --git a/src/widgets/split.hpp b/src/widgets/split.hpp index 38e2168bd..ddd71416b 100644 --- a/src/widgets/split.hpp +++ b/src/widgets/split.hpp @@ -42,14 +42,10 @@ class Split : public BaseWidget Q_OBJECT - const std::string uuid; - const std::string settingRoot; - public: - Split(SplitContainer *parent, const std::string &_uuid); + Split(SplitContainer *parent); ~Split() override; - pajlada::Settings::Setting channelName; pajlada::Signals::NoArgSignal channelChanged; ChannelView &getChannelView() @@ -57,8 +53,9 @@ public: return this->view; } - const std::string &getUUID() const; ChannelPtr getChannel() const; + void setChannel(ChannelPtr newChannel); + void setFlexSizeX(double x); double getFlexSizeX(); void setFlexSizeY(double y); @@ -98,8 +95,6 @@ private: pajlada::Signals::Connection channelIDChangedConnection; pajlada::Signals::Connection usermodeChangedConnection; - - void setChannel(ChannelPtr newChannel); void doOpenAccountPopupWidget(AccountPopupWidget *widget, QString user); void channelNameUpdated(const QString &newChannelName); void handleModifiers(QEvent *event, Qt::KeyboardModifiers modifiers); diff --git a/src/widgets/splitcontainer.cpp b/src/widgets/splitcontainer.cpp index b736397aa..f7d6f6894 100644 --- a/src/widgets/splitcontainer.cpp +++ b/src/widgets/splitcontainer.cpp @@ -26,12 +26,9 @@ bool SplitContainer::isDraggingSplit = false; Split *SplitContainer::draggingSplit = nullptr; std::pair SplitContainer::dropPosition = std::pair(-1, -1); -SplitContainer::SplitContainer(Notebook *parent, NotebookTab *_tab, const std::string &_uuid) +SplitContainer::SplitContainer(Notebook *parent, NotebookTab *_tab) : BaseWidget(parent->themeManager, parent) - , uuid(_uuid) - , settingRoot(fS("/containers/{}", this->uuid)) , tab(_tab) - , chats(fS("{}/chats", this->settingRoot)) , dropPreview(this) { this->tab->page = this; @@ -48,8 +45,6 @@ SplitContainer::SplitContainer(Notebook *parent, NotebookTab *_tab, const std::s this->ui.hbox.setSpacing(1); this->ui.hbox.setMargin(0); - this->loadSplits(); - this->refreshTitle(); } @@ -147,6 +142,24 @@ const std::vector &SplitContainer::getSplits() const return this->splits; } +std::vector> SplitContainer::getColumns() const +{ + std::vector> columns; + + for (int i = 0; i < this->ui.hbox.count(); i++) { + std::vector cells; + + QLayout *vbox = this->ui.hbox.itemAt(i)->layout(); + for (int j = 0; j < vbox->count(); j++) { + cells.push_back(dynamic_cast(vbox->itemAt(j)->widget())); + } + + columns.push_back(cells); + } + + return columns; +} + NotebookTab *SplitContainer::getTab() const { return this->tab; @@ -447,7 +460,7 @@ std::pair SplitContainer::getChatPosition(const Split *chatWidget) Split *SplitContainer::createChatWidget(const std::string &uuid) { - auto split = new Split(this, uuid); + auto split = new Split(this); split->getChannelView().highlightedMessageReceived.connect([this] { // fourtf: error potentionally here @@ -459,7 +472,7 @@ Split *SplitContainer::createChatWidget(const std::string &uuid) void SplitContainer::refreshTitle() { - if (!this->tab->useDefaultBehaviour) { + if (!this->tab->useDefaultTitle) { return; } @@ -467,7 +480,7 @@ void SplitContainer::refreshTitle() bool first = true; for (const auto &chatWidget : this->splits) { - auto channelName = chatWidget->channelName.getValue(); + auto channelName = chatWidget->getChannel()->name; if (channelName.isEmpty()) { continue; } @@ -487,83 +500,5 @@ void SplitContainer::refreshTitle() this->tab->setTitle(newTitle); } -void SplitContainer::loadSplits() -{ - const auto hboxes = this->chats.getValue(); - int column = 0; - for (const std::vector &hbox : hboxes) { - int row = 0; - for (const std::string &chatUUID : hbox) { - Split *split = this->createChatWidget(chatUUID); - - this->addToLayout(split, std::pair(column, row)); - - ++row; - } - ++column; - } -} - -template -static void saveFromLayout(QLayout *layout, Container &container) -{ - for (int i = 0; i < layout->count(); ++i) { - auto item = layout->itemAt(i); - - auto innerLayout = item->layout(); - if (innerLayout != nullptr) { - std::vector vbox; - - for (int j = 0; j < innerLayout->count(); ++j) { - auto innerItem = innerLayout->itemAt(j); - auto innerWidget = innerItem->widget(); - if (innerWidget == nullptr) { - assert(false); - continue; - } - Split *innerSplit = qobject_cast(innerWidget); - vbox.push_back(innerSplit->getUUID()); - } - - container.push_back(vbox); - - continue; - } - } -} - -void SplitContainer::save() -{ - auto layout = this->ui.hbox.layout(); - - std::vector> _chats; - - for (int i = 0; i < layout->count(); ++i) { - auto item = layout->itemAt(i); - - auto innerLayout = item->layout(); - if (innerLayout != nullptr) { - std::vector vbox; - - for (int j = 0; j < innerLayout->count(); ++j) { - auto innerItem = innerLayout->itemAt(j); - auto innerWidget = innerItem->widget(); - if (innerWidget == nullptr) { - assert(false); - continue; - } - Split *innerSplit = qobject_cast(innerWidget); - vbox.push_back(innerSplit->getUUID()); - } - - _chats.push_back(vbox); - - continue; - } - } - - this->chats = _chats; -} - } // namespace widgets } // namespace chatterino diff --git a/src/widgets/splitcontainer.hpp b/src/widgets/splitcontainer.hpp index bf07022f3..44093c8ae 100644 --- a/src/widgets/splitcontainer.hpp +++ b/src/widgets/splitcontainer.hpp @@ -19,21 +19,14 @@ class SplitContainer : public BaseWidget { Q_OBJECT - const std::string uuid; - const std::string settingRoot; - public: - SplitContainer(Notebook *parent, NotebookTab *_tab, const std::string &_uuid); - - const std::string &getUUID() const - { - return this->uuid; - } + SplitContainer(Notebook *parent, NotebookTab *_tab); std::pair removeFromLayout(Split *widget); void addToLayout(Split *widget, std::pair position = std::pair(-1, -1)); const std::vector &getSplits() const; + std::vector> getColumns() const; NotebookTab *getTab() const; void addChat(bool openChannelNameDialog = false, std::string chatUUID = std::string()); @@ -90,8 +83,6 @@ private: std::vector splits; std::vector dropRegions; - pajlada::Settings::Setting>> chats; - NotebookPageDropPreview dropPreview; void setPreviewRect(QPoint mousePos); diff --git a/src/widgets/window.cpp b/src/widgets/window.cpp index 3326a33fe..b0163014e 100644 --- a/src/widgets/window.cpp +++ b/src/widgets/window.cpp @@ -18,13 +18,11 @@ namespace chatterino { namespace widgets { -Window::Window(const QString &windowName, singletons::ThemeManager &_themeManager, - bool _isMainWindow) +Window::Window(singletons::ThemeManager &_themeManager, WindowType _type) : BaseWindow(_themeManager, nullptr, true) - , settingRoot(fS("/windows/{}", windowName)) - , windowGeometry(this->settingRoot) + , type(_type) , dpi(this->getScale()) - , notebook(this, _isMainWindow, this->settingRoot) + , notebook(this, !this->hasCustomWindowFrame()) { singletons::AccountManager::getInstance().Twitch.currentUsername.connect( [this](const std::string &newUsername, auto) { @@ -35,7 +33,7 @@ Window::Window(const QString &windowName, singletons::ThemeManager &_themeManage } }); - if (this->hasCustomWindowFrame()) { + if (this->hasCustomWindowFrame() && _type == Window::Main) { this->addTitleBarButton(TitleBarButton::Settings, [] { singletons::WindowManager::getInstance().showSettingsDialog(); }); @@ -49,6 +47,12 @@ Window::Window(const QString &windowName, singletons::ThemeManager &_themeManage }); } + if (_type == Window::Main) { + this->resize((int)(600 * this->getScale()), (int)(500 * this->getScale())); + } else { + this->resize((int)(300 * this->getScale()), (int)(500 * this->getScale())); + } + QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(&this->notebook); @@ -59,8 +63,6 @@ Window::Window(const QString &windowName, singletons::ThemeManager &_themeManage this->themeRefreshEvent(); - this->loadGeometry(); - /// Initialize program-wide hotkeys // CTRL+P: Open Settings Dialog CreateWindowShortcut(this, "CTRL+P", [] { SettingsDialog::showDialog(); }); @@ -77,7 +79,7 @@ Window::Window(const QString &windowName, singletons::ThemeManager &_themeManage CreateWindowShortcut(this, "CTRL+9", [this] { this->notebook.selectIndex(8); }); // CTRL+SHIFT+T: New tab - CreateWindowShortcut(this, "CTRL+SHIFT+T", [this] { this->notebook.addNewPage(); }); + CreateWindowShortcut(this, "CTRL+SHIFT+T", [this] { this->notebook.addNewPage(true); }); // CTRL+SHIFT+W: Close current tab CreateWindowShortcut(this, "CTRL+SHIFT+W", [this] { this->notebook.removeCurrentPage(); }); @@ -102,9 +104,14 @@ Window::Window(const QString &windowName, singletons::ThemeManager &_themeManage // }); } +Window::WindowType Window::getType() +{ + return this->type; +} + void Window::repaintVisibleChatWidgets(Channel *channel) { - auto *page = this->notebook.getSelectedPage(); + auto *page = this->notebook.getOrAddSelectedPage(); if (page == nullptr) { return; @@ -127,18 +134,6 @@ void Window::refreshWindowTitle(const QString &username) this->setWindowTitle(username + " - Chatterino for Twitch"); } -void Window::closeEvent(QCloseEvent *) -{ - const QRect &geom = this->geometry(); - - this->windowGeometry.x = geom.x(); - this->windowGeometry.y = geom.y(); - this->windowGeometry.width = geom.width(); - this->windowGeometry.height = geom.height(); - - this->closed.invoke(); -} - bool Window::event(QEvent *e) { switch (e->type()) { @@ -146,7 +141,7 @@ bool Window::event(QEvent *e) break; case QEvent::WindowDeactivate: { - auto page = this->notebook.getSelectedPage(); + auto page = this->notebook.getOrAddSelectedPage(); if (page != nullptr) { std::vector splits = page->getSplits(); @@ -160,35 +155,14 @@ bool Window::event(QEvent *e) return BaseWindow::event(e); } -void Window::loadGeometry() +void Window::closeEvent(QCloseEvent *event) { - bool doSetGeometry = false; - QRect loadedGeometry; - if (!this->windowGeometry.x.isDefaultValue() && !this->windowGeometry.y.isDefaultValue()) { - loadedGeometry.setX(this->windowGeometry.x); - loadedGeometry.setY(this->windowGeometry.y); - doSetGeometry = true; + if (this->type == Window::Main) { + singletons::WindowManager::getInstance().save(); + singletons::WindowManager::getInstance().closeAll(); } - if (!this->windowGeometry.width.isDefaultValue() && - !this->windowGeometry.height.isDefaultValue()) { - loadedGeometry.setWidth(this->windowGeometry.width); - loadedGeometry.setHeight(this->windowGeometry.height); - } else { - loadedGeometry.setWidth(1280); - loadedGeometry.setHeight(720); - } - - if (doSetGeometry) { - this->setGeometry(loadedGeometry); - } else { - this->resize(loadedGeometry.width(), loadedGeometry.height()); - } -} - -void Window::save() -{ - this->notebook.save(); + this->closed.invoke(); } } // namespace widgets diff --git a/src/widgets/window.hpp b/src/widgets/window.hpp index a82a9b299..b3b7a098f 100644 --- a/src/widgets/window.hpp +++ b/src/widgets/window.hpp @@ -18,32 +18,14 @@ class ThemeManager; namespace widgets { -struct WindowGeometry { - WindowGeometry(const std::string &settingPrefix) - : x(fS("{}/geometry/x", settingPrefix)) - , y(fS("{}/geometry/y", settingPrefix)) - , width(fS("{}/geometry/width", settingPrefix)) - , height(fS("{}/geometry/height", settingPrefix)) - { - } - - pajlada::Settings::Setting x; - pajlada::Settings::Setting y; - pajlada::Settings::Setting width; - pajlada::Settings::Setting height; -}; - class Window : public BaseWindow { Q_OBJECT - std::string settingRoot; - - WindowGeometry windowGeometry; - public: - explicit Window(const QString &windowName, singletons::ThemeManager &_themeManager, - bool isMainWindow); + enum WindowType { Main, Popup }; + + explicit Window(singletons::ThemeManager &_themeManager, WindowType type); void repaintVisibleChatWidgets(Channel *channel = nullptr); @@ -53,17 +35,19 @@ public: pajlada::Signals::NoArgSignal closed; + WindowType getType(); + protected: void closeEvent(QCloseEvent *event) override; bool event(QEvent *event) override; private: + WindowType type; float dpi; void loadGeometry(); Notebook notebook; - // TitleBar titleBar; friend class Notebook;