Browse Source

Use LocalAppData fallback for Windows ChatGUI storage

master
evgeny 5 days ago
parent
commit
753aa4217d
  1. 49
      tools/chatgui/src/main.cpp
  2. 7
      tools/chatgui/src/mainwindow.cpp

49
tools/chatgui/src/main.cpp

@ -14,6 +14,8 @@
#include "gui_language.h"
#include <cstdio>
#ifdef _WIN32
#include <QStandardPaths>
#include <QTemporaryFile>
#include <windows.h>
#include <tlhelp32.h>
#endif
@ -85,9 +87,44 @@ int main(int argc, char *argv[]) {
app.setQuitOnLastWindowClosed(false);
debug_config_init();
QString cfgDir = QCoreApplication::applicationDirPath();
#ifdef _WIN32
QString storageReason;
if (!QFile::exists(cfgDir + "/vibechat.cfg") && !QFile::exists(cfgDir + "/chatgui.cfg")) {
storageReason = QStringLiteral("config missing in executable directory");
} else {
/* Реальная проверка записи учитывает ACL Windows, а не только атрибуты каталога. */
QTemporaryFile probe(cfgDir + "/.vibechat-write-XXXXXX");
if (!probe.open()) {
storageReason = QStringLiteral("executable directory is not writable: %1").arg(probe.errorString());
} else if (!probe.remove()) {
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Cannot remove write probe %s: %s",
qPrintable(probe.fileName()), qPrintable(probe.errorString()));
return 1;
}
}
if (!storageReason.isEmpty()) {
cfgDir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
if (cfgDir.isEmpty() || !QDir().mkpath(cfgDir)) {
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Cannot create LocalAppData directory %s; fallback reason: %s",
qPrintable(cfgDir), qPrintable(storageReason));
return 1;
}
} else {
storageReason = QStringLiteral("config found in writable executable directory");
}
#endif
/* Блокировка до любых изменений конфига/БД; предупреждение после загрузки языка. */
QLockFile lock(QCoreApplication::applicationDirPath() + "/vibechat.lock");
QLockFile lock(cfgDir + "/vibechat.lock");
const bool locked = lock.tryLock();
#ifdef _WIN32
if (!locked && lock.error() != QLockFile::LockFailedError) {
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Cannot lock data directory %s: error=%d; selection reason: %s",
qPrintable(cfgDir), static_cast<int>(lock.error()), qPrintable(storageReason));
return 1;
}
#endif
app.setStyle(QStyleFactory::create("Fusion"));
QPalette p;
@ -108,7 +145,6 @@ int main(int argc, char *argv[]) {
p.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127));
app.setPalette(p);
QString cfgDir = QCoreApplication::applicationDirPath();
QString cfgPath = cfgDir + "/vibechat.cfg";
/* миграция: старый конфиг chatgui.cfg → vibechat.cfg */
if (locked && !QFile::exists(cfgPath) && QFile::exists(cfgDir + "/chatgui.cfg"))
@ -166,13 +202,13 @@ int main(int argc, char *argv[]) {
QString dbPath = cfg.dbPath();
if (dbPath.isEmpty()) dbPath = "chat_data";
if (!QDir::isAbsolutePath(dbPath))
dbPath = QCoreApplication::applicationDirPath() + "/" + dbPath;
dbPath = cfgDir + "/" + dbPath;
QDir(dbPath).mkpath(".");
QString debugFile = cfg.debugFile();
if (debugFile.isEmpty()) debugFile = "chatgui.log";
if (!QDir::isAbsolutePath(debugFile))
debugFile = QCoreApplication::applicationDirPath() + "/" + debugFile;
debugFile = cfgDir + "/" + debugFile;
/* ранняя инициализация лога в GUI-потоке: SoundManager::init() вызывается в
* конструкторе MainWindow ДО старта utun-потока, поэтому без этого его диагностика
@ -183,6 +219,11 @@ int main(int argc, char *argv[]) {
if (lvl.isEmpty()) lvl = QStringLiteral("info");
debug_apply_global_level(lvl.toUtf8().constData());
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "vibechat: version=%s", qPrintable(app.applicationVersion()));
#ifdef _WIN32
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Windows storage: reason=%s config=%s db=%s log=%s lock=%s",
qPrintable(storageReason), qPrintable(cfgPath), qPrintable(dbPath), qPrintable(debugFile),
qPrintable(cfgDir + "/vibechat.lock"));
#endif
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "GUI language: preference=%s system=%s selected=%s",
qPrintable(cfg.language()), qPrintable(QLocale::system().uiLanguages().join(',')), qPrintable(language));

7
tools/chatgui/src/mainwindow.cpp

@ -53,6 +53,9 @@ extern "C" {
#include <QFile>
#include <QTextStream>
#include <QDir>
#ifdef _WIN32
#include <QFileInfo>
#endif
#include <cmath>
#include <QJsonDocument>
#include <QJsonObject>
@ -362,7 +365,11 @@ void MainWindow::setupSoundFromConfig() {
}
if (soundDir.isEmpty()) soundDir = "sounds";
#ifdef _WIN32
QDir binDir(QFileInfo(m_cfgPath).absolutePath());
#else
QDir binDir(QApplication::applicationDirPath());
#endif
QString baseDir = QDir::isAbsolutePath(soundDir) ? soundDir : binDir.absoluteFilePath(soundDir);
auto resolvePath = [&baseDir](const QString& f) { return f.isEmpty() ? QString() : QDir::cleanPath(baseDir + "/" + f); };

Loading…
Cancel
Save