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
This commit is contained in:
Rasmus Karlsson 2018-10-07 16:27:40 +00:00
parent 7879fef3a0
commit a947bf74c8
8 changed files with 64 additions and 0 deletions

View file

@ -23,6 +23,8 @@
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
#include <chrono>
#define SETTINGS_FILENAME "/window-layout.json" #define SETTINGS_FILENAME "/window-layout.json"
namespace chatterino { namespace chatterino {
@ -83,6 +85,14 @@ WindowManager::WindowManager()
this->wordFlagsListener_.cb = [this](auto) { this->wordFlagsListener_.cb = [this](auto) {
this->updateWordTypeMask(); // this->updateWordTypeMask(); //
}; };
this->saveTimer = new QTimer;
this->saveTimer->setSingleShot(true);
QObject::connect(this->saveTimer, &QTimer::timeout, [] {
getApp()->windows->save(); //
});
} }
MessageElementFlags WindowManager::getWordFlags() MessageElementFlags WindowManager::getWordFlags()
@ -357,6 +367,8 @@ void WindowManager::initialize(Settings &settings, Paths &paths)
void WindowManager::save() void WindowManager::save()
{ {
log("[WindowManager] Saving");
assertInGuiThread(); assertInGuiThread();
auto app = getApp(); auto app = getApp();
@ -453,6 +465,13 @@ void WindowManager::sendAlert()
QApplication::alert(this->getMainWindow().window(), flashDuration); 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) void WindowManager::encodeNodeRecusively(SplitNode *node, QJsonObject &obj)
{ {
switch (node->getType()) { switch (node->getType()) {

View file

@ -77,6 +77,11 @@ public:
// or not // or not
void sendAlert(); 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: private:
void encodeNodeRecusively(SplitContainer::Node *node, QJsonObject &obj); void encodeNodeRecusively(SplitContainer::Node *node, QJsonObject &obj);
@ -91,6 +96,8 @@ private:
MessageElementFlags wordFlags_{}; MessageElementFlags wordFlags_{};
pajlada::Settings::SettingListener wordFlagsListener_; pajlada::Settings::SettingListener wordFlagsListener_;
QTimer *saveTimer;
}; };
} // namespace chatterino } // namespace chatterino

View file

@ -420,11 +420,22 @@ void BaseWindow::moveTo(QWidget *parent, QPoint point, bool offset)
void BaseWindow::resizeEvent(QResizeEvent *) void BaseWindow::resizeEvent(QResizeEvent *)
{ {
// Queue up save because: Window resized
getApp()->windows->queueSave();
this->moveIntoDesktopRect(this); this->moveIntoDesktopRect(this);
this->calcButtonsSizes(); this->calcButtonsSizes();
} }
void BaseWindow::moveEvent(QMoveEvent *event)
{
// Queue up save because: Window position changed
getApp()->windows->queueSave();
BaseWidget::moveEvent(event);
}
void BaseWindow::closeEvent(QCloseEvent *) void BaseWindow::closeEvent(QCloseEvent *)
{ {
this->closing.invoke(); this->closing.invoke();

View file

@ -64,6 +64,7 @@ protected:
virtual void changeEvent(QEvent *) override; virtual void changeEvent(QEvent *) override;
virtual void leaveEvent(QEvent *) override; virtual void leaveEvent(QEvent *) override;
virtual void resizeEvent(QResizeEvent *) override; virtual void resizeEvent(QResizeEvent *) override;
virtual void moveEvent(QMoveEvent *) override;
virtual void closeEvent(QCloseEvent *) override; virtual void closeEvent(QCloseEvent *) override;
virtual void themeChangedEvent() override; virtual void themeChangedEvent() override;

View file

@ -45,6 +45,9 @@ Notebook::Notebook(QWidget *parent)
NotebookTab *Notebook::addPage(QWidget *page, QString title, bool select) NotebookTab *Notebook::addPage(QWidget *page, QString title, bool select)
{ {
// Queue up save because: Tab added
getApp()->windows->queueSave();
auto *tab = new NotebookTab(this); auto *tab = new NotebookTab(this);
tab->page = page; tab->page = page;
@ -72,6 +75,9 @@ NotebookTab *Notebook::addPage(QWidget *page, QString title, bool select)
void Notebook::removePage(QWidget *page) void Notebook::removePage(QWidget *page)
{ {
// Queue up save because: Tab removed
getApp()->windows->queueSave();
for (int i = 0; i < this->items_.count(); i++) { for (int i = 0; i < this->items_.count(); i++) {
if (this->items_[i].page == page) { if (this->items_[i].page == page) {
if (this->items_.count() == 1) { 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) void Notebook::rearrangePage(QWidget *page, int index)
{ {
// Queue up save because: Tab rearranged
getApp()->windows->queueSave();
this->items_.move(this->indexOf(page), index); this->items_.move(this->indexOf(page), index);
this->performLayout(true); this->performLayout(true);

View file

@ -6,6 +6,7 @@
#include "singletons/Fonts.hpp" #include "singletons/Fonts.hpp"
#include "singletons/Settings.hpp" #include "singletons/Settings.hpp"
#include "singletons/Theme.hpp" #include "singletons/Theme.hpp"
#include "singletons/WindowManager.hpp"
#include "util/Clamp.hpp" #include "util/Clamp.hpp"
#include "util/Helpers.hpp" #include "util/Helpers.hpp"
#include "widgets/Notebook.hpp" #include "widgets/Notebook.hpp"
@ -146,6 +147,9 @@ const QString &NotebookTab::getTitle() const
void NotebookTab::titleUpdated() void NotebookTab::titleUpdated()
{ {
// Queue up save because: Tab title changed
getApp()->windows->queueSave();
this->updateSize(); this->updateSize();
this->update(); this->update();
} }

View file

@ -224,6 +224,9 @@ void Split::setChannel(IndirectChannel newChannel)
this->header_->updateRoomModes(); this->header_->updateRoomModes();
this->channelChanged.invoke(); this->channelChanged.invoke();
// Queue up save because: Split channel changed
getApp()->windows->queueSave();
} }
void Split::setModerationMode(bool value) void Split::setModerationMode(bool value)
@ -326,6 +329,9 @@ void Split::keyReleaseEvent(QKeyEvent *event)
void Split::resizeEvent(QResizeEvent *event) void Split::resizeEvent(QResizeEvent *event)
{ {
// Queue up save because: Split resized
getApp()->windows->queueSave();
BaseWidget::resizeEvent(event); BaseWidget::resizeEvent(event);
this->overlay_->setGeometry(this->rect()); this->overlay_->setGeometry(this->rect());

View file

@ -1,4 +1,5 @@
#include "widgets/splits/SplitContainer.hpp" #include "widgets/splits/SplitContainer.hpp"
#include "Application.hpp" #include "Application.hpp"
#include "common/Common.hpp" #include "common/Common.hpp"
#include "debug/AssertInGuiThread.hpp" #include "debug/AssertInGuiThread.hpp"
@ -142,6 +143,9 @@ void SplitContainer::insertSplit(Split *split, Direction direction,
void SplitContainer::insertSplit(Split *split, Direction direction, void SplitContainer::insertSplit(Split *split, Direction direction,
Node *relativeTo) Node *relativeTo)
{ {
// Queue up save because: Split added
getApp()->windows->queueSave();
assertInGuiThread(); assertInGuiThread();
split->setContainer(this); split->setContainer(this);
@ -236,6 +240,9 @@ SplitContainer::Position SplitContainer::releaseSplit(Split *split)
SplitContainer::Position SplitContainer::deleteSplit(Split *split) SplitContainer::Position SplitContainer::deleteSplit(Split *split)
{ {
// Queue up save because: Split removed
getApp()->windows->queueSave();
assertInGuiThread(); assertInGuiThread();
assert(split != nullptr); assert(split != nullptr);