mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
parent
4ec2c0d8b3
commit
cb06579c29
19 changed files with 291 additions and 316 deletions
|
@ -21,10 +21,10 @@ Application::Application()
|
||||||
|
|
||||||
singletons::LoggingManager::getInstance();
|
singletons::LoggingManager::getInstance();
|
||||||
|
|
||||||
singletons::SettingManager::getInstance().init();
|
singletons::SettingManager::getInstance().initialize();
|
||||||
singletons::CommandManager::getInstance().loadCommands();
|
singletons::CommandManager::getInstance().loadCommands();
|
||||||
|
|
||||||
singletons::WindowManager::getInstance().initMainWindow();
|
singletons::WindowManager::getInstance().initialize();
|
||||||
|
|
||||||
// Initialize everything we need
|
// Initialize everything we need
|
||||||
singletons::EmoteManager::getInstance().loadGlobalEmotes();
|
singletons::EmoteManager::getInstance().loadGlobalEmotes();
|
||||||
|
|
|
@ -47,7 +47,7 @@ bool SettingManager::isIgnoredEmote(const QString &)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingManager::init()
|
void SettingManager::initialize()
|
||||||
{
|
{
|
||||||
QString settingsPath = PathManager::getInstance().settingsFolderPath + "/settings.json";
|
QString settingsPath = PathManager::getInstance().settingsFolderPath + "/settings.json";
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ public:
|
||||||
messages::MessageElement::Flags getWordFlags();
|
messages::MessageElement::Flags getWordFlags();
|
||||||
bool isIgnoredEmote(const QString &emote);
|
bool isIgnoredEmote(const QString &emote);
|
||||||
|
|
||||||
void init();
|
void initialize();
|
||||||
|
|
||||||
/// Appearance
|
/// Appearance
|
||||||
BoolSetting showTimestamps = {"/appearance/messages/showTimestamps", true};
|
BoolSetting showTimestamps = {"/appearance/messages/showTimestamps", true};
|
||||||
|
|
|
@ -129,8 +129,8 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier)
|
||||||
this->messages.textColors.system = QColor(140, 127, 127);
|
this->messages.textColors.system = QColor(140, 127, 127);
|
||||||
|
|
||||||
this->messages.backgrounds.regular = splits.background;
|
this->messages.backgrounds.regular = splits.background;
|
||||||
this->messages.backgrounds.highlighted = blendColors(
|
this->messages.backgrounds.highlighted =
|
||||||
this->tabs.selected.backgrounds.regular.color(), this->messages.backgrounds.regular, 0.8);
|
blendColors(themeColor, this->messages.backgrounds.regular, 0.8);
|
||||||
// this->messages.backgrounds.resub
|
// this->messages.backgrounds.resub
|
||||||
// this->messages.backgrounds.whisper
|
// this->messages.backgrounds.whisper
|
||||||
this->messages.disabled = getColor(0, sat, 1, 0.6);
|
this->messages.disabled = getColor(0, sat, 1, 0.6);
|
||||||
|
|
|
@ -1,12 +1,19 @@
|
||||||
#include "windowmanager.hpp"
|
#include "windowmanager.hpp"
|
||||||
#include "debug/log.hpp"
|
#include "debug/log.hpp"
|
||||||
|
#include "providers/twitch/twitchserver.hpp"
|
||||||
#include "singletons/fontmanager.hpp"
|
#include "singletons/fontmanager.hpp"
|
||||||
|
#include "singletons/pathmanager.hpp"
|
||||||
#include "singletons/thememanager.hpp"
|
#include "singletons/thememanager.hpp"
|
||||||
#include "widgets/accountswitchpopupwidget.hpp"
|
#include "widgets/accountswitchpopupwidget.hpp"
|
||||||
#include "widgets/settingsdialog.hpp"
|
#include "widgets/settingsdialog.hpp"
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
#define SETTINGS_FILENAME "/layout.json"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace singletons {
|
namespace singletons {
|
||||||
|
|
||||||
|
@ -51,11 +58,6 @@ WindowManager::WindowManager(ThemeManager &_themeManager)
|
||||||
_themeManager.repaintVisibleChatWidgets.connect([this] { this->repaintVisibleChatWidgets(); });
|
_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)
|
void WindowManager::layoutVisibleChatWidgets(Channel *channel)
|
||||||
{
|
{
|
||||||
this->layout.invoke(channel);
|
this->layout.invoke(channel);
|
||||||
|
@ -90,12 +92,12 @@ widgets::Window &WindowManager::getSelectedWindow()
|
||||||
return *this->selectedWindow;
|
return *this->selectedWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
widgets::Window &WindowManager::createWindow()
|
widgets::Window &WindowManager::createWindow(widgets::Window::WindowType type)
|
||||||
{
|
{
|
||||||
auto *window = new widgets::Window("external", this->themeManager, false);
|
auto *window = new widgets::Window(this->themeManager, type);
|
||||||
window->getNotebook().addNewPage();
|
|
||||||
|
|
||||||
this->windows.push_back(window);
|
this->windows.push_back(window);
|
||||||
|
window->show();
|
||||||
|
|
||||||
return *window;
|
return *window;
|
||||||
}
|
}
|
||||||
|
@ -115,14 +117,168 @@ widgets::Window *WindowManager::windowAt(int index)
|
||||||
return this->windows.at(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()
|
void WindowManager::save()
|
||||||
{
|
{
|
||||||
assert(this->mainWindow);
|
QJsonDocument document;
|
||||||
|
|
||||||
this->mainWindow->save();
|
|
||||||
|
|
||||||
|
// "serialize"
|
||||||
|
QJsonArray window_arr;
|
||||||
for (widgets::Window *window : this->windows) {
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ public:
|
||||||
void showSettingsDialog();
|
void showSettingsDialog();
|
||||||
void showAccountSelectPopup(QPoint point);
|
void showAccountSelectPopup(QPoint point);
|
||||||
|
|
||||||
void initMainWindow();
|
|
||||||
void layoutVisibleChatWidgets(Channel *channel = nullptr);
|
void layoutVisibleChatWidgets(Channel *channel = nullptr);
|
||||||
void repaintVisibleChatWidgets(Channel *channel = nullptr);
|
void repaintVisibleChatWidgets(Channel *channel = nullptr);
|
||||||
void repaintGifEmotes();
|
void repaintGifEmotes();
|
||||||
|
@ -25,12 +24,14 @@ public:
|
||||||
|
|
||||||
widgets::Window &getMainWindow();
|
widgets::Window &getMainWindow();
|
||||||
widgets::Window &getSelectedWindow();
|
widgets::Window &getSelectedWindow();
|
||||||
widgets::Window &createWindow();
|
widgets::Window &createWindow(widgets::Window::WindowType type);
|
||||||
|
|
||||||
int windowCount();
|
int windowCount();
|
||||||
widgets::Window *windowAt(int index);
|
widgets::Window *windowAt(int index);
|
||||||
|
|
||||||
void save();
|
void save();
|
||||||
|
void initialize();
|
||||||
|
void closeAll();
|
||||||
|
|
||||||
pajlada::Signals::NoArgSignal repaintGifs;
|
pajlada::Signals::NoArgSignal repaintGifs;
|
||||||
pajlada::Signals::Signal<Channel *> layout;
|
pajlada::Signals::Signal<Channel *> layout;
|
||||||
|
@ -38,6 +39,8 @@ public:
|
||||||
private:
|
private:
|
||||||
ThemeManager &themeManager;
|
ThemeManager &themeManager;
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
std::vector<widgets::Window *> windows;
|
std::vector<widgets::Window *> windows;
|
||||||
|
|
||||||
widgets::Window *mainWindow = nullptr;
|
widgets::Window *mainWindow = nullptr;
|
||||||
|
|
|
@ -69,7 +69,12 @@ void BaseWindow::init()
|
||||||
layout->addLayout(buttonLayout);
|
layout->addLayout(buttonLayout);
|
||||||
|
|
||||||
// title
|
// 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);
|
buttonLayout->addWidget(title);
|
||||||
this->titleLabel = title;
|
this->titleLabel = title;
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,7 @@ ChannelView::ChannelView(BaseWidget *parent)
|
||||||
QObject::connect(this->layoutCooldown, &QTimer::timeout, [this] {
|
QObject::connect(this->layoutCooldown, &QTimer::timeout, [this] {
|
||||||
if (this->layoutQueued) {
|
if (this->layoutQueued) {
|
||||||
this->layoutMessages();
|
this->layoutMessages();
|
||||||
|
this->layoutQueued = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -137,15 +138,15 @@ void ChannelView::themeRefreshEvent()
|
||||||
|
|
||||||
void ChannelView::queueUpdate()
|
void ChannelView::queueUpdate()
|
||||||
{
|
{
|
||||||
if (this->updateTimer.isActive()) {
|
// if (this->updateTimer.isActive()) {
|
||||||
this->updateQueued = true;
|
// this->updateQueued = true;
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// this->repaint();
|
// this->repaint();
|
||||||
this->update();
|
this->update();
|
||||||
|
|
||||||
this->updateTimer.start();
|
// this->updateTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelView::layoutMessages()
|
void ChannelView::layoutMessages()
|
||||||
|
|
|
@ -17,14 +17,10 @@
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
|
|
||||||
NotebookTab::NotebookTab(Notebook *_notebook, const std::string &_uuid)
|
NotebookTab::NotebookTab(Notebook *_notebook)
|
||||||
: BaseWidget(_notebook)
|
: BaseWidget(_notebook)
|
||||||
, uuid(_uuid)
|
|
||||||
, settingRoot(fS("/containers/{}/tab", this->uuid))
|
|
||||||
, positionChangedAnimation(this, "pos")
|
, positionChangedAnimation(this, "pos")
|
||||||
, notebook(_notebook)
|
, notebook(_notebook)
|
||||||
, title(fS("{}/title", this->settingRoot), "")
|
|
||||||
, useDefaultBehaviour(fS("{}/useDefaultBehaviour", this->settingRoot), true)
|
|
||||||
, menu(this)
|
, menu(this)
|
||||||
{
|
{
|
||||||
this->setAcceptDrops(true);
|
this->setAcceptDrops(true);
|
||||||
|
@ -40,7 +36,7 @@ NotebookTab::NotebookTab(Notebook *_notebook, const std::string &_uuid)
|
||||||
TextInputDialog d(this);
|
TextInputDialog d(this);
|
||||||
|
|
||||||
d.setWindowTitle("Change tab title (Leave empty for default behaviour)");
|
d.setWindowTitle("Change tab title (Leave empty for default behaviour)");
|
||||||
if (this->useDefaultBehaviour) {
|
if (this->useDefaultTitle) {
|
||||||
d.setText("");
|
d.setText("");
|
||||||
} else {
|
} else {
|
||||||
d.setText(this->getTitle());
|
d.setText(this->getTitle());
|
||||||
|
@ -49,10 +45,10 @@ NotebookTab::NotebookTab(Notebook *_notebook, const std::string &_uuid)
|
||||||
if (d.exec() == QDialog::Accepted) {
|
if (d.exec() == QDialog::Accepted) {
|
||||||
QString newTitle = d.getText();
|
QString newTitle = d.getText();
|
||||||
if (newTitle.isEmpty()) {
|
if (newTitle.isEmpty()) {
|
||||||
this->useDefaultBehaviour = true;
|
this->useDefaultTitle = true;
|
||||||
this->page->refreshTitle();
|
this->page->refreshTitle();
|
||||||
} else {
|
} else {
|
||||||
this->useDefaultBehaviour = false;
|
this->useDefaultTitle = false;
|
||||||
this->setTitle(newTitle);
|
this->setTitle(newTitle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,11 +78,10 @@ void NotebookTab::updateSize()
|
||||||
|
|
||||||
int width;
|
int width;
|
||||||
|
|
||||||
QString qTitle(qS(this->title));
|
|
||||||
if (singletons::SettingManager::getInstance().hideTabX) {
|
if (singletons::SettingManager::getInstance().hideTabX) {
|
||||||
width = (int)((fontMetrics().width(qTitle) + 16 /*+ 16*/) * scale);
|
width = (int)((fontMetrics().width(this->title) + 16 /*+ 16*/) * scale);
|
||||||
} else {
|
} 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));
|
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)
|
void NotebookTab::setTitle(const QString &newTitle)
|
||||||
{
|
{
|
||||||
auto stdTitle = newTitle.toStdString();
|
if (this->title != newTitle) {
|
||||||
|
this->title = newTitle;
|
||||||
if (this->title != stdTitle) {
|
|
||||||
this->title = stdTitle;
|
|
||||||
this->updateSize();
|
this->updateSize();
|
||||||
this->update();
|
this->update();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,17 +18,14 @@ class NotebookTab : public BaseWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
const std::string uuid;
|
|
||||||
const std::string settingRoot;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit NotebookTab(Notebook *_notebook, const std::string &_uuid);
|
explicit NotebookTab(Notebook *_notebook);
|
||||||
|
|
||||||
void updateSize();
|
void updateSize();
|
||||||
|
|
||||||
SplitContainer *page;
|
SplitContainer *page;
|
||||||
|
|
||||||
QString getTitle() const;
|
const QString &getTitle() const;
|
||||||
void setTitle(const QString &newTitle);
|
void setTitle(const QString &newTitle);
|
||||||
bool isSelected() const;
|
bool isSelected() const;
|
||||||
void setSelected(bool value);
|
void setSelected(bool value);
|
||||||
|
@ -63,10 +60,10 @@ private:
|
||||||
|
|
||||||
Notebook *notebook;
|
Notebook *notebook;
|
||||||
|
|
||||||
pajlada::Settings::Setting<std::string> title;
|
QString title;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
pajlada::Settings::Setting<bool> useDefaultBehaviour;
|
bool useDefaultTitle = true;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool selected = false;
|
bool selected = false;
|
||||||
|
|
|
@ -155,7 +155,7 @@ void SplitHeader::scaleChangedEvent(float scale)
|
||||||
|
|
||||||
void SplitHeader::updateChannelText()
|
void SplitHeader::updateChannelText()
|
||||||
{
|
{
|
||||||
const QString channelName = this->split->channelName;
|
const QString channelName = this->split->getChannel()->name;
|
||||||
if (channelName.isEmpty()) {
|
if (channelName.isEmpty()) {
|
||||||
this->titleLabel->setText("<no channel>");
|
this->titleLabel->setText("<no channel>");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -22,15 +22,13 @@
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
|
|
||||||
Notebook::Notebook(Window *parent, bool _showButtons, const std::string &settingPrefix)
|
Notebook::Notebook(Window *parent, bool _showButtons)
|
||||||
: BaseWidget(parent)
|
: BaseWidget(parent)
|
||||||
, settingRoot(fS("{}/notebook", settingPrefix))
|
|
||||||
, parentWindow(parent)
|
, parentWindow(parent)
|
||||||
, addButton(this)
|
, addButton(this)
|
||||||
, settingsButton(this)
|
, settingsButton(this)
|
||||||
, userButton(this)
|
, userButton(this)
|
||||||
, showButtons(_showButtons)
|
, showButtons(_showButtons)
|
||||||
, tabs(fS("{}/tabs", this->settingRoot))
|
|
||||||
, closeConfirmDialog(this)
|
, closeConfirmDialog(this)
|
||||||
{
|
{
|
||||||
this->connect(&this->settingsButton, SIGNAL(clicked()), this, SLOT(settingsButtonClicked()));
|
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.hidePreferencesButton.connectSimple([this](auto) { this->performLayout(); });
|
||||||
settingsManager.hideUserButton.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.setText("Are you sure you want to close this tab?");
|
||||||
closeConfirmDialog.setIcon(QMessageBox::Icon::Question);
|
closeConfirmDialog.setIcon(QMessageBox::Icon::Question);
|
||||||
closeConfirmDialog.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
|
closeConfirmDialog.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
|
||||||
|
@ -57,15 +53,10 @@ Notebook::Notebook(Window *parent, bool _showButtons, const std::string &setting
|
||||||
this->scaleChangedEvent(this->getScale());
|
this->scaleChangedEvent(this->getScale());
|
||||||
}
|
}
|
||||||
|
|
||||||
SplitContainer *Notebook::addNewPage()
|
SplitContainer *Notebook::addNewPage(bool select)
|
||||||
{
|
{
|
||||||
return this->addPage(CreateUUID().toStdString(), true);
|
auto tab = new NotebookTab(this);
|
||||||
}
|
auto page = new SplitContainer(this, tab);
|
||||||
|
|
||||||
SplitContainer *Notebook::addPage(const std::string &uuid, bool select)
|
|
||||||
{
|
|
||||||
auto tab = new NotebookTab(this, uuid);
|
|
||||||
auto page = new SplitContainer(this, tab, uuid);
|
|
||||||
|
|
||||||
tab->show();
|
tab->show();
|
||||||
|
|
||||||
|
@ -178,6 +169,11 @@ SplitContainer *Notebook::tabAt(QPoint point, int &index, int maxWidth)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SplitContainer *Notebook::tabAt(int index)
|
||||||
|
{
|
||||||
|
return this->pages[index];
|
||||||
|
}
|
||||||
|
|
||||||
void Notebook::rearrangePage(SplitContainer *page, int index)
|
void Notebook::rearrangePage(SplitContainer *page, int index)
|
||||||
{
|
{
|
||||||
this->pages.move(this->pages.indexOf(page), index);
|
this->pages.move(this->pages.indexOf(page), index);
|
||||||
|
@ -244,7 +240,7 @@ void Notebook::performLayout(bool animated)
|
||||||
for (auto &i : this->pages) {
|
for (auto &i : this->pages) {
|
||||||
if (!first &&
|
if (!first &&
|
||||||
(i == this->pages.last() ? tabHeight : 0) + x + i->getTab()->width() > width()) {
|
(i == this->pages.last() ? tabHeight : 0) + x + i->getTab()->width() > width()) {
|
||||||
y += i->getTab()->height() - 1;
|
y += i->getTab()->height();
|
||||||
// y += 20;
|
// y += 20;
|
||||||
i->getTab()->moveAnimated(QPoint(0, y), animated);
|
i->getTab()->moveAnimated(QPoint(0, y), animated);
|
||||||
x = i->getTab()->width();
|
x = i->getTab()->width();
|
||||||
|
@ -310,33 +306,7 @@ void Notebook::usersButtonClicked()
|
||||||
|
|
||||||
void Notebook::addPageButtonClicked()
|
void Notebook::addPageButtonClicked()
|
||||||
{
|
{
|
||||||
QTimer::singleShot(80, [this] { this->addNewPage(); });
|
QTimer::singleShot(80, [this] { this->addNewPage(true); });
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace widgets
|
} // namespace widgets
|
||||||
|
|
|
@ -18,23 +18,24 @@ class Notebook : public BaseWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
std::string settingRoot;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum HighlightType { none, highlighted, newMessage };
|
enum HighlightType { none, highlighted, newMessage };
|
||||||
|
|
||||||
explicit Notebook(Window *parent, bool _showButtons, const std::string &settingPrefix);
|
explicit Notebook(Window *parent, bool _showButtons);
|
||||||
|
|
||||||
SplitContainer *addNewPage();
|
SplitContainer *addNewPage(bool select = false);
|
||||||
SplitContainer *addPage(const std::string &uuid, bool select = false);
|
|
||||||
|
|
||||||
void removePage(SplitContainer *page);
|
void removePage(SplitContainer *page);
|
||||||
void removeCurrentPage();
|
void removeCurrentPage();
|
||||||
void select(SplitContainer *page);
|
void select(SplitContainer *page);
|
||||||
void selectIndex(int index);
|
void selectIndex(int index);
|
||||||
|
|
||||||
SplitContainer *getSelectedPage() const
|
SplitContainer *getOrAddSelectedPage()
|
||||||
{
|
{
|
||||||
|
if (selectedPage == nullptr) {
|
||||||
|
this->addNewPage(true);
|
||||||
|
}
|
||||||
|
|
||||||
return selectedPage;
|
return selectedPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +43,7 @@ public:
|
||||||
|
|
||||||
int tabCount();
|
int tabCount();
|
||||||
SplitContainer *tabAt(QPoint point, int &index, int maxWidth = 2000000000);
|
SplitContainer *tabAt(QPoint point, int &index, int maxWidth = 2000000000);
|
||||||
|
SplitContainer *tabAt(int index);
|
||||||
void rearrangePage(SplitContainer *page, int index);
|
void rearrangePage(SplitContainer *page, int index);
|
||||||
|
|
||||||
void nextTab();
|
void nextTab();
|
||||||
|
@ -71,14 +73,7 @@ private:
|
||||||
|
|
||||||
bool showButtons;
|
bool showButtons;
|
||||||
|
|
||||||
pajlada::Settings::Setting<std::vector<std::string>> tabs;
|
|
||||||
|
|
||||||
void loadTabs();
|
|
||||||
|
|
||||||
QMessageBox closeConfirmDialog;
|
QMessageBox closeConfirmDialog;
|
||||||
|
|
||||||
public:
|
|
||||||
void save();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace widgets
|
} // namespace widgets
|
||||||
|
|
|
@ -36,11 +36,8 @@ using namespace chatterino::messages;
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
|
|
||||||
Split::Split(SplitContainer *parent, const std::string &_uuid)
|
Split::Split(SplitContainer *parent)
|
||||||
: BaseWidget(parent)
|
: BaseWidget(parent)
|
||||||
, uuid(_uuid)
|
|
||||||
, settingRoot(fS("/splits/{}", this->uuid))
|
|
||||||
, channelName(fS("{}/channelName", this->settingRoot))
|
|
||||||
, parentPage(*parent)
|
, parentPage(*parent)
|
||||||
, channel(Channel::getEmpty())
|
, channel(Channel::getEmpty())
|
||||||
, vbox(this)
|
, 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+UP", &Split::doIncFlexY);
|
||||||
// CreateShortcut(this, "ALT+SHIFT+DOWN", &Split::doDecFlexY);
|
// 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->input.ui.textEdit->installEventFilter(parent);
|
||||||
|
|
||||||
this->view.mouseDown.connect([this](QMouseEvent *) { this->giveFocus(Qt::MouseFocusReason); });
|
this->view.mouseDown.connect([this](QMouseEvent *) { this->giveFocus(Qt::MouseFocusReason); });
|
||||||
|
@ -130,11 +122,6 @@ Split::~Split()
|
||||||
this->channelIDChangedConnection.disconnect();
|
this->channelIDChangedConnection.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &Split::getUUID() const
|
|
||||||
{
|
|
||||||
return this->uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChannelPtr Split::getChannel() const
|
ChannelPtr Split::getChannel() const
|
||||||
{
|
{
|
||||||
return this->channel;
|
return this->channel;
|
||||||
|
@ -156,6 +143,7 @@ void Split::setChannel(ChannelPtr _newChannel)
|
||||||
}
|
}
|
||||||
|
|
||||||
this->header.updateModerationModeIcon();
|
this->header.updateModerationModeIcon();
|
||||||
|
this->header.updateChannelText();
|
||||||
|
|
||||||
this->channelChanged.invoke();
|
this->channelChanged.invoke();
|
||||||
}
|
}
|
||||||
|
@ -196,19 +184,6 @@ bool Split::getModerationMode() const
|
||||||
return this->moderationMode;
|
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)
|
bool Split::showChangeChannelPopup(const char *dialogTitle, bool empty)
|
||||||
{
|
{
|
||||||
// create new input dialog and execute it
|
// create new input dialog and execute it
|
||||||
|
@ -217,13 +192,13 @@ bool Split::showChangeChannelPopup(const char *dialogTitle, bool empty)
|
||||||
dialog.setWindowTitle(dialogTitle);
|
dialog.setWindowTitle(dialogTitle);
|
||||||
|
|
||||||
if (!empty) {
|
if (!empty) {
|
||||||
dialog.setText(this->channelName);
|
dialog.setText(this->channel->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dialog.exec() == QDialog::Accepted) {
|
if (dialog.exec() == QDialog::Accepted) {
|
||||||
QString newChannelName = dialog.getText().trimmed();
|
QString newChannelName = dialog.getText().trimmed();
|
||||||
|
|
||||||
this->channelName = newChannelName;
|
this->setChannel(providers::twitch::TwitchServer::getInstance().addChannel(newChannelName));
|
||||||
this->parentPage.refreshTitle();
|
this->parentPage.refreshTitle();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -328,12 +303,13 @@ void Split::doChangeChannel()
|
||||||
|
|
||||||
void Split::doPopup()
|
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()),
|
Split *split =
|
||||||
this->uuid);
|
new Split(static_cast<SplitContainer *>(window.getNotebook().getOrAddSelectedPage()));
|
||||||
|
|
||||||
window.getNotebook().getSelectedPage()->addToLayout(split);
|
split->setChannel(this->getChannel());
|
||||||
|
window.getNotebook().getOrAddSelectedPage()->addToLayout(split);
|
||||||
|
|
||||||
window.show();
|
window.show();
|
||||||
}
|
}
|
||||||
|
@ -366,7 +342,7 @@ void Split::doOpenPopupPlayer()
|
||||||
void Split::doOpenStreamlink()
|
void Split::doOpenStreamlink()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
streamlink::Start(this->channelName.getValue());
|
streamlink::Start(this->channel->name);
|
||||||
} catch (const streamlink::Exception &ex) {
|
} catch (const streamlink::Exception &ex) {
|
||||||
debug::Log("Error in doOpenStreamlink: {}", ex.what());
|
debug::Log("Error in doOpenStreamlink: {}", ex.what());
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,14 +42,10 @@ class Split : public BaseWidget
|
||||||
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
const std::string uuid;
|
|
||||||
const std::string settingRoot;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Split(SplitContainer *parent, const std::string &_uuid);
|
Split(SplitContainer *parent);
|
||||||
~Split() override;
|
~Split() override;
|
||||||
|
|
||||||
pajlada::Settings::Setting<QString> channelName;
|
|
||||||
pajlada::Signals::NoArgSignal channelChanged;
|
pajlada::Signals::NoArgSignal channelChanged;
|
||||||
|
|
||||||
ChannelView &getChannelView()
|
ChannelView &getChannelView()
|
||||||
|
@ -57,8 +53,9 @@ public:
|
||||||
return this->view;
|
return this->view;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &getUUID() const;
|
|
||||||
ChannelPtr getChannel() const;
|
ChannelPtr getChannel() const;
|
||||||
|
void setChannel(ChannelPtr newChannel);
|
||||||
|
|
||||||
void setFlexSizeX(double x);
|
void setFlexSizeX(double x);
|
||||||
double getFlexSizeX();
|
double getFlexSizeX();
|
||||||
void setFlexSizeY(double y);
|
void setFlexSizeY(double y);
|
||||||
|
@ -98,8 +95,6 @@ private:
|
||||||
|
|
||||||
pajlada::Signals::Connection channelIDChangedConnection;
|
pajlada::Signals::Connection channelIDChangedConnection;
|
||||||
pajlada::Signals::Connection usermodeChangedConnection;
|
pajlada::Signals::Connection usermodeChangedConnection;
|
||||||
|
|
||||||
void setChannel(ChannelPtr newChannel);
|
|
||||||
void doOpenAccountPopupWidget(AccountPopupWidget *widget, QString user);
|
void doOpenAccountPopupWidget(AccountPopupWidget *widget, QString user);
|
||||||
void channelNameUpdated(const QString &newChannelName);
|
void channelNameUpdated(const QString &newChannelName);
|
||||||
void handleModifiers(QEvent *event, Qt::KeyboardModifiers modifiers);
|
void handleModifiers(QEvent *event, Qt::KeyboardModifiers modifiers);
|
||||||
|
|
|
@ -26,12 +26,9 @@ bool SplitContainer::isDraggingSplit = false;
|
||||||
Split *SplitContainer::draggingSplit = nullptr;
|
Split *SplitContainer::draggingSplit = nullptr;
|
||||||
std::pair<int, int> SplitContainer::dropPosition = std::pair<int, int>(-1, -1);
|
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)
|
: BaseWidget(parent->themeManager, parent)
|
||||||
, uuid(_uuid)
|
|
||||||
, settingRoot(fS("/containers/{}", this->uuid))
|
|
||||||
, tab(_tab)
|
, tab(_tab)
|
||||||
, chats(fS("{}/chats", this->settingRoot))
|
|
||||||
, dropPreview(this)
|
, dropPreview(this)
|
||||||
{
|
{
|
||||||
this->tab->page = 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.setSpacing(1);
|
||||||
this->ui.hbox.setMargin(0);
|
this->ui.hbox.setMargin(0);
|
||||||
|
|
||||||
this->loadSplits();
|
|
||||||
|
|
||||||
this->refreshTitle();
|
this->refreshTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +142,24 @@ const std::vector<Split *> &SplitContainer::getSplits() const
|
||||||
return this->splits;
|
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
|
NotebookTab *SplitContainer::getTab() const
|
||||||
{
|
{
|
||||||
return this->tab;
|
return this->tab;
|
||||||
|
@ -447,7 +460,7 @@ std::pair<int, int> SplitContainer::getChatPosition(const Split *chatWidget)
|
||||||
|
|
||||||
Split *SplitContainer::createChatWidget(const std::string &uuid)
|
Split *SplitContainer::createChatWidget(const std::string &uuid)
|
||||||
{
|
{
|
||||||
auto split = new Split(this, uuid);
|
auto split = new Split(this);
|
||||||
|
|
||||||
split->getChannelView().highlightedMessageReceived.connect([this] {
|
split->getChannelView().highlightedMessageReceived.connect([this] {
|
||||||
// fourtf: error potentionally here
|
// fourtf: error potentionally here
|
||||||
|
@ -459,7 +472,7 @@ Split *SplitContainer::createChatWidget(const std::string &uuid)
|
||||||
|
|
||||||
void SplitContainer::refreshTitle()
|
void SplitContainer::refreshTitle()
|
||||||
{
|
{
|
||||||
if (!this->tab->useDefaultBehaviour) {
|
if (!this->tab->useDefaultTitle) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,7 +480,7 @@ void SplitContainer::refreshTitle()
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
for (const auto &chatWidget : this->splits) {
|
for (const auto &chatWidget : this->splits) {
|
||||||
auto channelName = chatWidget->channelName.getValue();
|
auto channelName = chatWidget->getChannel()->name;
|
||||||
if (channelName.isEmpty()) {
|
if (channelName.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -487,83 +500,5 @@ void SplitContainer::refreshTitle()
|
||||||
this->tab->setTitle(newTitle);
|
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 widgets
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -19,21 +19,14 @@ class SplitContainer : public BaseWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
const std::string uuid;
|
|
||||||
const std::string settingRoot;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SplitContainer(Notebook *parent, NotebookTab *_tab, const std::string &_uuid);
|
SplitContainer(Notebook *parent, NotebookTab *_tab);
|
||||||
|
|
||||||
const std::string &getUUID() const
|
|
||||||
{
|
|
||||||
return this->uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<int, int> removeFromLayout(Split *widget);
|
std::pair<int, int> removeFromLayout(Split *widget);
|
||||||
void addToLayout(Split *widget, std::pair<int, int> position = std::pair<int, int>(-1, -1));
|
void addToLayout(Split *widget, std::pair<int, int> position = std::pair<int, int>(-1, -1));
|
||||||
|
|
||||||
const std::vector<Split *> &getSplits() const;
|
const std::vector<Split *> &getSplits() const;
|
||||||
|
std::vector<std::vector<Split *>> getColumns() const;
|
||||||
NotebookTab *getTab() const;
|
NotebookTab *getTab() const;
|
||||||
|
|
||||||
void addChat(bool openChannelNameDialog = false, std::string chatUUID = std::string());
|
void addChat(bool openChannelNameDialog = false, std::string chatUUID = std::string());
|
||||||
|
@ -90,8 +83,6 @@ private:
|
||||||
std::vector<Split *> splits;
|
std::vector<Split *> splits;
|
||||||
std::vector<DropRegion> dropRegions;
|
std::vector<DropRegion> dropRegions;
|
||||||
|
|
||||||
pajlada::Settings::Setting<std::vector<std::vector<std::string>>> chats;
|
|
||||||
|
|
||||||
NotebookPageDropPreview dropPreview;
|
NotebookPageDropPreview dropPreview;
|
||||||
|
|
||||||
void setPreviewRect(QPoint mousePos);
|
void setPreviewRect(QPoint mousePos);
|
||||||
|
|
|
@ -18,13 +18,11 @@
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
|
|
||||||
Window::Window(const QString &windowName, singletons::ThemeManager &_themeManager,
|
Window::Window(singletons::ThemeManager &_themeManager, WindowType _type)
|
||||||
bool _isMainWindow)
|
|
||||||
: BaseWindow(_themeManager, nullptr, true)
|
: BaseWindow(_themeManager, nullptr, true)
|
||||||
, settingRoot(fS("/windows/{}", windowName))
|
, type(_type)
|
||||||
, windowGeometry(this->settingRoot)
|
|
||||||
, dpi(this->getScale())
|
, dpi(this->getScale())
|
||||||
, notebook(this, _isMainWindow, this->settingRoot)
|
, notebook(this, !this->hasCustomWindowFrame())
|
||||||
{
|
{
|
||||||
singletons::AccountManager::getInstance().Twitch.currentUsername.connect(
|
singletons::AccountManager::getInstance().Twitch.currentUsername.connect(
|
||||||
[this](const std::string &newUsername, auto) {
|
[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, [] {
|
this->addTitleBarButton(TitleBarButton::Settings, [] {
|
||||||
singletons::WindowManager::getInstance().showSettingsDialog();
|
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);
|
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||||
|
|
||||||
layout->addWidget(&this->notebook);
|
layout->addWidget(&this->notebook);
|
||||||
|
@ -59,8 +63,6 @@ Window::Window(const QString &windowName, singletons::ThemeManager &_themeManage
|
||||||
|
|
||||||
this->themeRefreshEvent();
|
this->themeRefreshEvent();
|
||||||
|
|
||||||
this->loadGeometry();
|
|
||||||
|
|
||||||
/// Initialize program-wide hotkeys
|
/// Initialize program-wide hotkeys
|
||||||
// CTRL+P: Open Settings Dialog
|
// CTRL+P: Open Settings Dialog
|
||||||
CreateWindowShortcut(this, "CTRL+P", [] { SettingsDialog::showDialog(); });
|
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); });
|
CreateWindowShortcut(this, "CTRL+9", [this] { this->notebook.selectIndex(8); });
|
||||||
|
|
||||||
// CTRL+SHIFT+T: New tab
|
// 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
|
// CTRL+SHIFT+W: Close current tab
|
||||||
CreateWindowShortcut(this, "CTRL+SHIFT+W", [this] { this->notebook.removeCurrentPage(); });
|
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)
|
void Window::repaintVisibleChatWidgets(Channel *channel)
|
||||||
{
|
{
|
||||||
auto *page = this->notebook.getSelectedPage();
|
auto *page = this->notebook.getOrAddSelectedPage();
|
||||||
|
|
||||||
if (page == nullptr) {
|
if (page == nullptr) {
|
||||||
return;
|
return;
|
||||||
|
@ -127,18 +134,6 @@ void Window::refreshWindowTitle(const QString &username)
|
||||||
this->setWindowTitle(username + " - Chatterino for Twitch");
|
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)
|
bool Window::event(QEvent *e)
|
||||||
{
|
{
|
||||||
switch (e->type()) {
|
switch (e->type()) {
|
||||||
|
@ -146,7 +141,7 @@ bool Window::event(QEvent *e)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QEvent::WindowDeactivate: {
|
case QEvent::WindowDeactivate: {
|
||||||
auto page = this->notebook.getSelectedPage();
|
auto page = this->notebook.getOrAddSelectedPage();
|
||||||
|
|
||||||
if (page != nullptr) {
|
if (page != nullptr) {
|
||||||
std::vector<Split *> splits = page->getSplits();
|
std::vector<Split *> splits = page->getSplits();
|
||||||
|
@ -160,35 +155,14 @@ bool Window::event(QEvent *e)
|
||||||
return BaseWindow::event(e);
|
return BaseWindow::event(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::loadGeometry()
|
void Window::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
bool doSetGeometry = false;
|
if (this->type == Window::Main) {
|
||||||
QRect loadedGeometry;
|
singletons::WindowManager::getInstance().save();
|
||||||
if (!this->windowGeometry.x.isDefaultValue() && !this->windowGeometry.y.isDefaultValue()) {
|
singletons::WindowManager::getInstance().closeAll();
|
||||||
loadedGeometry.setX(this->windowGeometry.x);
|
|
||||||
loadedGeometry.setY(this->windowGeometry.y);
|
|
||||||
doSetGeometry = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->windowGeometry.width.isDefaultValue() &&
|
this->closed.invoke();
|
||||||
!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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace widgets
|
} // namespace widgets
|
||||||
|
|
|
@ -18,32 +18,14 @@ class ThemeManager;
|
||||||
|
|
||||||
namespace widgets {
|
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
|
class Window : public BaseWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
std::string settingRoot;
|
|
||||||
|
|
||||||
WindowGeometry windowGeometry;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Window(const QString &windowName, singletons::ThemeManager &_themeManager,
|
enum WindowType { Main, Popup };
|
||||||
bool isMainWindow);
|
|
||||||
|
explicit Window(singletons::ThemeManager &_themeManager, WindowType type);
|
||||||
|
|
||||||
void repaintVisibleChatWidgets(Channel *channel = nullptr);
|
void repaintVisibleChatWidgets(Channel *channel = nullptr);
|
||||||
|
|
||||||
|
@ -53,17 +35,19 @@ public:
|
||||||
|
|
||||||
pajlada::Signals::NoArgSignal closed;
|
pajlada::Signals::NoArgSignal closed;
|
||||||
|
|
||||||
|
WindowType getType();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
bool event(QEvent *event) override;
|
bool event(QEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
WindowType type;
|
||||||
float dpi;
|
float dpi;
|
||||||
|
|
||||||
void loadGeometry();
|
void loadGeometry();
|
||||||
|
|
||||||
Notebook notebook;
|
Notebook notebook;
|
||||||
// TitleBar titleBar;
|
|
||||||
|
|
||||||
friend class Notebook;
|
friend class Notebook;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue