2023-03-10 18:43:31 +00:00
|
|
|
// Squawk messenger.
|
|
|
|
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#include "root.h"
|
|
|
|
#include <QDebug>
|
|
|
|
#include <QThread>
|
2023-03-11 16:46:23 +00:00
|
|
|
#include <QLibraryInfo>
|
|
|
|
#include <QStandardPaths>
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include <shared/pathcheck.h>
|
|
|
|
|
|
|
|
const std::vector<unsigned int> Root::appIconSizes({
|
|
|
|
16, 24, 32, 48, 64, 96, 128, 256, 512
|
|
|
|
});
|
2023-03-10 18:43:31 +00:00
|
|
|
|
|
|
|
Root::Root(int& argc, char *argv[]) :
|
2023-03-11 16:46:23 +00:00
|
|
|
QApplication(argc, argv),
|
|
|
|
signalCatcher(this),
|
|
|
|
defaultTranslator(),
|
|
|
|
currentTranslator(),
|
|
|
|
appIcon(),
|
|
|
|
settings(),
|
|
|
|
componentsInitialized(false),
|
|
|
|
global(nullptr),
|
|
|
|
coreThread(nullptr),
|
|
|
|
core(nullptr),
|
|
|
|
gui(nullptr)
|
|
|
|
{
|
|
|
|
setApplicationName("squawk");
|
|
|
|
setOrganizationName("macaw.me");
|
|
|
|
setApplicationDisplayName("Squawk");
|
|
|
|
setApplicationVersion("0.2.3");
|
|
|
|
setDesktopFileName("squawk");
|
|
|
|
|
|
|
|
initializeTranslation();
|
|
|
|
initializeAppIcon();
|
|
|
|
|
|
|
|
global = new Shared::Global(); //important to instantiate after initialization of translations;
|
|
|
|
}
|
|
|
|
|
|
|
|
Root::~Root() {
|
|
|
|
if (componentsInitialized) {
|
|
|
|
delete gui;
|
|
|
|
if (core != nullptr)
|
|
|
|
delete core;
|
|
|
|
delete coreThread;
|
|
|
|
}
|
|
|
|
delete global;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Root::initializeTranslation() {
|
|
|
|
defaultTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
|
|
|
installTranslator(&defaultTranslator);
|
|
|
|
|
|
|
|
QStringList shares = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation);
|
|
|
|
bool found = false;
|
|
|
|
for (QString share : shares) {
|
|
|
|
found = currentTranslator.load(QLocale(), QLatin1String("squawk"), ".", share + "/l10n");
|
|
|
|
if (found) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found) {
|
|
|
|
currentTranslator.load(QLocale(), QLatin1String("squawk"), ".", QCoreApplication::applicationDirPath());
|
|
|
|
}
|
|
|
|
|
|
|
|
installTranslator(¤tTranslator);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Root::initializeAppIcon() {
|
|
|
|
for (std::vector<unsigned int>::size_type i = 0; i < appIconSizes.size(); ++i)
|
|
|
|
appIcon.addFile(":images/logo.svg", QSize(appIconSizes[i], appIconSizes[i]));
|
|
|
|
|
|
|
|
Root::setWindowIcon(appIcon);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Root::initializeSettings() {
|
|
|
|
QVariant vs = settings.value("style");
|
|
|
|
if (vs.isValid()) {
|
|
|
|
QString style = vs.toString().toLower();
|
|
|
|
if (style != "system") {
|
|
|
|
Shared::Global::setStyle(style);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Shared::Global::supported("colorSchemeTools")) {
|
|
|
|
QVariant vt = settings.value("theme");
|
|
|
|
if (vt.isValid()) {
|
|
|
|
QString theme = vt.toString();
|
|
|
|
if (theme.toLower() != "system") {
|
|
|
|
Shared::Global::setTheme(theme);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QString path = Shared::downloadsPathCheck();
|
|
|
|
if (path.size() > 0) {
|
|
|
|
settings.setValue("downloadsPath", path);
|
|
|
|
} else {
|
|
|
|
qDebug() << "couldn't initialize directory for downloads, quitting";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Root::run() {
|
|
|
|
if (!componentsInitialized)
|
|
|
|
initializeComponents();
|
|
|
|
|
|
|
|
coreThread->start();
|
|
|
|
int result = exec();
|
|
|
|
qDebug("Event loop stopped");
|
|
|
|
|
|
|
|
if (result == 0) {
|
|
|
|
processEvents(); //I dont like all of this mess
|
|
|
|
if (coreThread->isRunning()) { //but it's the best solution for now
|
|
|
|
if (core != nullptr) { //Ideally, following line should never appear in the log
|
|
|
|
qDebug() << "Core is still seems to be running, killing manually";
|
|
|
|
core->deleteLater();
|
|
|
|
coreThread->quit();
|
|
|
|
processEvents();
|
|
|
|
core = nullptr;
|
|
|
|
}
|
|
|
|
coreThread->wait();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Root::initializeComponents() {
|
|
|
|
core = new Core::Squawk();
|
|
|
|
coreThread = new QThread();
|
|
|
|
core->moveToThread(coreThread);
|
|
|
|
gui = new Application(core);
|
|
|
|
|
|
|
|
QObject::connect(&signalCatcher, &SignalCatcher::interrupt, gui, &Application::quit);
|
|
|
|
|
|
|
|
QObject::connect(coreThread, &QThread::started, core, &Core::Squawk::start);
|
|
|
|
QObject::connect(gui, &Application::quitting, core, &Core::Squawk::stop);
|
|
|
|
|
|
|
|
QObject::connect(core, &Core::Squawk::quit, core, &Core::Squawk::deleteLater);
|
|
|
|
QObject::connect(core, &Core::Squawk::destroyed, this, &Root::onCoreDestroyed);
|
|
|
|
QObject::connect(core, &Core::Squawk::destroyed, coreThread, &QThread::quit, Qt::QueuedConnection);
|
|
|
|
QObject::connect(coreThread, &QThread::finished, this, &Root::quit, Qt::QueuedConnection);
|
|
|
|
|
|
|
|
componentsInitialized = true;
|
|
|
|
}
|
2023-03-10 18:43:31 +00:00
|
|
|
|
|
|
|
bool Root::notify(QObject* receiver, QEvent* e) {
|
|
|
|
try {
|
|
|
|
return QApplication::notify(receiver, e);
|
|
|
|
} catch(const std::runtime_error& e) {
|
2023-03-11 16:46:23 +00:00
|
|
|
qDebug() << "std::runtime_error in thread:" << QThread::currentThreadId();
|
|
|
|
qDebug() << "error message:" << e.what();
|
2023-03-10 18:43:31 +00:00
|
|
|
} catch(const std::exception& e) {
|
2023-03-11 16:46:23 +00:00
|
|
|
qDebug() << "std::exception in thread:" << QThread::currentThreadId();
|
|
|
|
qDebug() << "error message:" << e.what();
|
2023-03-10 18:43:31 +00:00
|
|
|
} catch(const int& e) {
|
2023-03-11 16:46:23 +00:00
|
|
|
qDebug() << "integer exception in thread:" << QThread::currentThreadId();
|
|
|
|
qDebug() << "thrown integer:" << std::to_string(e).c_str();
|
2023-03-10 18:43:31 +00:00
|
|
|
} catch(...) {
|
2023-03-11 16:46:23 +00:00
|
|
|
qDebug() << "unhandled exception thread:" << QThread::currentThreadId();
|
2023-03-10 18:43:31 +00:00
|
|
|
}
|
|
|
|
|
2023-03-11 16:46:23 +00:00
|
|
|
qDebug() << "Squawk is crashing...";
|
|
|
|
exit(1);
|
2023-03-10 18:43:31 +00:00
|
|
|
return false;
|
|
|
|
}
|
2023-03-11 16:46:23 +00:00
|
|
|
|
|
|
|
void Root::onCoreDestroyed() {
|
|
|
|
core = nullptr;
|
|
|
|
}
|