From a947bf74c8222f95f5b31ac4ed3b20ef8acf6537 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sun, 7 Oct 2018 16:27:40 +0000 Subject: [PATCH] Occasionally save window/split/tab layout The window layout is only saved if something has been changed. When something relevant to the window layout is changed, a save is queued to run after 10 seconds. If within those 10 seconds, another thing is changed, that timer is reset and will run after 10 seconds again. Events that cause the save to be queued up: - Tab created - Tab removed - Tab moved - Tab name changed - Split created - Split removed - Split moved - Split channel changed - Split resized - Window moved - Window resized What currently does not trigger the save to be queued up: - Active tab changed --- src/singletons/WindowManager.cpp | 19 +++++++++++++++++++ src/singletons/WindowManager.hpp | 7 +++++++ src/widgets/BaseWindow.cpp | 11 +++++++++++ src/widgets/BaseWindow.hpp | 1 + src/widgets/Notebook.cpp | 9 +++++++++ src/widgets/helper/NotebookTab.cpp | 4 ++++ src/widgets/splits/Split.cpp | 6 ++++++ src/widgets/splits/SplitContainer.cpp | 7 +++++++ 8 files changed, 64 insertions(+) diff --git a/src/singletons/WindowManager.cpp b/src/singletons/WindowManager.cpp index aa58ed48a..e75b0278c 100644 --- a/src/singletons/WindowManager.cpp +++ b/src/singletons/WindowManager.cpp @@ -23,6 +23,8 @@ #include #include +#include + #define SETTINGS_FILENAME "/window-layout.json" namespace chatterino { @@ -83,6 +85,14 @@ WindowManager::WindowManager() this->wordFlagsListener_.cb = [this](auto) { this->updateWordTypeMask(); // }; + + this->saveTimer = new QTimer; + + this->saveTimer->setSingleShot(true); + + QObject::connect(this->saveTimer, &QTimer::timeout, [] { + getApp()->windows->save(); // + }); } MessageElementFlags WindowManager::getWordFlags() @@ -357,6 +367,8 @@ void WindowManager::initialize(Settings &settings, Paths &paths) void WindowManager::save() { + log("[WindowManager] Saving"); + assertInGuiThread(); auto app = getApp(); @@ -453,6 +465,13 @@ void WindowManager::sendAlert() QApplication::alert(this->getMainWindow().window(), flashDuration); } +void WindowManager::queueSave() +{ + using namespace std::chrono_literals; + + this->saveTimer->start(10s); +} + void WindowManager::encodeNodeRecusively(SplitNode *node, QJsonObject &obj) { switch (node->getType()) { diff --git a/src/singletons/WindowManager.hpp b/src/singletons/WindowManager.hpp index 9ca3dc879..dc66b0c7f 100644 --- a/src/singletons/WindowManager.hpp +++ b/src/singletons/WindowManager.hpp @@ -77,6 +77,11 @@ public: // or not void sendAlert(); + // Queue up a save in the next 10 seconds + // If a save was already queued up, we reset the to happen in 10 seconds + // again + void queueSave(); + private: void encodeNodeRecusively(SplitContainer::Node *node, QJsonObject &obj); @@ -91,6 +96,8 @@ private: MessageElementFlags wordFlags_{}; pajlada::Settings::SettingListener wordFlagsListener_; + + QTimer *saveTimer; }; } // namespace chatterino diff --git a/src/widgets/BaseWindow.cpp b/src/widgets/BaseWindow.cpp index 6394284e0..5c6df9f54 100644 --- a/src/widgets/BaseWindow.cpp +++ b/src/widgets/BaseWindow.cpp @@ -420,11 +420,22 @@ void BaseWindow::moveTo(QWidget *parent, QPoint point, bool offset) void BaseWindow::resizeEvent(QResizeEvent *) { + // Queue up save because: Window resized + getApp()->windows->queueSave(); + this->moveIntoDesktopRect(this); this->calcButtonsSizes(); } +void BaseWindow::moveEvent(QMoveEvent *event) +{ + // Queue up save because: Window position changed + getApp()->windows->queueSave(); + + BaseWidget::moveEvent(event); +} + void BaseWindow::closeEvent(QCloseEvent *) { this->closing.invoke(); diff --git a/src/widgets/BaseWindow.hpp b/src/widgets/BaseWindow.hpp index 088c07c86..25b12025a 100644 --- a/src/widgets/BaseWindow.hpp +++ b/src/widgets/BaseWindow.hpp @@ -64,6 +64,7 @@ protected: virtual void changeEvent(QEvent *) override; virtual void leaveEvent(QEvent *) override; virtual void resizeEvent(QResizeEvent *) override; + virtual void moveEvent(QMoveEvent *) override; virtual void closeEvent(QCloseEvent *) override; virtual void themeChangedEvent() override; diff --git a/src/widgets/Notebook.cpp b/src/widgets/Notebook.cpp index c56fba8b5..3ec63fc29 100644 --- a/src/widgets/Notebook.cpp +++ b/src/widgets/Notebook.cpp @@ -45,6 +45,9 @@ Notebook::Notebook(QWidget *parent) NotebookTab *Notebook::addPage(QWidget *page, QString title, bool select) { + // Queue up save because: Tab added + getApp()->windows->queueSave(); + auto *tab = new NotebookTab(this); tab->page = page; @@ -72,6 +75,9 @@ NotebookTab *Notebook::addPage(QWidget *page, QString title, bool select) void Notebook::removePage(QWidget *page) { + // Queue up save because: Tab removed + getApp()->windows->queueSave(); + for (int i = 0; i < this->items_.count(); i++) { if (this->items_[i].page == page) { if (this->items_.count() == 1) { @@ -267,6 +273,9 @@ QWidget *Notebook::tabAt(QPoint point, int &index, int maxWidth) void Notebook::rearrangePage(QWidget *page, int index) { + // Queue up save because: Tab rearranged + getApp()->windows->queueSave(); + this->items_.move(this->indexOf(page), index); this->performLayout(true); diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index f3f2f7643..8875a4ca6 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -6,6 +6,7 @@ #include "singletons/Fonts.hpp" #include "singletons/Settings.hpp" #include "singletons/Theme.hpp" +#include "singletons/WindowManager.hpp" #include "util/Clamp.hpp" #include "util/Helpers.hpp" #include "widgets/Notebook.hpp" @@ -146,6 +147,9 @@ const QString &NotebookTab::getTitle() const void NotebookTab::titleUpdated() { + // Queue up save because: Tab title changed + getApp()->windows->queueSave(); + this->updateSize(); this->update(); } diff --git a/src/widgets/splits/Split.cpp b/src/widgets/splits/Split.cpp index 225e526fd..57348be6c 100644 --- a/src/widgets/splits/Split.cpp +++ b/src/widgets/splits/Split.cpp @@ -224,6 +224,9 @@ void Split::setChannel(IndirectChannel newChannel) this->header_->updateRoomModes(); this->channelChanged.invoke(); + + // Queue up save because: Split channel changed + getApp()->windows->queueSave(); } void Split::setModerationMode(bool value) @@ -326,6 +329,9 @@ void Split::keyReleaseEvent(QKeyEvent *event) void Split::resizeEvent(QResizeEvent *event) { + // Queue up save because: Split resized + getApp()->windows->queueSave(); + BaseWidget::resizeEvent(event); this->overlay_->setGeometry(this->rect()); diff --git a/src/widgets/splits/SplitContainer.cpp b/src/widgets/splits/SplitContainer.cpp index 86fc7673a..a4de3e6d1 100644 --- a/src/widgets/splits/SplitContainer.cpp +++ b/src/widgets/splits/SplitContainer.cpp @@ -1,4 +1,5 @@ #include "widgets/splits/SplitContainer.hpp" + #include "Application.hpp" #include "common/Common.hpp" #include "debug/AssertInGuiThread.hpp" @@ -142,6 +143,9 @@ void SplitContainer::insertSplit(Split *split, Direction direction, void SplitContainer::insertSplit(Split *split, Direction direction, Node *relativeTo) { + // Queue up save because: Split added + getApp()->windows->queueSave(); + assertInGuiThread(); split->setContainer(this); @@ -236,6 +240,9 @@ SplitContainer::Position SplitContainer::releaseSplit(Split *split) SplitContainer::Position SplitContainer::deleteSplit(Split *split) { + // Queue up save because: Split removed + getApp()->windows->queueSave(); + assertInGuiThread(); assert(split != nullptr);