rewrote window saveing/serialization system

fixes #212
This commit is contained in:
fourtf 2018-04-06 23:31:34 +02:00
parent 4ec2c0d8b3
commit cb06579c29
19 changed files with 291 additions and 316 deletions

View file

@ -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();

View file

@ -47,7 +47,7 @@ bool SettingManager::isIgnoredEmote(const QString &)
return false;
}
void SettingManager::init()
void SettingManager::initialize()
{
QString settingsPath = PathManager::getInstance().settingsFolderPath + "/settings.json";

View file

@ -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};

View file

@ -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);

View file

@ -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 <QJsonDocument>
#include <QJsonObject>
#include <QDebug>
#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<std::vector<widgets::Split *>> columns = tab->getColumns();
for (std::vector<widgets::Split *> &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();
}
}

View file

@ -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<Channel *> layout;
@ -38,6 +39,8 @@ public:
private:
ThemeManager &themeManager;
bool initialized = false;
std::vector<widgets::Window *> windows;
widgets::Window *mainWindow = nullptr;

View file

@ -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;

View file

@ -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()

View file

@ -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();
}

View file

@ -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<std::string> title;
QString title;
public:
pajlada::Settings::Setting<bool> useDefaultBehaviour;
bool useDefaultTitle = true;
private:
bool selected = false;

View file

@ -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("<no channel>");
return;

View file

@ -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<std::string> 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<std::string> 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

View file

@ -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<std::vector<std::string>> tabs;
void loadTabs();
QMessageBox closeConfirmDialog;
public:
void save();
};
} // namespace widgets

View file

@ -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<SplitContainer *>(window.getNotebook().getSelectedPage()),
this->uuid);
Split *split =
new Split(static_cast<SplitContainer *>(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());
}

View file

@ -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<QString> 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);

View file

@ -26,12 +26,9 @@ bool SplitContainer::isDraggingSplit = false;
Split *SplitContainer::draggingSplit = nullptr;
std::pair<int, int> SplitContainer::dropPosition = std::pair<int, int>(-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<Split *> &SplitContainer::getSplits() const
return this->splits;
}
std::vector<std::vector<Split *>> SplitContainer::getColumns() const
{
std::vector<std::vector<Split *>> columns;
for (int i = 0; i < this->ui.hbox.count(); i++) {
std::vector<Split *> cells;
QLayout *vbox = this->ui.hbox.itemAt(i)->layout();
for (int j = 0; j < vbox->count(); j++) {
cells.push_back(dynamic_cast<Split *>(vbox->itemAt(j)->widget()));
}
columns.push_back(cells);
}
return columns;
}
NotebookTab *SplitContainer::getTab() const
{
return this->tab;
@ -447,7 +460,7 @@ std::pair<int, int> 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<std::string> &hbox : hboxes) {
int row = 0;
for (const std::string &chatUUID : hbox) {
Split *split = this->createChatWidget(chatUUID);
this->addToLayout(split, std::pair<int, int>(column, row));
++row;
}
++column;
}
}
template <typename Container>
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<std::string> 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<Split *>(innerWidget);
vbox.push_back(innerSplit->getUUID());
}
container.push_back(vbox);
continue;
}
}
}
void SplitContainer::save()
{
auto layout = this->ui.hbox.layout();
std::vector<std::vector<std::string>> _chats;
for (int i = 0; i < layout->count(); ++i) {
auto item = layout->itemAt(i);
auto innerLayout = item->layout();
if (innerLayout != nullptr) {
std::vector<std::string> 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<Split *>(innerWidget);
vbox.push_back(innerSplit->getUUID());
}
_chats.push_back(vbox);
continue;
}
}
this->chats = _chats;
}
} // namespace widgets
} // namespace chatterino

View file

@ -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<int, int> removeFromLayout(Split *widget);
void addToLayout(Split *widget, std::pair<int, int> position = std::pair<int, int>(-1, -1));
const std::vector<Split *> &getSplits() const;
std::vector<std::vector<Split *>> getColumns() const;
NotebookTab *getTab() const;
void addChat(bool openChannelNameDialog = false, std::string chatUUID = std::string());
@ -90,8 +83,6 @@ private:
std::vector<Split *> splits;
std::vector<DropRegion> dropRegions;
pajlada::Settings::Setting<std::vector<std::vector<std::string>>> chats;
NotebookPageDropPreview dropPreview;
void setPreviewRect(QPoint mousePos);

View file

@ -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<Split *> 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

View file

@ -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<int> x;
pajlada::Settings::Setting<int> y;
pajlada::Settings::Setting<int> width;
pajlada::Settings::Setting<int> 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;