diff --git a/src/common.hpp b/src/common.hpp index bba4fa463..c1762d7da 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -3,6 +3,7 @@ #include "debug/log.hpp" #include +#include #include #include @@ -20,4 +21,8 @@ inline QString qS(const std::string &string) return QString::fromStdString(string); } +const Qt::KeyboardModifiers showSplitOverlayModifiers = Qt::ControlModifier | Qt::AltModifier; +const Qt::KeyboardModifiers showAddSplitRegions = Qt::ControlModifier | Qt::AltModifier; +const Qt::KeyboardModifiers showResizeHandlesModifiers = Qt::ControlModifier; + } // namespace chatterino diff --git a/src/main.cpp b/src/main.cpp index 6a8e85f5d..c7249734e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include "application.hpp" #include "singletons/nativemessagingmanager.hpp" #include "singletons/pathmanager.hpp" +#include "singletons/updatemanager.hpp" #include "util/networkmanager.hpp" #include "widgets/lastruncrashdialog.hpp" @@ -26,6 +27,7 @@ int runGui(int argc, char *argv[]); void runNativeMessagingHost(); +void installCustomPalette(); int main(int argc, char *argv[]) { @@ -57,41 +59,14 @@ int runGui(int argc, char *argv[]) QApplication::setStyle(QStyleFactory::create("Fusion")); - // borrowed from - // https://stackoverflow.com/questions/15035767/is-the-qt-5-dark-fusion-theme-available-for-windows - QPalette darkPalette = a.palette(); - - darkPalette.setColor(QPalette::Window, QColor(22, 22, 22)); - darkPalette.setColor(QPalette::WindowText, Qt::white); - darkPalette.setColor(QPalette::Text, Qt::white); - darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(127, 127, 127)); - darkPalette.setColor(QPalette::Base, QColor("#333")); - darkPalette.setColor(QPalette::AlternateBase, QColor("#444")); - darkPalette.setColor(QPalette::ToolTipBase, Qt::white); - darkPalette.setColor(QPalette::ToolTipText, Qt::white); - darkPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127)); - darkPalette.setColor(QPalette::Dark, QColor(35, 35, 35)); - darkPalette.setColor(QPalette::Shadow, QColor(20, 20, 20)); - darkPalette.setColor(QPalette::Button, QColor(70, 70, 70)); - darkPalette.setColor(QPalette::ButtonText, Qt::white); - darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127)); - darkPalette.setColor(QPalette::BrightText, Qt::red); - darkPalette.setColor(QPalette::Link, QColor(42, 130, 218)); - darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218)); - darkPalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(80, 80, 80)); - darkPalette.setColor(QPalette::HighlightedText, Qt::white); - darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(127, 127, 127)); - - qApp->setPalette(darkPalette); - - // Install native event handler for hidpi on windows - //#ifdef USEWINSDK - // a.installNativeEventFilter(new chatterino::util::DpiNativeEventFilter); - //#endif + installCustomPalette(); // Initialize NetworkManager chatterino::util::NetworkManager::init(); + // Check for upates + chatterino::singletons::UpdateManager::getInstance().checkForUpdates(); + // Initialize application chatterino::Application::instantiate(argc, argv); auto app = chatterino::getApp(); @@ -105,7 +80,14 @@ int runGui(int argc, char *argv[]) if (QFile::exists(runningPath)) { #ifndef DISABLE_CRASH_DIALOG chatterino::widgets::LastRunCrashDialog dialog; - dialog.exec(); + + switch (dialog.exec()) { + case QDialog::Accepted: { + }; break; + default: { + _exit(0); + } + } #endif } else { QFile runningFile(runningPath); @@ -188,3 +170,33 @@ void runNativeMessagingHost() nm->sendToGuiProcess(QByteArray::fromRawData(b.get(), static_cast(size))); } } + +void installCustomPalette() +{ + // borrowed from + // https://stackoverflow.com/questions/15035767/is-the-qt-5-dark-fusion-theme-available-for-windows + QPalette darkPalette = qApp->palette(); + + darkPalette.setColor(QPalette::Window, QColor(22, 22, 22)); + darkPalette.setColor(QPalette::WindowText, Qt::white); + darkPalette.setColor(QPalette::Text, Qt::white); + darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(127, 127, 127)); + darkPalette.setColor(QPalette::Base, QColor("#333")); + darkPalette.setColor(QPalette::AlternateBase, QColor("#444")); + darkPalette.setColor(QPalette::ToolTipBase, Qt::white); + darkPalette.setColor(QPalette::ToolTipText, Qt::white); + darkPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127)); + darkPalette.setColor(QPalette::Dark, QColor(35, 35, 35)); + darkPalette.setColor(QPalette::Shadow, QColor(20, 20, 20)); + darkPalette.setColor(QPalette::Button, QColor(70, 70, 70)); + darkPalette.setColor(QPalette::ButtonText, Qt::white); + darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127)); + darkPalette.setColor(QPalette::BrightText, Qt::red); + darkPalette.setColor(QPalette::Link, QColor(42, 130, 218)); + darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218)); + darkPalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(80, 80, 80)); + darkPalette.setColor(QPalette::HighlightedText, Qt::white); + darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(127, 127, 127)); + + qApp->setPalette(darkPalette); +} diff --git a/src/singletons/nativemessagingmanager.cpp b/src/singletons/nativemessagingmanager.cpp index f817a91a0..64578e75f 100644 --- a/src/singletons/nativemessagingmanager.cpp +++ b/src/singletons/nativemessagingmanager.cpp @@ -31,6 +31,7 @@ namespace ipc = boost::interprocess; namespace chatterino { namespace singletons { +// fourtf: don't add this class to the application class NativeMessagingManager::NativeMessagingManager() { qDebug() << "init NativeMessagingManager"; diff --git a/src/singletons/nativemessagingmanager.hpp b/src/singletons/nativemessagingmanager.hpp index b4d17ab2b..36e8a78ec 100644 --- a/src/singletons/nativemessagingmanager.hpp +++ b/src/singletons/nativemessagingmanager.hpp @@ -8,6 +8,7 @@ namespace singletons { class NativeMessagingManager { public: + // fourtf: don't add this class to the application class NativeMessagingManager(); ~NativeMessagingManager() = delete; diff --git a/src/singletons/thememanager.cpp b/src/singletons/thememanager.cpp index f4126bfd4..b61692e53 100644 --- a/src/singletons/thememanager.cpp +++ b/src/singletons/thememanager.cpp @@ -142,7 +142,12 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) this->splits.messageSeperator = isLight ? QColor(127, 127, 127) : QColor(60, 60, 60); this->splits.background = getColor(0, sat, 1); this->splits.dropPreview = QColor(0, 148, 255, 0x30); - this->splits.dropPreviewBorder = QColor(0, 148, 255, 0x70); + this->splits.dropPreviewBorder = QColor(0, 148, 255, 0xff); + this->splits.dropTargetRect = QColor(0, 148, 255, 0x00); + this->splits.dropTargetRectBorder = QColor(0, 148, 255, 0x00); + this->splits.resizeHandle = QColor(0, 148, 255, 0x70); + this->splits.resizeHandleBackground = QColor(0, 148, 255, 0x20); + // this->splits.border // this->splits.borderFocused @@ -191,9 +196,9 @@ void ThemeManager::actuallyUpdate(double hue, double multiplier) QColor ThemeManager::blendColors(const QColor &color1, const QColor &color2, qreal ratio) { - int r = color1.red() * (1 - ratio) + color2.red() * ratio; - int g = color1.green() * (1 - ratio) + color2.green() * ratio; - int b = color1.blue() * (1 - ratio) + color2.blue() * ratio; + int r = int(color1.red() * (1 - ratio) + color2.red() * ratio); + int g = int(color1.green() * (1 - ratio) + color2.green() * ratio); + int b = int(color1.blue() * (1 - ratio) + color2.blue() * ratio); return QColor(r, g, b, 255); } @@ -201,22 +206,22 @@ QColor ThemeManager::blendColors(const QColor &color1, const QColor &color2, qre void ThemeManager::normalizeColor(QColor &color) { if (this->isLight) { - if (color.lightnessF() > 0.5f) { - color.setHslF(color.hueF(), color.saturationF(), 0.5f); + if (color.lightnessF() > 0.5) { + color.setHslF(color.hueF(), color.saturationF(), 0.5); } - if (color.lightnessF() > 0.4f && color.hueF() > 0.1 && color.hueF() < 0.33333) { + if (color.lightnessF() > 0.4 && color.hueF() > 0.1 && color.hueF() < 0.33333) { color.setHslF( color.hueF(), color.saturationF(), color.lightnessF() - sin((color.hueF() - 0.1) / (0.3333 - 0.1) * 3.14159) * color.saturationF() * 0.2); } } else { - if (color.lightnessF() < 0.5f) { - color.setHslF(color.hueF(), color.saturationF(), 0.5f); + if (color.lightnessF() < 0.5) { + color.setHslF(color.hueF(), color.saturationF(), 0.5); } - if (color.lightnessF() < 0.6f && color.hueF() > 0.54444 && color.hueF() < 0.83333) { + if (color.lightnessF() < 0.6 && color.hueF() > 0.54444 && color.hueF() < 0.83333) { color.setHslF( color.hueF(), color.saturationF(), color.lightnessF() + sin((color.hueF() - 0.54444) / (0.8333 - 0.54444) * 3.14159) * diff --git a/src/singletons/thememanager.hpp b/src/singletons/thememanager.hpp index b3cda6acd..04ebcbd4f 100644 --- a/src/singletons/thememanager.hpp +++ b/src/singletons/thememanager.hpp @@ -63,6 +63,10 @@ public: QColor borderFocused; QColor dropPreview; QColor dropPreviewBorder; + QColor dropTargetRect; + QColor dropTargetRectBorder; + QColor resizeHandle; + QColor resizeHandleBackground; struct { QColor border; diff --git a/src/singletons/updatemanager.cpp b/src/singletons/updatemanager.cpp index 73b99717e..ad270db7e 100644 --- a/src/singletons/updatemanager.cpp +++ b/src/singletons/updatemanager.cpp @@ -7,25 +7,31 @@ namespace chatterino { namespace singletons { UpdateManager::UpdateManager() - : currentVersion(CHATTERINO_VERSION) + : currentVersion_(CHATTERINO_VERSION) { qDebug() << "init UpdateManager"; } UpdateManager &UpdateManager::getInstance() { + // fourtf: don't add this class to the application class static UpdateManager instance; + return instance; } const QString &UpdateManager::getCurrentVersion() const { - return this->getCurrentVersion(); + return currentVersion_; } const QString &UpdateManager::getOnlineVersion() const { - return this->getOnlineVersion(); + return onlineVersion_; +} + +void UpdateManager::installUpdates() +{ } void UpdateManager::checkForUpdates() @@ -33,17 +39,38 @@ void UpdateManager::checkForUpdates() QString url = "https://notitia.chatterino.com/version/chatterino/" CHATTERINO_OS "/stable"; util::NetworkRequest req(url); - req.setTimeout(20000); + req.setTimeout(30000); req.getJSON([this](QJsonObject &object) { QJsonValue version_val = object.value("version"); if (!version_val.isString()) { + this->setStatus_(Error); qDebug() << "error updating"; return; } - this->onlineVersion = version_val.toString(); - this->onlineVersionUpdated.invoke(); + this->onlineVersion_ = version_val.toString(); + + if (this->currentVersion_ != this->onlineVersion_) { + this->setStatus_(UpdateAvailable); + } else { + this->setStatus_(NoUpdateAvailable); + } }); + this->setStatus_(Searching); + req.execute(); +} + +UpdateManager::UpdateStatus UpdateManager::getStatus() const +{ + return this->status_; +} + +void UpdateManager::setStatus_(UpdateStatus status) +{ + if (this->status_ != status) { + this->status_ = status; + this->statusUpdated.invoke(status); + } } } // namespace singletons diff --git a/src/singletons/updatemanager.hpp b/src/singletons/updatemanager.hpp index f0e6ff657..365bc21f9 100644 --- a/src/singletons/updatemanager.hpp +++ b/src/singletons/updatemanager.hpp @@ -11,17 +11,25 @@ class UpdateManager UpdateManager(); public: + enum UpdateStatus { None, Searching, UpdateAvailable, NoUpdateAvailable, Error }; + + // fourtf: don't add this class to the application class static UpdateManager &getInstance(); void checkForUpdates(); const QString &getCurrentVersion() const; const QString &getOnlineVersion() const; + void installUpdates(); + UpdateStatus getStatus() const; - pajlada::Signals::NoArgSignal onlineVersionUpdated; + pajlada::Signals::Signal statusUpdated; private: - QString currentVersion; - QString onlineVersion; + QString currentVersion_; + QString onlineVersion_; + UpdateStatus status_ = None; + + void setStatus_(UpdateStatus status); }; } // namespace singletons diff --git a/src/util/networkrequest.hpp b/src/util/networkrequest.hpp index d0c6fef52..44ea93b34 100644 --- a/src/util/networkrequest.hpp +++ b/src/util/networkrequest.hpp @@ -277,6 +277,7 @@ public: void getJSON(FinishedCallback onFinished) { this->get([onFinished{std::move(onFinished)}](const QByteArray &bytes)->bool { + auto object = parseJSONFromData(bytes); onFinished(object); diff --git a/src/widgets/helper/splitoverlay.cpp b/src/widgets/helper/splitoverlay.cpp index 567c9dcb3..e59cc71d4 100644 --- a/src/widgets/helper/splitoverlay.cpp +++ b/src/widgets/helper/splitoverlay.cpp @@ -113,6 +113,9 @@ void SplitOverlay::paintEvent(QPaintEvent *) default:; } + rect.setRight(rect.right() - 1); + rect.setBottom(rect.bottom() - 1); + if (!rect.isNull()) { painter.setPen(getApp()->themes->splits.dropPreviewBorder); painter.setBrush(getApp()->themes->splits.dropPreview); diff --git a/src/widgets/lastruncrashdialog.cpp b/src/widgets/lastruncrashdialog.cpp index 8568e34e1..06f43acc3 100644 --- a/src/widgets/lastruncrashdialog.cpp +++ b/src/widgets/lastruncrashdialog.cpp @@ -1,17 +1,75 @@ #include "lastruncrashdialog.hpp" +#include +#include +#include #include +#include "singletons/updatemanager.hpp" +#include "util/layoutcreator.hpp" +#include "util/posttothread.hpp" + namespace chatterino { namespace widgets { LastRunCrashDialog::LastRunCrashDialog() { - QVBoxLayout *layout = new QVBoxLayout(this); - layout->addWidget( - new QLabel("The application wasn't terminated properly last time it was executed.")); + this->setWindowFlag(Qt::WindowContextHelpButtonHint, false); + this->setWindowTitle("Chatterino"); - this->setLayout(layout); + auto &updateManager = singletons::UpdateManager::getInstance(); + + auto layout = util::LayoutCreator(this).setLayoutType(); + + layout.emplace( + "The application wasn't terminated properly the last time it was executed."); + + layout->addSpacing(16); + + auto update = layout.emplace(); + auto buttons = layout.emplace(); + + auto *installUpdateButton = buttons->addButton("Install Update", QDialogButtonBox::NoRole); + installUpdateButton->setEnabled(false); + QObject::connect(installUpdateButton, &QPushButton::clicked, [this, update]() mutable { + auto &updateManager = singletons::UpdateManager::getInstance(); + + updateManager.installUpdates(); + this->setEnabled(false); + update->setText("Downloading updates..."); + }); + + auto *okButton = buttons->addButton("Ignore", QDialogButtonBox::ButtonRole::NoRole); + QObject::connect(okButton, &QPushButton::clicked, [this] { this->accept(); }); + + // Updates + auto updateUpdateLabel = [update]() mutable { + auto &updateManager = singletons::UpdateManager::getInstance(); + + switch (updateManager.getStatus()) { + case singletons::UpdateManager::None: { + update->setText("Not checking for updates."); + } break; + case singletons::UpdateManager::Searching: { + update->setText("Checking for updates..."); + } break; + case singletons::UpdateManager::UpdateAvailable: { + update->setText("Update available."); + } break; + case singletons::UpdateManager::NoUpdateAvailable: { + update->setText("No update abailable."); + } break; + case singletons::UpdateManager::Error: { + update->setText("Error while searching for update.\nEither the update service is " + "temporarily down or there is an issue with your installation."); + } break; + } + }; + + updateUpdateLabel(); + this->managedConnect(updateManager.statusUpdated, [updateUpdateLabel](auto) mutable { + util::postToThread([updateUpdateLabel]() mutable { updateUpdateLabel(); }); + }); } } // namespace widgets diff --git a/src/widgets/lastruncrashdialog.hpp b/src/widgets/lastruncrashdialog.hpp index 03b07ca18..23bcd2e36 100644 --- a/src/widgets/lastruncrashdialog.hpp +++ b/src/widgets/lastruncrashdialog.hpp @@ -1,11 +1,12 @@ #pragma once #include +#include namespace chatterino { namespace widgets { -class LastRunCrashDialog : public QDialog +class LastRunCrashDialog : public QDialog, pajlada::Signals::SignalHolder { public: LastRunCrashDialog(); diff --git a/src/widgets/split.cpp b/src/widgets/split.cpp index 096203a5c..a7578d77c 100644 --- a/src/widgets/split.cpp +++ b/src/widgets/split.cpp @@ -1,6 +1,7 @@ #include "widgets/split.hpp" #include "application.hpp" +#include "common.hpp" #include "providers/twitch/emotevalue.hpp" #include "providers/twitch/twitchchannel.hpp" #include "providers/twitch/twitchmessagebuilder.hpp" @@ -129,7 +130,7 @@ Split::Split(QWidget *parent) this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); this->managedConnect(modifierStatusChanged, [this](Qt::KeyboardModifiers status) { - if ((status == Qt::AltModifier || status == (Qt::AltModifier | Qt::ControlModifier)) && + if ((status == showSplitOverlayModifiers /*|| status == showAddSplitRegions*/) && this->isMouseOver) { this->overlay->show(); } else { @@ -307,8 +308,7 @@ void Split::enterEvent(QEvent *event) this->handleModifiers(QGuiApplication::queryKeyboardModifiers()); - if (modifierStatus == Qt::AltModifier || - modifierStatus == (Qt::AltModifier | Qt::ControlModifier)) { + if (modifierStatus == showSplitOverlayModifiers /*|| modifierStatus == showAddSplitRegions*/) { this->overlay->show(); } } diff --git a/src/widgets/splitcontainer.cpp b/src/widgets/splitcontainer.cpp index df46b361a..cccf8a490 100644 --- a/src/widgets/splitcontainer.cpp +++ b/src/widgets/splitcontainer.cpp @@ -42,7 +42,7 @@ SplitContainer::SplitContainer(Notebook *parent) this->managedConnect(Split::modifierStatusChanged, [this](auto modifiers) { this->layout(); - if (modifiers == Qt::AltModifier) { + if (modifiers == showResizeHandlesModifiers) { for (std::unique_ptr &handle : this->resizeHandles) { handle->show(); handle->raise(); @@ -52,6 +52,12 @@ SplitContainer::SplitContainer(Notebook *parent) handle->hide(); } } + + if (modifiers == showSplitOverlayModifiers) { + this->setCursor(Qt::PointingHandCursor); + } else { + this->unsetCursor(); + } }); this->setCursor(Qt::PointingHandCursor); @@ -296,9 +302,8 @@ void SplitContainer::layout() std::vector _dropRects; std::vector _resizeRects; - this->baseNode.layout( - Split::modifierStatus == (Qt::AltModifier | Qt::ControlModifier) || this->isDragging, - this->getScale(), _dropRects, _resizeRects); + this->baseNode.layout(Split::modifierStatus == showAddSplitRegions || this->isDragging, + this->getScale(), _dropRects, _resizeRects); this->dropRects = _dropRects; @@ -345,7 +350,7 @@ void SplitContainer::layout() handle->setVertical(resizeRect.vertical); handle->node = resizeRect.node; - if (Split::modifierStatus == Qt::AltModifier) { + if (Split::modifierStatus == showResizeHandlesModifiers) { handle->show(); handle->raise(); } @@ -371,6 +376,7 @@ void SplitContainer::mouseReleaseEvent(QMouseEvent *event) if (this->splits.size() == 0) { // "Add Chat" was clicked this->appendNewSplit(true); + this->mouseOverPoint = QPoint(-10000, -10000); // this->setCursor(QCursor(Qt::ArrowCursor)); } else { @@ -410,18 +416,31 @@ void SplitContainer::paintEvent(QPaintEvent *) } for (DropRect &dropRect : this->dropRects) { - QColor border = getApp()->themes->splits.dropPreviewBorder; - QColor background = getApp()->themes->splits.dropPreview; + QColor border = getApp()->themes->splits.dropTargetRectBorder; + QColor background = getApp()->themes->splits.dropTargetRect; if (!dropRect.rect.contains(this->mouseOverPoint)) { // border.setAlphaF(0.1); - background.setAlphaF(0.1); + // background.setAlphaF(0.1); + } else { + // background.setAlphaF(0.1); + border.setAlpha(255); } painter.setPen(border); painter.setBrush(background); - painter.drawRect(dropRect.rect.marginsRemoved(QMargins(2, 2, 2, 2))); + auto rect = dropRect.rect.marginsRemoved(QMargins(2, 2, 2, 2)); + + painter.drawRect(rect); + + int s = std::min(dropRect.rect.width(), dropRect.rect.height()) - 12; + + painter.setPen(QColor(255, 255, 255)); + painter.drawLine(rect.left() + rect.width() / 2 - (s / 2), rect.top() + rect.height() / 2, + rect.left() + rect.width() / 2 + (s / 2), rect.top() + rect.height() / 2); + painter.drawLine(rect.left() + rect.width() / 2, rect.top() + rect.height() / 2 - (s / 2), + rect.left() + rect.width() / 2, rect.top() + rect.height() / 2 + (s / 2)); } QBrush accentColor = (QApplication::activeWindow() == this->window() @@ -1045,9 +1064,9 @@ SplitContainer::ResizeHandle::ResizeHandle(SplitContainer *_parent) void SplitContainer::ResizeHandle::paintEvent(QPaintEvent *) { QPainter painter(this); - painter.setPen(QPen(getApp()->themes->splits.dropPreviewBorder, 2)); + painter.setPen(QPen(getApp()->themes->splits.resizeHandle, 2)); - painter.fillRect(this->rect(), getApp()->themes->splits.dropPreview); + painter.fillRect(this->rect(), getApp()->themes->splits.resizeHandleBackground); if (this->vertical) { painter.drawLine(0, this->height() / 2, this->width(), this->height() / 2); diff --git a/src/widgets/window.cpp b/src/widgets/window.cpp index c9a045882..bd83e5f78 100644 --- a/src/widgets/window.cpp +++ b/src/widgets/window.cpp @@ -6,6 +6,7 @@ #include "singletons/settingsmanager.hpp" #include "singletons/thememanager.hpp" #include "singletons/windowmanager.hpp" +#include "version.hpp" #include "widgets/accountswitchpopupwidget.hpp" #include "widgets/helper/shortcut.hpp" #include "widgets/notebook.hpp" @@ -118,7 +119,7 @@ Window::Window(WindowType _type) // ircManager.addFakeMessage(cheerMessages[index++ % cheerMessages.size()]); // }); - this->setWindowTitle("Chatterino 2 Development Build"); + this->refreshWindowTitle(""); this->notebook.setAllowUserTabManagement(true); this->notebook.setShowAddButton(true); @@ -151,7 +152,7 @@ SplitNotebook &Window::getNotebook() void Window::refreshWindowTitle(const QString &username) { - this->setWindowTitle(username + " - Chatterino for Twitch"); + this->setWindowTitle(username + " - Chatterino Beta " CHATTERINO_VERSION); } bool Window::event(QEvent *event)