2018-07-15 14:03:41 +02:00
|
|
|
#include "singletons/WindowManager.hpp"
|
2018-06-26 14:09:39 +02:00
|
|
|
|
|
|
|
#include "Application.hpp"
|
2018-06-26 17:20:03 +02:00
|
|
|
#include "debug/AssertInGuiThread.hpp"
|
2018-06-26 14:09:39 +02:00
|
|
|
#include "debug/Log.hpp"
|
|
|
|
#include "providers/twitch/TwitchServer.hpp"
|
2018-06-28 19:46:45 +02:00
|
|
|
#include "singletons/Fonts.hpp"
|
|
|
|
#include "singletons/Paths.hpp"
|
2018-06-28 20:03:04 +02:00
|
|
|
#include "singletons/Theme.hpp"
|
2018-06-26 14:09:39 +02:00
|
|
|
#include "util/Clamp.hpp"
|
|
|
|
#include "widgets/AccountSwitchPopupWidget.hpp"
|
2018-06-26 15:11:45 +02:00
|
|
|
#include "widgets/dialogs/SettingsDialog.hpp"
|
2017-01-15 16:38:30 +01:00
|
|
|
|
2018-07-15 14:03:41 +02:00
|
|
|
#include <QDebug>
|
2018-05-16 14:55:45 +02:00
|
|
|
#include <QJsonArray>
|
2018-04-06 23:31:34 +02:00
|
|
|
#include <QJsonDocument>
|
|
|
|
#include <QJsonObject>
|
|
|
|
|
2018-06-21 13:02:34 +02:00
|
|
|
#define SETTINGS_FILENAME "/window-layout.json"
|
2018-04-06 23:31:34 +02:00
|
|
|
|
2017-01-18 21:30:23 +01:00
|
|
|
namespace chatterino {
|
2018-01-05 02:56:18 +01:00
|
|
|
|
2018-06-26 17:06:17 +02:00
|
|
|
using SplitNode = SplitContainer::Node;
|
|
|
|
using SplitDirection = SplitContainer::Direction;
|
2018-05-16 14:55:45 +02:00
|
|
|
|
2018-06-11 19:11:33 +02:00
|
|
|
const int WindowManager::uiScaleMin = -5;
|
|
|
|
const int WindowManager::uiScaleMax = 10;
|
|
|
|
|
2018-01-24 15:08:22 +01:00
|
|
|
void WindowManager::showSettingsDialog()
|
|
|
|
{
|
2018-06-26 17:06:17 +02:00
|
|
|
QTimer::singleShot(80, [] { SettingsDialog::showDialog(); });
|
2018-01-24 15:08:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void WindowManager::showAccountSelectPopup(QPoint point)
|
|
|
|
{
|
|
|
|
// static QWidget *lastFocusedWidget = nullptr;
|
2018-06-26 17:06:17 +02:00
|
|
|
static AccountSwitchPopupWidget *w = new AccountSwitchPopupWidget();
|
2018-01-24 15:08:22 +01:00
|
|
|
|
|
|
|
if (w->hasFocus()) {
|
|
|
|
w->hide();
|
|
|
|
// if (lastFocusedWidget) {
|
|
|
|
// lastFocusedWidget->setFocus();
|
|
|
|
// }
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// lastFocusedWidget = this->focusWidget();
|
|
|
|
|
|
|
|
w->refresh();
|
|
|
|
|
|
|
|
QPoint buttonPos = point;
|
|
|
|
w->move(buttonPos.x(), buttonPos.y());
|
|
|
|
|
|
|
|
w->show();
|
|
|
|
w->setFocus();
|
|
|
|
}
|
|
|
|
|
2018-04-27 22:11:19 +02:00
|
|
|
WindowManager::WindowManager()
|
2017-04-13 19:25:33 +02:00
|
|
|
{
|
2018-04-26 18:10:26 +02:00
|
|
|
qDebug() << "init WindowManager";
|
2018-06-28 19:38:57 +02:00
|
|
|
|
|
|
|
auto settings = getSettings();
|
|
|
|
|
2018-07-06 19:23:47 +02:00
|
|
|
this->wordFlagsListener_.addSetting(settings->showTimestamps);
|
|
|
|
this->wordFlagsListener_.addSetting(settings->showBadges);
|
|
|
|
this->wordFlagsListener_.addSetting(settings->enableBttvEmotes);
|
|
|
|
this->wordFlagsListener_.addSetting(settings->enableEmojis);
|
|
|
|
this->wordFlagsListener_.addSetting(settings->enableFfzEmotes);
|
|
|
|
this->wordFlagsListener_.addSetting(settings->enableTwitchEmotes);
|
2018-07-12 18:56:54 +02:00
|
|
|
this->wordFlagsListener_.addSetting(settings->enableUsernameBold);
|
2018-08-06 16:40:12 +02:00
|
|
|
this->wordFlagsListener_.addSetting(settings->enableLowercaseLink);
|
2018-07-06 19:23:47 +02:00
|
|
|
this->wordFlagsListener_.cb = [this](auto) {
|
2018-06-28 19:38:57 +02:00
|
|
|
this->updateWordTypeMask(); //
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-08-07 07:55:31 +02:00
|
|
|
MessageElementFlags WindowManager::getWordFlags()
|
2018-06-28 19:38:57 +02:00
|
|
|
{
|
2018-07-06 19:23:47 +02:00
|
|
|
return this->wordFlags_;
|
2018-06-28 19:38:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void WindowManager::updateWordTypeMask()
|
|
|
|
{
|
2018-08-07 07:55:31 +02:00
|
|
|
using MEF = MessageElementFlag;
|
2018-06-28 19:38:57 +02:00
|
|
|
auto settings = getSettings();
|
|
|
|
|
|
|
|
// text
|
2018-08-07 07:55:31 +02:00
|
|
|
auto flags = MessageElementFlags(MEF::Text);
|
2018-06-28 19:38:57 +02:00
|
|
|
|
|
|
|
// timestamp
|
|
|
|
if (settings->showTimestamps) {
|
2018-08-07 07:55:31 +02:00
|
|
|
flags.set(MEF::Timestamp);
|
2018-06-28 19:38:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// emotes
|
2018-08-07 07:55:31 +02:00
|
|
|
flags.set(settings->enableTwitchEmotes ? MEF::TwitchEmoteImage
|
|
|
|
: MEF::TwitchEmoteText);
|
|
|
|
flags.set(settings->enableFfzEmotes ? MEF::FfzEmoteImage
|
|
|
|
: MEF::FfzEmoteText);
|
|
|
|
flags.set(settings->enableBttvEmotes ? MEF::BttvEmoteImage
|
|
|
|
: MEF::BttvEmoteText);
|
|
|
|
flags.set(settings->enableEmojis ? MEF::EmojiImage : MEF::EmojiText);
|
2018-06-28 19:38:57 +02:00
|
|
|
|
|
|
|
// bits
|
2018-08-07 07:55:31 +02:00
|
|
|
flags.set(MEF::BitsAmount);
|
|
|
|
flags.set(settings->enableGifAnimations ? MEF::BitsAnimated
|
|
|
|
: MEF::BitsStatic);
|
2018-06-28 19:38:57 +02:00
|
|
|
|
|
|
|
// badges
|
2018-08-07 07:55:31 +02:00
|
|
|
flags.set(settings->showBadges ? MEF::Badges : MEF::None);
|
2018-06-28 19:38:57 +02:00
|
|
|
|
|
|
|
// username
|
2018-08-07 07:55:31 +02:00
|
|
|
flags.set(MEF::Username);
|
2018-06-28 19:38:57 +02:00
|
|
|
|
|
|
|
// misc
|
2018-08-07 07:55:31 +02:00
|
|
|
flags.set(MEF::AlwaysShow);
|
|
|
|
flags.set(MEF::Collapsed);
|
|
|
|
flags.set(settings->enableUsernameBold ? MEF::BoldUsername
|
|
|
|
: MEF::NonBoldUsername);
|
|
|
|
flags.set(settings->enableLowercaseLink ? MEF::LowercaseLink
|
|
|
|
: MEF::OriginalLink);
|
2018-06-28 19:38:57 +02:00
|
|
|
|
|
|
|
// update flags
|
2018-08-07 07:55:31 +02:00
|
|
|
MessageElementFlags newFlags = static_cast<MessageElementFlags>(flags);
|
2018-06-28 19:38:57 +02:00
|
|
|
|
2018-07-06 19:23:47 +02:00
|
|
|
if (newFlags != this->wordFlags_) {
|
|
|
|
this->wordFlags_ = newFlags;
|
2018-06-28 19:38:57 +02:00
|
|
|
|
|
|
|
this->wordFlagsChanged.invoke();
|
|
|
|
}
|
2017-04-13 19:25:33 +02:00
|
|
|
}
|
2017-01-18 21:30:23 +01:00
|
|
|
|
2018-06-04 16:10:54 +02:00
|
|
|
void WindowManager::layoutChannelViews(Channel *channel)
|
2017-01-15 16:38:30 +01:00
|
|
|
{
|
2018-04-03 02:55:32 +02:00
|
|
|
this->layout.invoke(channel);
|
2017-01-16 03:15:07 +01:00
|
|
|
}
|
|
|
|
|
2018-06-04 16:10:54 +02:00
|
|
|
void WindowManager::forceLayoutChannelViews()
|
|
|
|
{
|
|
|
|
this->incGeneration();
|
|
|
|
this->layoutChannelViews(nullptr);
|
|
|
|
}
|
|
|
|
|
2017-04-12 17:46:44 +02:00
|
|
|
void WindowManager::repaintVisibleChatWidgets(Channel *channel)
|
2017-01-16 03:15:07 +01:00
|
|
|
{
|
2018-07-06 19:23:47 +02:00
|
|
|
if (this->mainWindow_ != nullptr) {
|
|
|
|
this->mainWindow_->repaintVisibleChatWidgets(channel);
|
2017-01-26 04:26:40 +01:00
|
|
|
}
|
2017-01-15 16:38:30 +01:00
|
|
|
}
|
2017-01-26 21:04:01 +01:00
|
|
|
|
2017-04-12 17:46:44 +02:00
|
|
|
void WindowManager::repaintGifEmotes()
|
2017-02-07 00:03:15 +01:00
|
|
|
{
|
2018-04-03 02:55:32 +02:00
|
|
|
this->repaintGifs.invoke();
|
2017-02-07 00:03:15 +01:00
|
|
|
}
|
|
|
|
|
2017-09-16 00:05:06 +02:00
|
|
|
// void WindowManager::updateAll()
|
|
|
|
//{
|
|
|
|
// if (this->mainWindow != nullptr) {
|
|
|
|
// this->mainWindow->update();
|
|
|
|
// }
|
|
|
|
//}
|
2017-02-02 01:23:26 +01:00
|
|
|
|
2018-06-26 17:06:17 +02:00
|
|
|
Window &WindowManager::getMainWindow()
|
2017-04-13 19:25:33 +02:00
|
|
|
{
|
2018-06-26 17:06:17 +02:00
|
|
|
assertInGuiThread();
|
2018-04-26 18:10:26 +02:00
|
|
|
|
2018-07-06 19:23:47 +02:00
|
|
|
return *this->mainWindow_;
|
2017-04-13 19:25:33 +02:00
|
|
|
}
|
|
|
|
|
2018-06-26 17:06:17 +02:00
|
|
|
Window &WindowManager::getSelectedWindow()
|
2017-11-12 17:21:50 +01:00
|
|
|
{
|
2018-06-26 17:06:17 +02:00
|
|
|
assertInGuiThread();
|
2018-04-26 18:10:26 +02:00
|
|
|
|
2018-07-06 19:23:47 +02:00
|
|
|
return *this->selectedWindow_;
|
2017-11-12 17:21:50 +01:00
|
|
|
}
|
|
|
|
|
2018-07-06 17:02:26 +02:00
|
|
|
Window &WindowManager::createWindow(Window::Type type)
|
2017-11-12 17:21:50 +01:00
|
|
|
{
|
2018-06-26 17:06:17 +02:00
|
|
|
assertInGuiThread();
|
2018-04-26 18:10:26 +02:00
|
|
|
|
2018-06-26 17:06:17 +02:00
|
|
|
auto *window = new Window(type);
|
2018-07-06 19:23:47 +02:00
|
|
|
this->windows_.push_back(window);
|
2018-04-06 23:31:34 +02:00
|
|
|
window->show();
|
2017-11-12 17:21:50 +01:00
|
|
|
|
2018-07-06 17:02:26 +02:00
|
|
|
if (type != Window::Type::Main) {
|
2018-04-08 14:13:48 +02:00
|
|
|
window->setAttribute(Qt::WA_DeleteOnClose);
|
|
|
|
|
|
|
|
QObject::connect(window, &QWidget::destroyed, [this, window] {
|
2018-08-06 21:17:03 +02:00
|
|
|
for (auto it = this->windows_.begin(); it != this->windows_.end();
|
|
|
|
it++) {
|
2018-04-08 14:13:48 +02:00
|
|
|
if (*it == window) {
|
2018-07-06 19:23:47 +02:00
|
|
|
this->windows_.erase(it);
|
2018-04-08 14:13:48 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-11-12 17:21:50 +01:00
|
|
|
return *window;
|
|
|
|
}
|
|
|
|
|
2017-12-14 00:25:06 +01:00
|
|
|
int WindowManager::windowCount()
|
|
|
|
{
|
2018-07-06 19:23:47 +02:00
|
|
|
return this->windows_.size();
|
2017-12-14 00:25:06 +01:00
|
|
|
}
|
|
|
|
|
2018-06-26 17:06:17 +02:00
|
|
|
Window *WindowManager::windowAt(int index)
|
2017-12-14 00:25:06 +01:00
|
|
|
{
|
2018-06-26 17:06:17 +02:00
|
|
|
assertInGuiThread();
|
2018-04-26 18:10:26 +02:00
|
|
|
|
2018-07-06 19:23:47 +02:00
|
|
|
if (index < 0 || (size_t)index >= this->windows_.size()) {
|
2017-12-14 00:25:06 +01:00
|
|
|
return nullptr;
|
|
|
|
}
|
2018-08-11 14:20:53 +02:00
|
|
|
log("getting window at bad index {}", index);
|
2017-12-14 00:25:06 +01:00
|
|
|
|
2018-07-06 19:23:47 +02:00
|
|
|
return this->windows_.at(index);
|
2017-12-14 00:25:06 +01:00
|
|
|
}
|
|
|
|
|
2018-08-02 14:23:27 +02:00
|
|
|
void WindowManager::initialize(Settings &settings, Paths &paths)
|
2017-01-26 21:04:01 +01:00
|
|
|
{
|
2018-06-26 17:06:17 +02:00
|
|
|
assertInGuiThread();
|
2018-04-26 18:10:26 +02:00
|
|
|
|
2018-08-02 14:23:27 +02:00
|
|
|
getApp()->themes->repaintVisibleChatWidgets_.connect(
|
|
|
|
[this] { this->repaintVisibleChatWidgets(); });
|
2018-04-27 22:11:19 +02:00
|
|
|
|
2018-07-06 19:23:47 +02:00
|
|
|
assert(!this->initialized_);
|
2018-04-06 23:31:34 +02:00
|
|
|
|
|
|
|
// load file
|
2018-07-07 11:41:01 +02:00
|
|
|
QString settingsPath = getPaths()->settingsDirectory + SETTINGS_FILENAME;
|
2018-04-06 23:31:34 +02:00
|
|
|
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();
|
2018-08-06 21:17:03 +02:00
|
|
|
Window::Type type =
|
|
|
|
type_val == "main" ? Window::Type::Main : Window::Type::Popup;
|
2018-04-06 23:31:34 +02:00
|
|
|
|
2018-07-06 19:23:47 +02:00
|
|
|
if (type == Window::Type::Main && mainWindow_ != nullptr) {
|
2018-07-06 17:02:26 +02:00
|
|
|
type = Window::Type::Popup;
|
2018-04-06 23:31:34 +02:00
|
|
|
}
|
|
|
|
|
2018-06-26 17:06:17 +02:00
|
|
|
Window &window = createWindow(type);
|
2018-04-06 23:31:34 +02:00
|
|
|
|
2018-07-06 17:02:26 +02:00
|
|
|
if (type == Window::Type::Main) {
|
2018-07-06 19:23:47 +02:00
|
|
|
mainWindow_ = &window;
|
2018-04-06 23:31:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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) {
|
2018-06-26 17:06:17 +02:00
|
|
|
SplitContainer *page = window.getNotebook().addPage(false);
|
2018-04-06 23:31:34 +02:00
|
|
|
|
|
|
|
QJsonObject tab_obj = tab_val.toObject();
|
|
|
|
|
|
|
|
// set custom title
|
|
|
|
QJsonValue title_val = tab_obj.value("title");
|
|
|
|
if (title_val.isString()) {
|
2018-06-01 16:01:49 +02:00
|
|
|
page->getTab()->setCustomTitle(title_val.toString());
|
2018-04-06 23:31:34 +02:00
|
|
|
}
|
|
|
|
|
2018-04-10 15:59:53 +02:00
|
|
|
// selected
|
|
|
|
if (tab_obj.value("selected").toBool(false)) {
|
2018-05-23 04:22:17 +02:00
|
|
|
window.getNotebook().select(page);
|
2018-04-10 15:59:53 +02:00
|
|
|
}
|
|
|
|
|
2018-04-06 23:31:34 +02:00
|
|
|
// load splits
|
2018-05-16 14:55:45 +02:00
|
|
|
QJsonObject splitRoot = tab_obj.value("splits2").toObject();
|
|
|
|
|
|
|
|
if (!splitRoot.isEmpty()) {
|
2018-05-23 04:22:17 +02:00
|
|
|
page->decodeFromJson(splitRoot);
|
2018-05-16 14:55:45 +02:00
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// fallback load splits (old)
|
2018-04-06 23:31:34 +02:00
|
|
|
int colNr = 0;
|
|
|
|
for (QJsonValue column_val : tab_obj.value("splits").toArray()) {
|
|
|
|
for (QJsonValue split_val : column_val.toArray()) {
|
2018-06-26 17:06:17 +02:00
|
|
|
Split *split = new Split(page);
|
2018-04-06 23:31:34 +02:00
|
|
|
|
|
|
|
QJsonObject split_obj = split_val.toObject();
|
2018-05-16 14:55:45 +02:00
|
|
|
split->setChannel(decodeChannel(split_obj));
|
2018-04-06 23:31:34 +02:00
|
|
|
|
2018-05-23 04:22:17 +02:00
|
|
|
page->appendSplit(split);
|
2018-04-06 23:31:34 +02:00
|
|
|
}
|
|
|
|
colNr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-06 19:23:47 +02:00
|
|
|
if (mainWindow_ == nullptr) {
|
|
|
|
mainWindow_ = &createWindow(Window::Type::Main);
|
|
|
|
mainWindow_->getNotebook().addPage(true);
|
2018-04-06 23:31:34 +02:00
|
|
|
}
|
|
|
|
|
2018-08-06 21:17:03 +02:00
|
|
|
settings.timestampFormat.connect(
|
|
|
|
[this](auto, auto) { this->layoutChannelViews(); });
|
2018-07-07 11:41:01 +02:00
|
|
|
|
2018-08-06 21:17:03 +02:00
|
|
|
settings.emoteScale.connect(
|
|
|
|
[this](auto, auto) { this->forceLayoutChannelViews(); });
|
2018-07-07 11:41:01 +02:00
|
|
|
|
2018-08-06 21:17:03 +02:00
|
|
|
settings.timestampFormat.connect(
|
|
|
|
[this](auto, auto) { this->forceLayoutChannelViews(); });
|
2018-08-02 14:23:27 +02:00
|
|
|
settings.alternateMessageBackground.connect(
|
2018-07-07 11:41:01 +02:00
|
|
|
[this](auto, auto) { this->forceLayoutChannelViews(); });
|
2018-08-06 21:17:03 +02:00
|
|
|
settings.separateMessages.connect(
|
|
|
|
[this](auto, auto) { this->forceLayoutChannelViews(); });
|
2018-08-02 14:23:27 +02:00
|
|
|
settings.collpseMessagesMinLines.connect(
|
2018-07-07 11:41:01 +02:00
|
|
|
[this](auto, auto) { this->forceLayoutChannelViews(); });
|
|
|
|
|
2018-07-06 19:23:47 +02:00
|
|
|
this->initialized_ = true;
|
2018-04-06 23:31:34 +02:00
|
|
|
}
|
2017-01-28 22:35:23 +01:00
|
|
|
|
2018-04-06 23:31:34 +02:00
|
|
|
void WindowManager::save()
|
|
|
|
{
|
2018-06-26 17:06:17 +02:00
|
|
|
assertInGuiThread();
|
2018-04-27 22:11:19 +02:00
|
|
|
auto app = getApp();
|
2018-04-26 18:10:26 +02:00
|
|
|
|
2018-04-06 23:31:34 +02:00
|
|
|
QJsonDocument document;
|
2017-01-28 22:35:23 +01:00
|
|
|
|
2018-04-06 23:31:34 +02:00
|
|
|
// "serialize"
|
|
|
|
QJsonArray window_arr;
|
2018-07-06 19:23:47 +02:00
|
|
|
for (Window *window : this->windows_) {
|
2018-04-06 23:31:34 +02:00
|
|
|
QJsonObject window_obj;
|
|
|
|
|
|
|
|
// window type
|
|
|
|
switch (window->getType()) {
|
2018-07-06 17:02:26 +02:00
|
|
|
case Window::Type::Main:
|
2018-04-06 23:31:34 +02:00
|
|
|
window_obj.insert("type", "main");
|
|
|
|
break;
|
2018-07-07 11:41:01 +02:00
|
|
|
|
2018-07-06 17:02:26 +02:00
|
|
|
case Window::Type::Popup:
|
2018-04-06 23:31:34 +02:00
|
|
|
window_obj.insert("type", "popup");
|
|
|
|
break;
|
2018-07-07 11:41:01 +02:00
|
|
|
|
|
|
|
case Window::Type::Attached:;
|
2018-04-06 23:31:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
2018-08-06 21:17:03 +02:00
|
|
|
for (int tab_i = 0; tab_i < window->getNotebook().getPageCount();
|
|
|
|
tab_i++) {
|
2018-04-06 23:31:34 +02:00
|
|
|
QJsonObject tab_obj;
|
2018-08-06 21:17:03 +02:00
|
|
|
SplitContainer *tab = dynamic_cast<SplitContainer *>(
|
|
|
|
window->getNotebook().getPageAt(tab_i));
|
2018-05-23 04:22:17 +02:00
|
|
|
assert(tab != nullptr);
|
2018-04-06 23:31:34 +02:00
|
|
|
|
|
|
|
// custom tab title
|
2018-06-01 16:01:49 +02:00
|
|
|
if (tab->getTab()->hasCustomTitle()) {
|
|
|
|
tab_obj.insert("title", tab->getTab()->getCustomTitle());
|
2018-04-06 23:31:34 +02:00
|
|
|
}
|
|
|
|
|
2018-04-10 15:59:53 +02:00
|
|
|
// selected
|
|
|
|
if (window->getNotebook().getSelectedPage() == tab) {
|
|
|
|
tab_obj.insert("selected", true);
|
|
|
|
}
|
|
|
|
|
2018-04-06 23:31:34 +02:00
|
|
|
// splits
|
2018-05-16 14:55:45 +02:00
|
|
|
QJsonObject splits;
|
2018-04-06 23:31:34 +02:00
|
|
|
|
2018-05-16 14:55:45 +02:00
|
|
|
this->encodeNodeRecusively(tab->getBaseNode(), splits);
|
2018-04-06 23:31:34 +02:00
|
|
|
|
2018-05-16 14:55:45 +02:00
|
|
|
tab_obj.insert("splits2", splits);
|
2018-04-06 23:31:34 +02:00
|
|
|
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
|
2018-06-21 13:02:34 +02:00
|
|
|
QString settingsPath = app->paths->settingsDirectory + SETTINGS_FILENAME;
|
2018-04-06 23:31:34 +02:00
|
|
|
QFile file(settingsPath);
|
|
|
|
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
2018-05-16 14:55:45 +02:00
|
|
|
|
|
|
|
QJsonDocument::JsonFormat format =
|
|
|
|
#ifdef _DEBUG
|
|
|
|
QJsonDocument::JsonFormat::Compact
|
|
|
|
#else
|
|
|
|
(QJsonDocument::JsonFormat)0
|
|
|
|
#endif
|
|
|
|
;
|
|
|
|
|
|
|
|
file.write(document.toJson(format));
|
2018-04-06 23:31:34 +02:00
|
|
|
file.flush();
|
|
|
|
}
|
|
|
|
|
2018-05-16 14:55:45 +02:00
|
|
|
void WindowManager::encodeNodeRecusively(SplitNode *node, QJsonObject &obj)
|
|
|
|
{
|
|
|
|
switch (node->getType()) {
|
|
|
|
case SplitNode::_Split: {
|
|
|
|
obj.insert("type", "split");
|
|
|
|
QJsonObject split;
|
|
|
|
encodeChannel(node->getSplit()->getIndirectChannel(), split);
|
|
|
|
obj.insert("data", split);
|
|
|
|
obj.insert("flexh", node->getHorizontalFlex());
|
|
|
|
obj.insert("flexv", node->getVerticalFlex());
|
|
|
|
} break;
|
|
|
|
case SplitNode::HorizontalContainer:
|
|
|
|
case SplitNode::VerticalContainer: {
|
2018-08-06 21:17:03 +02:00
|
|
|
obj.insert("type", node->getType() == SplitNode::HorizontalContainer
|
|
|
|
? "horizontal"
|
|
|
|
: "vertical");
|
2018-05-16 14:55:45 +02:00
|
|
|
|
|
|
|
QJsonArray items_arr;
|
|
|
|
for (const std::unique_ptr<SplitNode> &n : node->getChildren()) {
|
|
|
|
QJsonObject subObj;
|
|
|
|
this->encodeNodeRecusively(n.get(), subObj);
|
|
|
|
items_arr.append(subObj);
|
|
|
|
}
|
|
|
|
obj.insert("items", items_arr);
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-20 22:33:28 +02:00
|
|
|
void WindowManager::encodeChannel(IndirectChannel channel, QJsonObject &obj)
|
|
|
|
{
|
2018-06-26 17:06:17 +02:00
|
|
|
assertInGuiThread();
|
2018-04-26 18:10:26 +02:00
|
|
|
|
2018-04-20 22:33:28 +02:00
|
|
|
switch (channel.getType()) {
|
2018-07-06 17:30:12 +02:00
|
|
|
case Channel::Type::Twitch: {
|
2018-04-20 22:33:28 +02:00
|
|
|
obj.insert("type", "twitch");
|
2018-08-02 14:23:27 +02:00
|
|
|
obj.insert("name", channel.get()->getName());
|
2018-04-20 22:33:28 +02:00
|
|
|
} break;
|
2018-07-06 17:30:12 +02:00
|
|
|
case Channel::Type::TwitchMentions: {
|
2018-04-20 22:33:28 +02:00
|
|
|
obj.insert("type", "mentions");
|
|
|
|
} break;
|
2018-07-06 17:30:12 +02:00
|
|
|
case Channel::Type::TwitchWatching: {
|
2018-04-20 22:33:28 +02:00
|
|
|
obj.insert("type", "watching");
|
|
|
|
} break;
|
2018-07-06 17:30:12 +02:00
|
|
|
case Channel::Type::TwitchWhispers: {
|
2018-04-20 22:33:28 +02:00
|
|
|
obj.insert("type", "whispers");
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
IndirectChannel WindowManager::decodeChannel(const QJsonObject &obj)
|
|
|
|
{
|
2018-06-26 17:06:17 +02:00
|
|
|
assertInGuiThread();
|
2018-04-26 18:10:26 +02:00
|
|
|
|
2018-04-28 15:20:18 +02:00
|
|
|
auto app = getApp();
|
|
|
|
|
2018-04-20 22:33:28 +02:00
|
|
|
QString type = obj.value("type").toString();
|
|
|
|
if (type == "twitch") {
|
2018-08-06 21:17:03 +02:00
|
|
|
return app->twitch.server->getOrAddChannel(
|
|
|
|
obj.value("name").toString());
|
2018-04-20 22:33:28 +02:00
|
|
|
} else if (type == "mentions") {
|
2018-04-28 15:20:18 +02:00
|
|
|
return app->twitch.server->mentionsChannel;
|
2018-04-20 22:33:28 +02:00
|
|
|
} else if (type == "watching") {
|
2018-04-28 15:20:18 +02:00
|
|
|
return app->twitch.server->watchingChannel;
|
2018-04-20 22:33:28 +02:00
|
|
|
} else if (type == "whispers") {
|
2018-04-28 15:20:18 +02:00
|
|
|
return app->twitch.server->whispersChannel;
|
2018-04-20 22:33:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return Channel::getEmpty();
|
|
|
|
}
|
|
|
|
|
2018-04-06 23:31:34 +02:00
|
|
|
void WindowManager::closeAll()
|
|
|
|
{
|
2018-06-26 17:06:17 +02:00
|
|
|
assertInGuiThread();
|
2018-04-26 18:10:26 +02:00
|
|
|
|
2018-07-06 19:23:47 +02:00
|
|
|
for (Window *window : windows_) {
|
2018-04-06 23:31:34 +02:00
|
|
|
window->close();
|
2017-01-28 22:35:23 +01:00
|
|
|
}
|
2017-01-26 21:04:01 +01:00
|
|
|
}
|
2017-01-28 22:35:23 +01:00
|
|
|
|
2018-06-04 16:10:54 +02:00
|
|
|
int WindowManager::getGeneration() const
|
|
|
|
{
|
2018-07-06 19:23:47 +02:00
|
|
|
return this->generation_;
|
2018-06-04 16:10:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void WindowManager::incGeneration()
|
|
|
|
{
|
2018-07-06 19:23:47 +02:00
|
|
|
this->generation_++;
|
2018-06-04 16:10:54 +02:00
|
|
|
}
|
|
|
|
|
2018-06-11 15:04:54 +02:00
|
|
|
int WindowManager::clampUiScale(int scale)
|
|
|
|
{
|
2018-06-26 17:06:17 +02:00
|
|
|
return clamp(scale, uiScaleMin, uiScaleMax);
|
2018-06-11 15:04:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
float WindowManager::getUiScaleValue()
|
|
|
|
{
|
|
|
|
return getUiScaleValue(getApp()->settings->uiScale.getValue());
|
|
|
|
}
|
|
|
|
|
|
|
|
float WindowManager::getUiScaleValue(int scale)
|
|
|
|
{
|
|
|
|
switch (clampUiScale(scale)) {
|
|
|
|
case -5:
|
|
|
|
return 0.5f;
|
|
|
|
case -4:
|
|
|
|
return 0.6f;
|
|
|
|
case -3:
|
|
|
|
return 0.7f;
|
|
|
|
case -2:
|
|
|
|
return 0.8f;
|
|
|
|
case -1:
|
|
|
|
return 0.9f;
|
|
|
|
case 0:
|
|
|
|
return 1;
|
|
|
|
case 1:
|
|
|
|
return 1.2f;
|
|
|
|
case 2:
|
|
|
|
return 1.4f;
|
|
|
|
case 3:
|
|
|
|
return 1.6f;
|
|
|
|
case 4:
|
|
|
|
return 1.6f;
|
|
|
|
case 5:
|
|
|
|
return 2;
|
|
|
|
case 6:
|
|
|
|
return 2.33f;
|
|
|
|
case 7:
|
|
|
|
return 2.66f;
|
|
|
|
case 8:
|
|
|
|
return 3;
|
|
|
|
case 9:
|
|
|
|
return 3.5f;
|
|
|
|
case 10:
|
|
|
|
return 4;
|
2018-06-21 13:02:34 +02:00
|
|
|
default:
|
|
|
|
assert(false);
|
2018-06-11 15:04:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-14 17:52:22 +02:00
|
|
|
} // namespace chatterino
|