feat: include ai first step works
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
#include <QApplication>
|
||||
#include <QCommandLineOption>
|
||||
#include <QCommandLineParser>
|
||||
#include <QLocale>
|
||||
#include <QMessageBox>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QTranslator>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <wfassoc++.h>
|
||||
|
||||
#include "main_window.h"
|
||||
#include "manifest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Context used for translatable strings that live outside of any QObject.
|
||||
// Keeping it stable lets translators find these messages under the same key
|
||||
// across builds.
|
||||
constexpr const char* kTranslationContext = "qwfassoc";
|
||||
|
||||
// Show a modal error dialog with the given message and return a non-zero
|
||||
// exit code. Used for the various fatal conditions that may occur before the
|
||||
// main dialog can be shown.
|
||||
int fatal(QWidget* parent, const QString& message) {
|
||||
// The application name is treated as a brand identifier and is not
|
||||
// translated; the message text itself is already translated by callers.
|
||||
QMessageBox::critical(parent, QApplication::applicationName(), message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Convert the --for command line value to a TargetScope. Throws if the value
|
||||
// is not one of the accepted strings.
|
||||
qwfassoc::TargetScope parseScope(const QString& value) {
|
||||
const QString normalized = value.trimmed().toLower();
|
||||
if (normalized == QStringLiteral("user")) {
|
||||
return qwfassoc::TargetScope::User;
|
||||
}
|
||||
if (normalized == QStringLiteral("system")) {
|
||||
return qwfassoc::TargetScope::System;
|
||||
}
|
||||
throw std::runtime_error(
|
||||
"Invalid value for --for. Use \"user\" or \"system\".");
|
||||
}
|
||||
|
||||
// Load the translation matching the user's preferred UI language, if any.
|
||||
// Qt's qt6_add_translations() compiles .ts files into .qm files and embeds
|
||||
// them under the ":/i18n" resource prefix.
|
||||
void installTranslators(QApplication& app) {
|
||||
QTranslator* translator = new QTranslator(&app);
|
||||
const QStringList uiLanguages = QLocale::system().uiLanguages();
|
||||
for (const QString& locale : uiLanguages) {
|
||||
const QString baseName =
|
||||
QStringLiteral("qwfassoc_") + QLocale(locale).name();
|
||||
if (translator->load(QStringLiteral(":/i18n/") + baseName)) {
|
||||
app.installTranslator(translator);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
QApplication app(argc, argv);
|
||||
QApplication::setApplicationName(QStringLiteral("qwfassoc"));
|
||||
|
||||
// Install available translations before any translatable string is
|
||||
// resolved (including the application display name below) so that tr()
|
||||
// and QCoreApplication::translate() pick up the right language.
|
||||
installTranslators(app);
|
||||
|
||||
QApplication::setApplicationDisplayName(
|
||||
QCoreApplication::translate(kTranslationContext,
|
||||
"qwfassoc - wfassoc Configurator"));
|
||||
|
||||
// Parse command line arguments using Qt's built-in parser.
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(
|
||||
QCoreApplication::translate(kTranslationContext,
|
||||
"Qt-based GUI for the wfassoc library."));
|
||||
parser.addHelpOption();
|
||||
|
||||
QCommandLineOption manifestOption(
|
||||
QStringList() << QStringLiteral("c") << QStringLiteral("manifest"),
|
||||
QCoreApplication::translate(kTranslationContext,
|
||||
"Path to the application manifest TOML file."),
|
||||
QStringLiteral("manifest"));
|
||||
QCommandLineOption forOption(
|
||||
QStringList() << QStringLiteral("f") << QStringLiteral("for"),
|
||||
QCoreApplication::translate(kTranslationContext,
|
||||
"Target scope: \"user\" or \"system\"."),
|
||||
QStringLiteral("scope"));
|
||||
|
||||
parser.addOption(manifestOption);
|
||||
parser.addOption(forOption);
|
||||
parser.process(app);
|
||||
|
||||
// Validate that both mandatory options were provided with sane values.
|
||||
const QString manifestPath = parser.value(manifestOption);
|
||||
const QString forValue = parser.value(forOption);
|
||||
|
||||
if (manifestPath.isEmpty()) {
|
||||
return fatal(nullptr,
|
||||
QCoreApplication::translate(
|
||||
kTranslationContext,
|
||||
"The --manifest/-c option is required."));
|
||||
}
|
||||
if (forValue.isEmpty()) {
|
||||
return fatal(nullptr,
|
||||
QCoreApplication::translate(
|
||||
kTranslationContext,
|
||||
"The --for/-f option is required."));
|
||||
}
|
||||
|
||||
qwfassoc::TargetScope scope;
|
||||
try {
|
||||
scope = parseScope(forValue);
|
||||
} catch (const std::exception& e) {
|
||||
return fatal(nullptr, QString::fromUtf8(e.what()));
|
||||
}
|
||||
|
||||
// Initialize the wfassoc runtime. WFStartup must run before most other
|
||||
// wfassoc calls; if it fails we cannot proceed.
|
||||
if (!wfassoc::WFStartup()) {
|
||||
return fatal(nullptr,
|
||||
QString::fromUtf8(wfassoc::WFGetLastError()));
|
||||
}
|
||||
|
||||
// Build the manifest -> schema -> program pipeline and run the dialog.
|
||||
// Program construction consumes the schema (move) and performs the deep
|
||||
// validation (identifier format, dangling references, etc.).
|
||||
int exitCode = 0;
|
||||
try {
|
||||
qwfassoc::Manifest manifest =
|
||||
qwfassoc::Manifest::fromFile(manifestPath.toStdString());
|
||||
wfassocpp::Schema schema = manifest.toSchema();
|
||||
wfassocpp::Program program(std::move(schema));
|
||||
|
||||
qwfassoc::MainWindow window(std::move(program), scope);
|
||||
exitCode = window.exec();
|
||||
} catch (const std::exception& e) {
|
||||
wfassoc::WFShutdown();
|
||||
return fatal(nullptr, QString::fromUtf8(e.what()));
|
||||
}
|
||||
|
||||
wfassoc::WFShutdown();
|
||||
return exitCode;
|
||||
}
|
||||
Reference in New Issue
Block a user