2018-08-02 14:23:27 +02:00
|
|
|
#include "RunGui.hpp"
|
|
|
|
|
|
|
|
#include <QApplication>
|
|
|
|
#include <QFile>
|
|
|
|
#include <QPalette>
|
|
|
|
#include <QStyleFactory>
|
2019-09-22 15:32:36 +02:00
|
|
|
#include <Qt>
|
2019-10-07 22:14:00 +02:00
|
|
|
#include <QtConcurrent>
|
2019-09-22 15:32:36 +02:00
|
|
|
#include <csignal>
|
2018-08-02 14:23:27 +02:00
|
|
|
|
|
|
|
#include "Application.hpp"
|
2020-09-26 16:03:51 +02:00
|
|
|
#include "common/Args.hpp"
|
2019-10-05 16:40:04 +02:00
|
|
|
#include "common/Modes.hpp"
|
2018-08-02 14:23:27 +02:00
|
|
|
#include "common/NetworkManager.hpp"
|
2020-11-21 16:20:10 +01:00
|
|
|
#include "common/QLogging.hpp"
|
2018-08-02 14:23:27 +02:00
|
|
|
#include "singletons/Paths.hpp"
|
2019-09-22 10:53:39 +02:00
|
|
|
#include "singletons/Resources.hpp"
|
2019-09-22 15:32:36 +02:00
|
|
|
#include "singletons/Settings.hpp"
|
2018-08-02 14:23:27 +02:00
|
|
|
#include "singletons/Updates.hpp"
|
2019-08-25 22:58:19 +02:00
|
|
|
#include "util/CombinePath.hpp"
|
2018-08-02 14:23:27 +02:00
|
|
|
#include "widgets/dialogs/LastRunCrashDialog.hpp"
|
|
|
|
|
2018-10-09 18:37:51 +02:00
|
|
|
#ifdef USEWINSDK
|
|
|
|
# include "util/WindowsHelper.hpp"
|
|
|
|
#endif
|
|
|
|
|
2018-08-02 14:23:27 +02:00
|
|
|
#ifdef C_USE_BREAKPAD
|
2018-08-15 22:46:20 +02:00
|
|
|
# include <QBreakpadHandler.h>
|
2018-08-02 14:23:27 +02:00
|
|
|
#endif
|
|
|
|
|
2021-10-02 12:58:28 +02:00
|
|
|
#ifdef Q_OS_MAC
|
|
|
|
# include "corefoundation/CFBundle.h"
|
|
|
|
#endif
|
|
|
|
|
2018-08-02 14:23:27 +02:00
|
|
|
namespace chatterino {
|
|
|
|
namespace {
|
2018-08-15 22:46:20 +02:00
|
|
|
void installCustomPalette()
|
|
|
|
{
|
|
|
|
// borrowed from
|
|
|
|
// https://stackoverflow.com/questions/15035767/is-the-qt-5-dark-fusion-theme-available-for-windows
|
|
|
|
auto dark = qApp->palette();
|
|
|
|
|
|
|
|
dark.setColor(QPalette::Window, QColor(22, 22, 22));
|
|
|
|
dark.setColor(QPalette::WindowText, Qt::white);
|
|
|
|
dark.setColor(QPalette::Text, Qt::white);
|
|
|
|
dark.setColor(QPalette::Disabled, QPalette::WindowText,
|
|
|
|
QColor(127, 127, 127));
|
|
|
|
dark.setColor(QPalette::Base, QColor("#333"));
|
|
|
|
dark.setColor(QPalette::AlternateBase, QColor("#444"));
|
|
|
|
dark.setColor(QPalette::ToolTipBase, Qt::white);
|
|
|
|
dark.setColor(QPalette::ToolTipText, Qt::white);
|
|
|
|
dark.setColor(QPalette::Disabled, QPalette::Text,
|
|
|
|
QColor(127, 127, 127));
|
|
|
|
dark.setColor(QPalette::Dark, QColor(35, 35, 35));
|
|
|
|
dark.setColor(QPalette::Shadow, QColor(20, 20, 20));
|
|
|
|
dark.setColor(QPalette::Button, QColor(70, 70, 70));
|
|
|
|
dark.setColor(QPalette::ButtonText, Qt::white);
|
|
|
|
dark.setColor(QPalette::Disabled, QPalette::ButtonText,
|
|
|
|
QColor(127, 127, 127));
|
|
|
|
dark.setColor(QPalette::BrightText, Qt::red);
|
|
|
|
dark.setColor(QPalette::Link, QColor(42, 130, 218));
|
|
|
|
dark.setColor(QPalette::Highlight, QColor(42, 130, 218));
|
|
|
|
dark.setColor(QPalette::Disabled, QPalette::Highlight,
|
|
|
|
QColor(80, 80, 80));
|
|
|
|
dark.setColor(QPalette::HighlightedText, Qt::white);
|
|
|
|
dark.setColor(QPalette::Disabled, QPalette::HighlightedText,
|
|
|
|
QColor(127, 127, 127));
|
|
|
|
|
|
|
|
qApp->setPalette(dark);
|
|
|
|
}
|
2018-08-02 14:23:27 +02:00
|
|
|
|
2018-08-15 22:46:20 +02:00
|
|
|
void initQt()
|
|
|
|
{
|
|
|
|
// set up the QApplication flags
|
|
|
|
QApplication::setAttribute(Qt::AA_Use96Dpi, true);
|
2018-08-02 14:23:27 +02:00
|
|
|
#ifdef Q_OS_WIN32
|
2018-08-15 22:46:20 +02:00
|
|
|
QApplication::setAttribute(Qt::AA_DisableHighDpiScaling, true);
|
2018-08-02 14:23:27 +02:00
|
|
|
#endif
|
|
|
|
|
2018-08-15 22:46:20 +02:00
|
|
|
QApplication::setStyle(QStyleFactory::create("Fusion"));
|
2018-08-02 14:23:27 +02:00
|
|
|
|
2022-01-30 16:08:02 +01:00
|
|
|
QApplication::setWindowIcon(QIcon(":/icon.ico"));
|
|
|
|
|
2018-08-15 22:46:20 +02:00
|
|
|
installCustomPalette();
|
|
|
|
}
|
2018-08-02 14:23:27 +02:00
|
|
|
|
2018-08-15 22:46:20 +02:00
|
|
|
void showLastCrashDialog()
|
|
|
|
{
|
2019-08-18 20:14:00 +02:00
|
|
|
//#ifndef C_DISABLE_CRASH_DIALOG
|
|
|
|
// LastRunCrashDialog dialog;
|
|
|
|
|
|
|
|
// switch (dialog.exec())
|
|
|
|
// {
|
|
|
|
// case QDialog::Accepted:
|
|
|
|
// {
|
|
|
|
// };
|
|
|
|
// break;
|
|
|
|
// default:
|
|
|
|
// {
|
|
|
|
// _exit(0);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//#endif
|
2018-08-15 22:46:20 +02:00
|
|
|
}
|
2018-08-02 14:23:27 +02:00
|
|
|
|
2018-08-15 22:46:20 +02:00
|
|
|
void createRunningFile(const QString &path)
|
|
|
|
{
|
|
|
|
QFile runningFile(path);
|
2018-08-02 14:23:27 +02:00
|
|
|
|
2018-08-15 22:46:20 +02:00
|
|
|
runningFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
|
|
|
runningFile.flush();
|
|
|
|
runningFile.close();
|
|
|
|
}
|
2018-08-02 14:23:27 +02:00
|
|
|
|
2018-08-15 22:46:20 +02:00
|
|
|
void removeRunningFile(const QString &path)
|
|
|
|
{
|
|
|
|
QFile::remove(path);
|
|
|
|
}
|
2019-09-22 15:32:36 +02:00
|
|
|
|
|
|
|
std::chrono::steady_clock::time_point signalsInitTime;
|
|
|
|
bool restartOnSignal = false;
|
|
|
|
|
|
|
|
[[noreturn]] void handleSignal(int signum)
|
|
|
|
{
|
|
|
|
using namespace std::chrono_literals;
|
|
|
|
|
2019-09-22 16:14:16 +02:00
|
|
|
if (restartOnSignal &&
|
|
|
|
std::chrono::steady_clock::now() - signalsInitTime > 30s)
|
|
|
|
{
|
|
|
|
QProcess proc;
|
2021-10-02 12:58:28 +02:00
|
|
|
|
|
|
|
#ifdef Q_OS_MAC
|
|
|
|
// On macOS, programs are bundled into ".app" Application bundles,
|
2021-10-17 15:06:58 +02:00
|
|
|
// when restarting Chatterino that bundle should be opened with the "open"
|
2021-10-02 12:58:28 +02:00
|
|
|
// terminal command instead of directly starting the underlying executable,
|
|
|
|
// as those are 2 different things for the OS and i.e. do not use
|
2021-10-17 15:06:58 +02:00
|
|
|
// the same dock icon (resulting in a second Chatterino icon on restarting)
|
2021-10-02 12:58:28 +02:00
|
|
|
CFURLRef appUrlRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
|
|
|
|
CFStringRef macPath =
|
|
|
|
CFURLCopyFileSystemPath(appUrlRef, kCFURLPOSIXPathStyle);
|
|
|
|
const char *pathPtr =
|
|
|
|
CFStringGetCStringPtr(macPath, CFStringGetSystemEncoding());
|
|
|
|
|
|
|
|
proc.setProgram("open");
|
2021-10-20 08:34:19 +02:00
|
|
|
proc.setArguments({pathPtr, "-n", "--args", "--crash-recovery"});
|
2021-10-02 12:58:28 +02:00
|
|
|
|
|
|
|
CFRelease(appUrlRef);
|
|
|
|
CFRelease(macPath);
|
|
|
|
#else
|
2019-09-22 16:14:16 +02:00
|
|
|
proc.setProgram(QApplication::applicationFilePath());
|
|
|
|
proc.setArguments({"--crash-recovery"});
|
2021-10-02 12:58:28 +02:00
|
|
|
#endif
|
|
|
|
|
2019-09-22 16:14:16 +02:00
|
|
|
proc.startDetached();
|
|
|
|
}
|
2019-09-22 15:32:36 +02:00
|
|
|
|
|
|
|
_exit(signum);
|
|
|
|
}
|
|
|
|
|
2021-10-17 15:06:58 +02:00
|
|
|
// We want to restart Chatterino when it crashes and the setting is set to
|
2019-09-22 15:32:36 +02:00
|
|
|
// true.
|
|
|
|
void initSignalHandler()
|
|
|
|
{
|
2021-05-20 14:21:41 +02:00
|
|
|
#ifdef NDEBUG
|
2019-09-22 15:32:36 +02:00
|
|
|
signalsInitTime = std::chrono::steady_clock::now();
|
|
|
|
|
|
|
|
signal(SIGSEGV, handleSignal);
|
2019-09-22 16:14:16 +02:00
|
|
|
#endif
|
2019-09-22 15:32:36 +02:00
|
|
|
}
|
2019-10-07 22:14:00 +02:00
|
|
|
|
|
|
|
// We delete cache files that haven't been modified in 14 days. This strategy may be
|
|
|
|
// improved in the future.
|
|
|
|
void clearCache(const QDir &dir)
|
|
|
|
{
|
2021-07-03 13:40:24 +02:00
|
|
|
int deletedCount = 0;
|
2019-10-07 22:14:00 +02:00
|
|
|
for (auto &&info : dir.entryInfoList(QDir::Files))
|
|
|
|
{
|
|
|
|
if (info.lastModified().addDays(14) < QDateTime::currentDateTime())
|
|
|
|
{
|
2021-07-03 13:40:24 +02:00
|
|
|
bool res = QFile(info.absoluteFilePath()).remove();
|
|
|
|
if (res)
|
|
|
|
++deletedCount;
|
2019-10-07 22:14:00 +02:00
|
|
|
}
|
|
|
|
}
|
2021-07-03 13:40:24 +02:00
|
|
|
qCDebug(chatterinoCache) << "Deleted" << deletedCount << "files";
|
2019-10-07 22:14:00 +02:00
|
|
|
}
|
2018-08-02 14:23:27 +02:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
void runGui(QApplication &a, Paths &paths, Settings &settings)
|
|
|
|
{
|
2018-08-07 08:12:44 +02:00
|
|
|
initQt();
|
2019-09-22 10:53:39 +02:00
|
|
|
initResources();
|
2019-09-22 15:32:36 +02:00
|
|
|
initSignalHandler();
|
|
|
|
|
2020-11-08 12:02:19 +01:00
|
|
|
settings.restartOnCrash.connect([](const bool &value) {
|
|
|
|
restartOnSignal = value;
|
|
|
|
});
|
2019-09-22 10:53:39 +02:00
|
|
|
|
2019-08-25 22:58:19 +02:00
|
|
|
auto thread = std::thread([dir = paths.miscDirectory] {
|
|
|
|
{
|
|
|
|
auto path = combinePath(dir, "Update.exe");
|
|
|
|
if (QFile::exists(path))
|
|
|
|
{
|
|
|
|
QFile::remove(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto path = combinePath(dir, "update.zip");
|
|
|
|
if (QFile::exists(path))
|
|
|
|
{
|
|
|
|
QFile::remove(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-10-07 22:14:00 +02:00
|
|
|
// Clear the cache 1 minute after start.
|
|
|
|
QTimer::singleShot(60 * 1000, [cachePath = paths.cacheDirectory()] {
|
2020-11-08 12:02:19 +01:00
|
|
|
QtConcurrent::run([cachePath]() {
|
|
|
|
clearCache(cachePath);
|
|
|
|
});
|
2019-10-07 22:14:00 +02:00
|
|
|
});
|
|
|
|
|
2018-08-02 14:23:27 +02:00
|
|
|
chatterino::NetworkManager::init();
|
2019-10-07 22:42:34 +02:00
|
|
|
chatterino::Updates::instance().checkForUpdates();
|
2018-08-02 14:23:27 +02:00
|
|
|
|
|
|
|
#ifdef C_USE_BREAKPAD
|
2018-08-12 12:56:28 +02:00
|
|
|
QBreakpadInstance.setDumpPath(getPaths()->settingsFolderPath + "/Crashes");
|
2018-08-02 14:23:27 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Running file
|
2018-08-06 21:17:03 +02:00
|
|
|
auto runningPath =
|
|
|
|
paths.miscDirectory + "/running_" + paths.applicationFilePathHash;
|
2018-08-02 14:23:27 +02:00
|
|
|
|
2018-10-21 13:43:02 +02:00
|
|
|
if (QFile::exists(runningPath))
|
|
|
|
{
|
2018-08-02 14:23:27 +02:00
|
|
|
showLastCrashDialog();
|
2018-10-21 13:43:02 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-08-02 14:23:27 +02:00
|
|
|
createRunningFile(runningPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
Application app(settings, paths);
|
|
|
|
app.initialize(settings, paths);
|
|
|
|
app.run(a);
|
|
|
|
app.save();
|
|
|
|
|
|
|
|
removeRunningFile(runningPath);
|
|
|
|
|
2020-09-26 16:03:51 +02:00
|
|
|
if (!getArgs().dontSaveSettings)
|
|
|
|
{
|
|
|
|
pajlada::Settings::SettingManager::gSave();
|
|
|
|
}
|
2018-08-02 14:23:27 +02:00
|
|
|
|
|
|
|
chatterino::NetworkManager::deinit();
|
|
|
|
|
2018-10-09 18:37:51 +02:00
|
|
|
#ifdef USEWINSDK
|
2018-10-21 13:43:02 +02:00
|
|
|
// flushing windows clipboard to keep copied messages
|
2018-10-09 18:37:51 +02:00
|
|
|
flushClipboard();
|
|
|
|
#endif
|
|
|
|
|
2018-08-02 14:23:27 +02:00
|
|
|
_exit(0);
|
|
|
|
}
|
|
|
|
} // namespace chatterino
|