/**
* Copyright (C) 2021 Saturneric
*
* This file is part of GpgFrontend.
*
* GpgFrontend 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.
*
* GpgFrontend 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 GpgFrontend. If not, see .
*
* The initial version of the source code is inherited from
* the gpg4usb project, which is under GPL-3.0-or-later.
*
* All the source code of GpgFrontend was modified and released by
* Saturneric starting on May 12, 2021.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
*/
#include "GpgFrontendUIInit.h"
#include
#include
#include
#include
#include "core/function/GlobalSettingStation.h"
#include "core/thread/CtxCheckTask.h"
#include "core/thread/TaskRunnerGetter.h"
#include "ui/SignalStation.h"
#include "ui/UserInterfaceUtils.h"
#include "ui/main_window/MainWindow.h"
#if !defined(RELEASE) && defined(WINDOWS)
#include "core/function/GlobalSettingStation.h"
#endif
namespace GpgFrontend::UI {
extern void init_logging_system();
extern void init_locale();
void InitGpgFrontendUI(QApplication* app) {
// init logging system
init_logging_system();
// init locale
init_locale();
#if !defined(RELEASE) && defined(WINDOWS)
// css
std::filesystem::path css_path =
GpgFrontend::GlobalSettingStation::GetInstance().GetResourceDir() /
"css" / "default.qss";
QFile file(css_path.u8string().c_str());
file.open(QFile::ReadOnly);
QString styleSheet = QLatin1String(file.readAll());
qApp->setStyleSheet(styleSheet);
file.close();
#endif
// init signal station
SignalStation::GetInstance();
// init common utils
CommonUtils::GetInstance();
// create the thread to load the gpg context
auto* init_ctx_task = new Thread::CtxCheckTask();
// create and show loading window before starting the main window
auto* waiting_dialog = new QProgressDialog();
waiting_dialog->setMaximum(0);
waiting_dialog->setMinimum(0);
auto waiting_dialog_label =
new QLabel(QString(_("Loading Gnupg Info...")) + "
" +
_("If this process is too slow, please set the key "
"server address appropriately in the gnupg configuration "
"file (depending "
"on the network situation in your country or region)."));
waiting_dialog_label->setWordWrap(true);
waiting_dialog->setLabel(waiting_dialog_label);
waiting_dialog->resize(420, 120);
app->connect(init_ctx_task, &Thread::CtxCheckTask::SignalTaskFinished,
waiting_dialog, [=]() {
SPDLOG_INFO("gpg context loaded");
waiting_dialog->finished(0);
waiting_dialog->deleteLater();
});
app->connect(waiting_dialog, &QProgressDialog::canceled, [=]() {
SPDLOG_INFO("cancel clicked");
app->quit();
exit(0);
});
// show the loading window
waiting_dialog->setModal(true);
waiting_dialog->setFocus();
waiting_dialog->show();
// new local event looper
QEventLoop looper;
app->connect(init_ctx_task, &Thread::CtxCheckTask::SignalTaskFinished,
&looper, &QEventLoop::quit);
// start the thread to load the gpg context
Thread::TaskRunnerGetter::GetInstance().GetTaskRunner()->PostTask(
init_ctx_task);
// block the main thread until the gpg context is loaded
looper.exec();
}
int RunGpgFrontendUI(QApplication* app) {
// create main window and show it
auto main_window = std::make_unique();
main_window->Init();
SPDLOG_INFO("main window inited");
main_window->show();
// start the main event loop
return app->exec();
}
void init_logging_system() {
using namespace boost::posix_time;
using namespace boost::gregorian;
// get the log directory
auto logfile_path = (GlobalSettingStation::GetInstance().GetLogDir() / "ui");
logfile_path.replace_extension(".log");
// sinks
std::vector sinks;
sinks.push_back(std::make_shared());
sinks.push_back(std::make_shared(
logfile_path.u8string(), 1048576 * 32, 32));
// thread pool
spdlog::init_thread_pool(1024, 2);
// logger
auto ui_logger = std::make_shared(
"core", begin(sinks), end(sinks), spdlog::thread_pool());
ui_logger->set_pattern(
"[%H:%M:%S.%e] [T:%t] [%=4n] %^[%=8l]%$ [%s:%#] [%!] -> %v (+%ius)");
#ifdef DEBUG
ui_logger->set_level(spdlog::level::trace);
#else
core_logger->set_level(spdlog::level::info);
#endif
// register it as default logger
spdlog::set_default_logger(ui_logger);
}
/**
* @brief setup the locale and load the translations
*
*/
void init_locale() {
// get the instance of the GlobalSettingStation
auto& settings =
GpgFrontend::GlobalSettingStation::GetInstance().GetUISettings();
// create general settings if not exist
if (!settings.exists("general") ||
settings.lookup("general").getType() != libconfig::Setting::TypeGroup)
settings.add("general", libconfig::Setting::TypeGroup);
// set system default at first
auto& general = settings["general"];
if (!general.exists("lang"))
general.add("lang", libconfig::Setting::TypeString) = "";
// sync the settings to the file
GpgFrontend::GlobalSettingStation::GetInstance().SyncSettings();
SPDLOG_INFO("current system locale: {}", setlocale(LC_ALL, nullptr));
// read from settings file
std::string lang;
if (!general.lookupValue("lang", lang)) {
SPDLOG_ERROR(_("could not read properly from configure file"));
};
SPDLOG_INFO("lang from settings: {}", lang);
SPDLOG_INFO("project name: {}", PROJECT_NAME);
SPDLOG_INFO(
"locales path: {}",
GpgFrontend::GlobalSettingStation::GetInstance().GetLocaleDir().c_str());
#ifndef WINDOWS
if (!lang.empty()) {
std::string lc = lang.empty() ? "" : lang + ".UTF-8";
// set LC_ALL
auto* locale_name = setlocale(LC_ALL, lc.c_str());
if (locale_name == nullptr) SPDLOG_WARN("set LC_ALL failed: {}", lc);
auto language = getenv("LANGUAGE");
// set LANGUAGE
std::string language_env = language == nullptr ? "en" : language;
language_env.insert(0, lang + ":");
SPDLOG_INFO("language env: {}", language_env);
if (setenv("LANGUAGE", language_env.c_str(), 1)) {
SPDLOG_WARN("set LANGUAGE failed", language_env);
};
}
#else
if (!lang.empty()) {
std::string lc = lang.empty() ? "" : lang;
// set LC_ALL
auto* locale_name = setlocale(LC_ALL, lc.c_str());
if (locale_name == nullptr) SPDLOG_WARN("set LC_ALL failed", lc);
auto language = getenv("LANGUAGE");
// set LANGUAGE
std::string language_env = language == nullptr ? "en" : language;
language_env.insert(0, lang + ":");
language_env.insert(0, "LANGUAGE=");
SPDLOG_INFO("language env: {}", language_env);
if (putenv(language_env.c_str())) {
spdlog::warn, "set LANGUAGE failed", language_env;
};
}
#endif
bindtextdomain(PROJECT_NAME, GpgFrontend::GlobalSettingStation::GetInstance()
.GetLocaleDir()
.u8string()
.c_str());
bind_textdomain_codeset(PROJECT_NAME, "utf-8");
textdomain(PROJECT_NAME);
}
} // namespace GpgFrontend::UI