forked from quickshell/quickshell
core: add pragmas
UseQApplication: use QApplication over QGuiApplication (for qqc2-desktop-style) NativeTextRendering: use NativeTextRendering over QtRendering for text Env VAR = VAL: define environment variables (usually qt ones)
This commit is contained in:
parent
c0847366dd
commit
082c3c480f
|
@ -57,8 +57,8 @@ if (NOT CMAKE_BUILD_TYPE)
|
|||
set(CMAKE_BUILD_TYPE Debug)
|
||||
endif()
|
||||
|
||||
set(QT_DEPS Qt6::Gui Qt6::Qml Qt6::Quick Qt6::QuickControls2)
|
||||
set(QT_FPDEPS Gui Qml Quick QuickControls2)
|
||||
set(QT_DEPS Qt6::Gui Qt6::Qml Qt6::Quick Qt6::QuickControls2 Qt6::Widgets)
|
||||
set(QT_FPDEPS Gui Qml Quick QuickControls2 Widgets)
|
||||
|
||||
if (BUILD_TESTING)
|
||||
enable_testing()
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
#include "main.hpp"
|
||||
#include <iostream>
|
||||
|
||||
#include <qapplication.h>
|
||||
#include <qcommandlineoption.h>
|
||||
#include <qcommandlineparser.h>
|
||||
#include <qcoreapplication.h>
|
||||
#include <qdir.h>
|
||||
#include <qfileinfo.h>
|
||||
#include <qguiapplication.h>
|
||||
#include <qhash.h>
|
||||
#include <qlogging.h>
|
||||
#include <qobject.h>
|
||||
#include <qquickwindow.h>
|
||||
|
@ -19,34 +22,41 @@
|
|||
#include "rootwrapper.hpp"
|
||||
|
||||
int qs_main(int argc, char** argv) {
|
||||
const auto app = QGuiApplication(argc, argv);
|
||||
QGuiApplication::setApplicationName("quickshell");
|
||||
QGuiApplication::setApplicationVersion("0.1.0 (" GIT_REVISION ")");
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
|
||||
// clang-format off
|
||||
auto currentOption = QCommandLineOption("current", "Print information about the manifest and defaults.");
|
||||
auto manifestOption = QCommandLineOption({"m", "manifest"}, "Path to a configuration manifest.", "path");
|
||||
auto configOption = QCommandLineOption({"c", "config"}, "Name of a configuration in the manifest.", "name");
|
||||
auto pathOption = QCommandLineOption({"p", "path"}, "Path to a configuration file.", "path");
|
||||
auto workdirOption = QCommandLineOption({"d", "workdir"}, "Initial working directory.", "path");
|
||||
// clang-format on
|
||||
|
||||
parser.addOption(currentOption);
|
||||
parser.addOption(manifestOption);
|
||||
parser.addOption(configOption);
|
||||
parser.addOption(pathOption);
|
||||
parser.addOption(workdirOption);
|
||||
parser.process(app);
|
||||
|
||||
QString configFilePath;
|
||||
{
|
||||
auto printCurrent = parser.isSet(currentOption);
|
||||
QString workingDirectory;
|
||||
|
||||
// NOLINTBEGIN
|
||||
auto useQApplication = false;
|
||||
auto nativeTextRendering = false;
|
||||
QHash<QString, QString> envOverrides;
|
||||
|
||||
{
|
||||
const auto app = QCoreApplication(argc, argv);
|
||||
QCoreApplication::setApplicationName("quickshell");
|
||||
QCoreApplication::setApplicationVersion("0.1.0 (" GIT_REVISION ")");
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
|
||||
// clang-format off
|
||||
auto currentOption = QCommandLineOption("current", "Print information about the manifest and defaults.");
|
||||
auto manifestOption = QCommandLineOption({"m", "manifest"}, "Path to a configuration manifest.", "path");
|
||||
auto configOption = QCommandLineOption({"c", "config"}, "Name of a configuration in the manifest.", "name");
|
||||
auto pathOption = QCommandLineOption({"p", "path"}, "Path to a configuration file.", "path");
|
||||
auto workdirOption = QCommandLineOption({"d", "workdir"}, "Initial working directory.", "path");
|
||||
// clang-format on
|
||||
|
||||
parser.addOption(currentOption);
|
||||
parser.addOption(manifestOption);
|
||||
parser.addOption(configOption);
|
||||
parser.addOption(pathOption);
|
||||
parser.addOption(workdirOption);
|
||||
parser.process(app);
|
||||
|
||||
{
|
||||
auto printCurrent = parser.isSet(currentOption);
|
||||
|
||||
// NOLINTBEGIN
|
||||
#define CHECK(rname, name, level, label, expr) \
|
||||
QString name = expr; \
|
||||
if (rname.isEmpty() && !name.isEmpty()) { \
|
||||
|
@ -56,194 +66,250 @@ int qs_main(int argc, char** argv) {
|
|||
}
|
||||
|
||||
#define OPTSTR(name) (name.isEmpty() ? "(unset)" : name.toStdString())
|
||||
// NOLINTEND
|
||||
|
||||
QString basePath;
|
||||
int basePathLevel = 0;
|
||||
Q_UNUSED(basePathLevel);
|
||||
{
|
||||
// NOLINTBEGIN
|
||||
// clang-format off
|
||||
CHECK(basePath, envBasePath, 0, foundbase, qEnvironmentVariable("QS_BASE_PATH"));
|
||||
CHECK(basePath, defaultBasePath, 0, foundbase, QDir(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)).filePath("quickshell"));
|
||||
// clang-format on
|
||||
// NOLINTEND
|
||||
|
||||
if (printCurrent) {
|
||||
QString basePath;
|
||||
int basePathLevel = 0;
|
||||
Q_UNUSED(basePathLevel);
|
||||
{
|
||||
// NOLINTBEGIN
|
||||
// clang-format off
|
||||
std::cout << "Base path: " << OPTSTR(basePath) << "\n";
|
||||
std::cout << " - Environment (QS_BASE_PATH): " << OPTSTR(envBasePath) << "\n";
|
||||
std::cout << " - Default: " << OPTSTR(defaultBasePath) << "\n";
|
||||
CHECK(basePath, envBasePath, 0, foundbase, qEnvironmentVariable("QS_BASE_PATH"));
|
||||
CHECK(basePath, defaultBasePath, 0, foundbase, QDir(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)).filePath("quickshell"));
|
||||
// clang-format on
|
||||
// NOLINTEND
|
||||
|
||||
if (printCurrent) {
|
||||
// clang-format off
|
||||
std::cout << "Base path: " << OPTSTR(basePath) << "\n";
|
||||
std::cout << " - Environment (QS_BASE_PATH): " << OPTSTR(envBasePath) << "\n";
|
||||
std::cout << " - Default: " << OPTSTR(defaultBasePath) << "\n";
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
}
|
||||
foundbase:;
|
||||
foundbase:;
|
||||
|
||||
QString configPath;
|
||||
int configPathLevel = 10;
|
||||
{
|
||||
// NOLINTBEGIN
|
||||
CHECK(configPath, optionConfigPath, 0, foundpath, parser.value(pathOption));
|
||||
CHECK(configPath, envConfigPath, 1, foundpath, qEnvironmentVariable("QS_CONFIG_PATH"));
|
||||
// NOLINTEND
|
||||
QString configPath;
|
||||
int configPathLevel = 10;
|
||||
{
|
||||
// NOLINTBEGIN
|
||||
CHECK(configPath, optionConfigPath, 0, foundpath, parser.value(pathOption));
|
||||
CHECK(configPath, envConfigPath, 1, foundpath, qEnvironmentVariable("QS_CONFIG_PATH"));
|
||||
// NOLINTEND
|
||||
|
||||
if (printCurrent) {
|
||||
if (printCurrent) {
|
||||
// clang-format off
|
||||
std::cout << "\nConfig path: " << OPTSTR(configPath) << "\n";
|
||||
std::cout << " - Option: " << OPTSTR(optionConfigPath) << "\n";
|
||||
std::cout << " - Environment (QS_CONFIG_PATH): " << OPTSTR(envConfigPath) << "\n";
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
foundpath:;
|
||||
|
||||
QString manifestPath;
|
||||
int manifestPathLevel = 10;
|
||||
{
|
||||
// NOLINTBEGIN
|
||||
// clang-format off
|
||||
std::cout << "\nConfig path: " << OPTSTR(configPath) << "\n";
|
||||
std::cout << " - Option: " << OPTSTR(optionConfigPath) << "\n";
|
||||
std::cout << " - Environment (QS_CONFIG_PATH): " << OPTSTR(envConfigPath) << "\n";
|
||||
CHECK(manifestPath, optionManifestPath, 0, foundmf, parser.value(manifestOption));
|
||||
CHECK(manifestPath, envManifestPath, 1, foundmf, qEnvironmentVariable("QS_MANIFEST"));
|
||||
CHECK(manifestPath, defaultManifestPath, 2, foundmf, QDir(basePath).filePath("manifest.conf"));
|
||||
// clang-format on
|
||||
// NOLINTEND
|
||||
|
||||
if (printCurrent) {
|
||||
// clang-format off
|
||||
std::cout << "\nManifest path: " << OPTSTR(manifestPath) << "\n";
|
||||
std::cout << " - Option: " << OPTSTR(optionManifestPath) << "\n";
|
||||
std::cout << " - Environment (QS_MANIFEST): " << OPTSTR(envManifestPath) << "\n";
|
||||
std::cout << " - Default: " << OPTSTR(defaultManifestPath) << "\n";
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
}
|
||||
foundpath:;
|
||||
foundmf:;
|
||||
|
||||
QString manifestPath;
|
||||
int manifestPathLevel = 10;
|
||||
{
|
||||
// NOLINTBEGIN
|
||||
// clang-format off
|
||||
CHECK(manifestPath, optionManifestPath, 0, foundmf, parser.value(manifestOption));
|
||||
CHECK(manifestPath, envManifestPath, 1, foundmf, qEnvironmentVariable("QS_MANIFEST"));
|
||||
CHECK(manifestPath, defaultManifestPath, 2, foundmf, QDir(basePath).filePath("manifest.conf"));
|
||||
// clang-format on
|
||||
// NOLINTEND
|
||||
QString configName;
|
||||
int configNameLevel = 10;
|
||||
{
|
||||
// NOLINTBEGIN
|
||||
CHECK(configName, optionConfigName, 0, foundname, parser.value(configOption));
|
||||
CHECK(configName, envConfigName, 1, foundname, qEnvironmentVariable("QS_CONFIG_NAME"));
|
||||
// NOLINTEND
|
||||
|
||||
if (printCurrent) {
|
||||
// clang-format off
|
||||
std::cout << "\nManifest path: " << OPTSTR(manifestPath) << "\n";
|
||||
std::cout << " - Option: " << OPTSTR(optionManifestPath) << "\n";
|
||||
std::cout << " - Environment (QS_MANIFEST): " << OPTSTR(envManifestPath) << "\n";
|
||||
std::cout << " - Default: " << OPTSTR(defaultManifestPath) << "\n";
|
||||
// clang-format on
|
||||
if (printCurrent) {
|
||||
// clang-format off
|
||||
std::cout << "\nConfig name: " << OPTSTR(configName) << "\n";
|
||||
std::cout << " - Option: " << OPTSTR(optionConfigName) << "\n";
|
||||
std::cout << " - Environment (QS_CONFIG_NAME): " << OPTSTR(envConfigName) << "\n\n";
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
}
|
||||
foundmf:;
|
||||
foundname:;
|
||||
|
||||
QString configName;
|
||||
int configNameLevel = 10;
|
||||
{
|
||||
// NOLINTBEGIN
|
||||
CHECK(configName, optionConfigName, 0, foundname, parser.value(configOption));
|
||||
CHECK(configName, envConfigName, 1, foundname, qEnvironmentVariable("QS_CONFIG_NAME"));
|
||||
// NOLINTEND
|
||||
|
||||
if (printCurrent) {
|
||||
// clang-format off
|
||||
std::cout << "\nConfig name: " << OPTSTR(configName) << "\n";
|
||||
std::cout << " - Option: " << OPTSTR(optionConfigName) << "\n";
|
||||
std::cout << " - Environment (QS_CONFIG_NAME): " << OPTSTR(envConfigName) << "\n\n";
|
||||
// clang-format on
|
||||
if (configPathLevel == 0 && configNameLevel == 0) {
|
||||
qCritical() << "Pass only one of --path or --config";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
foundname:;
|
||||
|
||||
if (configPathLevel == 0 && configNameLevel == 0) {
|
||||
qFatal() << "Pass only one of --path or --config";
|
||||
return -1;
|
||||
}
|
||||
if (!configPath.isEmpty() && configPathLevel <= configNameLevel) {
|
||||
configFilePath = configPath;
|
||||
} else if (!configName.isEmpty()) {
|
||||
if (!manifestPath.isEmpty()) {
|
||||
auto file = QFile(manifestPath);
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
auto stream = QTextStream(&file);
|
||||
while (!stream.atEnd()) {
|
||||
auto line = stream.readLine();
|
||||
if (line.trimmed().startsWith("#")) continue;
|
||||
if (line.trimmed().isEmpty()) continue;
|
||||
|
||||
if (!configPath.isEmpty() && configPathLevel <= configNameLevel) {
|
||||
configFilePath = configPath;
|
||||
} else if (!configName.isEmpty()) {
|
||||
if (!manifestPath.isEmpty()) {
|
||||
auto file = QFile(manifestPath);
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
auto stream = QTextStream(&file);
|
||||
while (!stream.atEnd()) {
|
||||
auto line = stream.readLine();
|
||||
if (line.trimmed().startsWith("#")) continue;
|
||||
if (line.trimmed().isEmpty()) continue;
|
||||
auto split = line.split('=');
|
||||
if (split.length() != 2) {
|
||||
qCritical() << "manifest line not in expected format 'name = relativepath':"
|
||||
<< line;
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto split = line.split('=');
|
||||
if (split.length() != 2) {
|
||||
qFatal() << "manifest line not in expected format 'name = relativepath':" << line;
|
||||
return -1;
|
||||
if (split[0].trimmed() == configName) {
|
||||
configFilePath = QDir(QFileInfo(file).canonicalPath()).filePath(split[1].trimmed());
|
||||
goto haspath; // NOLINT
|
||||
}
|
||||
}
|
||||
|
||||
if (split[0].trimmed() == configName) {
|
||||
configFilePath = QDir(QFileInfo(file).canonicalPath()).filePath(split[1].trimmed());
|
||||
qCritical() << "configuration" << configName << "not found in manifest" << manifestPath;
|
||||
return -1;
|
||||
} else if (manifestPathLevel < 2) {
|
||||
qCritical() << "cannot open config manifest at" << manifestPath;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto basePathInfo = QFileInfo(basePath);
|
||||
if (!basePathInfo.exists()) {
|
||||
qCritical() << "base path does not exist:" << basePath;
|
||||
return -1;
|
||||
} else if (!QFileInfo(basePathInfo.canonicalFilePath()).isDir()) {
|
||||
qCritical() << "base path is not a directory" << basePath;
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto dir = QDir(basePath);
|
||||
for (auto& entry: dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot)) {
|
||||
if (entry == configName) {
|
||||
configFilePath = dir.filePath(entry);
|
||||
goto haspath; // NOLINT
|
||||
}
|
||||
}
|
||||
|
||||
qFatal() << "configuration" << configName << "not found in manifest" << manifestPath;
|
||||
return -1;
|
||||
} else if (manifestPathLevel < 2) {
|
||||
qFatal() << "cannot open config manifest at" << manifestPath;
|
||||
qCritical() << "no directory named " << configName << "found in base path" << basePath;
|
||||
return -1;
|
||||
}
|
||||
haspath:;
|
||||
} else {
|
||||
configFilePath = basePath;
|
||||
}
|
||||
|
||||
{
|
||||
auto basePathInfo = QFileInfo(basePath);
|
||||
if (!basePathInfo.exists()) {
|
||||
qFatal() << "base path does not exist:" << basePath;
|
||||
return -1;
|
||||
} else if (!QFileInfo(basePathInfo.canonicalFilePath()).isDir()) {
|
||||
qFatal() << "base path is not a directory" << basePath;
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto dir = QDir(basePath);
|
||||
for (auto& entry: dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot)) {
|
||||
if (entry == configName) {
|
||||
configFilePath = dir.filePath(entry);
|
||||
goto haspath; // NOLINT
|
||||
}
|
||||
}
|
||||
|
||||
qFatal() << "no directory named " << configName << "found in base path" << basePath;
|
||||
auto configFile = QFileInfo(configFilePath);
|
||||
if (!configFile.exists()) {
|
||||
qCritical() << "config path does not exist:" << configFilePath;
|
||||
return -1;
|
||||
}
|
||||
haspath:;
|
||||
} else {
|
||||
configFilePath = basePath;
|
||||
}
|
||||
|
||||
auto configFile = QFileInfo(configFilePath);
|
||||
if (!configFile.exists()) {
|
||||
qFatal() << "config path does not exist:" << configFilePath;
|
||||
return -1;
|
||||
}
|
||||
if (configFile.isDir()) {
|
||||
configFilePath = QDir(configFilePath).filePath("shell.qml");
|
||||
}
|
||||
|
||||
if (configFile.isDir()) {
|
||||
configFilePath = QDir(configFilePath).filePath("shell.qml");
|
||||
}
|
||||
configFile = QFileInfo(configFilePath);
|
||||
if (!configFile.exists()) {
|
||||
qCritical() << "no shell.qml found in config path:" << configFilePath;
|
||||
return -1;
|
||||
} else if (configFile.isDir()) {
|
||||
qCritical() << "shell.qml is a directory:" << configFilePath;
|
||||
return -1;
|
||||
}
|
||||
|
||||
configFile = QFileInfo(configFilePath);
|
||||
if (!configFile.exists()) {
|
||||
qFatal() << "no shell.qml found in config path:" << configFilePath;
|
||||
return -1;
|
||||
} else if (configFile.isDir()) {
|
||||
qFatal() << "shell.qml is a directory:" << configFilePath;
|
||||
return -1;
|
||||
}
|
||||
|
||||
configFilePath = QFileInfo(configFilePath).canonicalFilePath();
|
||||
configFile = QFileInfo(configFilePath);
|
||||
if (!configFile.exists()) {
|
||||
qFatal() << "config file does not exist:" << configFilePath;
|
||||
return -1;
|
||||
} else if (configFile.isDir()) {
|
||||
qFatal() << "config file is a directory:" << configFilePath;
|
||||
return -1;
|
||||
}
|
||||
configFilePath = QFileInfo(configFilePath).canonicalFilePath();
|
||||
configFile = QFileInfo(configFilePath);
|
||||
if (!configFile.exists()) {
|
||||
qCritical() << "config file does not exist:" << configFilePath;
|
||||
return -1;
|
||||
} else if (configFile.isDir()) {
|
||||
qCritical() << "config file is a directory:" << configFilePath;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#undef CHECK
|
||||
#undef OPTSTR
|
||||
|
||||
qInfo() << "config file path:" << configFilePath;
|
||||
qInfo() << "config file path:" << configFilePath;
|
||||
|
||||
if (printCurrent) return 0;
|
||||
if (printCurrent) return 0;
|
||||
}
|
||||
|
||||
if (!QFile(configFilePath).exists()) {
|
||||
qCritical() << "config file does not exist";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (parser.isSet(workdirOption)) {
|
||||
workingDirectory = parser.value(workdirOption);
|
||||
}
|
||||
|
||||
auto file = QFile(configFilePath);
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
||||
qCritical() << "could not open config file";
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto stream = QTextStream(&file);
|
||||
while (!stream.atEnd()) {
|
||||
auto line = stream.readLine().trimmed();
|
||||
if (line.startsWith("//@ pragma ")) {
|
||||
auto pragma = line.sliced(11).trimmed();
|
||||
|
||||
if (pragma == "UseQApplication") useQApplication = true;
|
||||
else if (pragma == "NativeTextRendering") nativeTextRendering = true;
|
||||
else if (pragma.startsWith("Env ")) {
|
||||
auto envPragma = pragma.sliced(4);
|
||||
auto splitIdx = envPragma.indexOf('=');
|
||||
|
||||
if (splitIdx == -1) {
|
||||
qCritical() << "Env pragma" << pragma << "not in the form 'VAR = VALUE'";
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto var = envPragma.sliced(0, splitIdx).trimmed();
|
||||
auto val = envPragma.sliced(splitIdx + 1).trimmed();
|
||||
envOverrides.insert(var, val);
|
||||
} else {
|
||||
qCritical() << "Unrecognized pragma" << pragma;
|
||||
return -1;
|
||||
}
|
||||
} else if (line.startsWith("import")) break;
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
if (!QFile(configFilePath).exists()) {
|
||||
qCritical() << "config file does not exist";
|
||||
return -1;
|
||||
for (auto [var, val]: envOverrides.asKeyValueRange()) {
|
||||
qputenv(var.toUtf8(), val.toUtf8());
|
||||
}
|
||||
|
||||
if (parser.isSet(workdirOption)) {
|
||||
QDir::setCurrent(parser.value(workdirOption));
|
||||
QCoreApplication* app = nullptr;
|
||||
|
||||
if (useQApplication) {
|
||||
app = new QApplication(argc, argv);
|
||||
} else {
|
||||
app = new QGuiApplication(argc, argv);
|
||||
}
|
||||
|
||||
QCoreApplication::setApplicationName("quickshell");
|
||||
QCoreApplication::setApplicationVersion("0.1.0 (" GIT_REVISION ")");
|
||||
|
||||
if (!workingDirectory.isEmpty()) {
|
||||
QDir::setCurrent(workingDirectory);
|
||||
}
|
||||
|
||||
QuickshellPlugin::initPlugins();
|
||||
|
@ -252,8 +318,12 @@ int qs_main(int argc, char** argv) {
|
|||
// Use a fully transparent window with a colored rect.
|
||||
QQuickWindow::setDefaultAlphaBuffer(true);
|
||||
|
||||
if (nativeTextRendering) {
|
||||
QQuickWindow::setTextRenderType(QQuickWindow::NativeTextRendering);
|
||||
}
|
||||
|
||||
auto root = RootWrapper(configFilePath);
|
||||
QGuiApplication::setQuitOnLastWindowClosed(false);
|
||||
|
||||
return QGuiApplication::exec();
|
||||
return QCoreApplication::exec();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue