From df168536ca1aaf0b147e67ef214bf35dfd34e441 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 30 May 2019 01:14:31 +0200 Subject: Cleanup, and rewrite cmdline + settings handling Command line parsing now uses QCommandLineXXX classes Old unused options have been removed, like the "pools" feature Closes #3599 --- src/command_line_options.cpp | 140 --------------------- src/command_line_options.h | 23 ---- src/config.cpp | 103 ++++++++++++++++ src/config.h | 46 +++++++ src/dialog.cpp | 59 +++++---- src/dialog.h | 4 +- src/globals.cpp | 23 +--- src/globals.h | 25 +--- src/main.cpp | 284 ++++++------------------------------------- src/vsession.cpp | 16 +-- 10 files changed, 235 insertions(+), 488 deletions(-) delete mode 100644 src/command_line_options.cpp delete mode 100644 src/command_line_options.h create mode 100644 src/config.cpp create mode 100644 src/config.h diff --git a/src/command_line_options.cpp b/src/command_line_options.cpp deleted file mode 100644 index fc4e0e1..0000000 --- a/src/command_line_options.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include "command_line_options.h" -#include -#include - - -CommandLineOptions::CommandLineOptions(int argc, char * const argv[]) { - // parse command line arguments (please sort by short option for easier handling) - static const struct option longOptions[] = { - {"allow-vm-edit", no_argument, nullptr, 'vmed'}, - {"autoquit", required_argument, nullptr, 'aqit'}, - {"base", required_argument, nullptr, 'b'}, - {"path", required_argument, nullptr, 'b'}, // Compatibility to v1.0 - {"config", required_argument, nullptr, 'c'}, - {"debug", no_argument, nullptr, 'D'}, - {"default", required_argument, nullptr, 'd'}, - {"exam-mode", no_argument, nullptr, 'exms'}, - {"fullscreen", no_argument, nullptr, 'F'}, - {"file", required_argument, nullptr, 'f'}, - {"help", no_argument, nullptr, 'h'}, - {"insecure", no_argument, nullptr, 'i'}, - {"locations", required_argument, nullptr, 'l'}, - {"pool", required_argument, nullptr, 'P'}, - {"pvs", no_argument, nullptr, 'p'}, - {"pvs-checked", no_argument, nullptr, 'pvck'}, - {"runscript", no_argument, nullptr, 'S'}, - {"size", required_argument, nullptr, 's'}, - {"tab", required_argument, nullptr, 'T'}, - {"theme", required_argument, nullptr, 't'}, - {"url", required_argument, nullptr, 'u'}, - {"url-list", required_argument, nullptr, 'ulst'}, - {"url-news", required_argument, nullptr, 'unws'}, - {"url-help", required_argument, nullptr, 'uhlp'}, - {"version", no_argument, nullptr, 'v'}, - {"xpath", required_argument, nullptr, 'x'}, - {"location-mode", required_argument, nullptr, 'locm'}, - {"template-mode", required_argument, nullptr, 'tmpm'}, - {"start-uuid", required_argument, nullptr, 'uuid'}, - {"no-vtx", no_argument, nullptr, 'nvtx'}, - {nullptr, 0, nullptr, 0} - }; - - int c; - - // Again, please sort alphabetically in getopt_long call and switch statement - while ((c = getopt_long(argc, argv, "b:c:Dd:Ff:hil:P:pSs:t:T:u:vx:?", longOptions, nullptr)) != -1) { - switch (c) { - case 'aqit': - options.insert("autoquit", optarg); - break; - case 'b': - options.insert("base", optarg); - break; - case 'c': - options.insert("config", optarg); - break; - case 'D': - options.insert("debugMode", "debugMode"); - break; - case 'd': - options.insert("default", optarg); - break; - case 'F': - options.insert("fullscreen", "fullscreen"); - break; - case 'exms': - options.insert("exam-mode", "yo"); - break; - case 'f': - options.insert("file", optarg); - break; - case 'h': - case '?': - options.insert("usage", "usage"); - break; - case 'i': - options.insert("insecure", "nossl"); - break; - case 'l': - options.insert("locations", optarg); - break; - case 'p': - options.insert("pvs", "pvs"); - break; - case 'pvck': - options.insert("pvs-checked", "pvs-checked"); - break; - case 'P': - options.insert("pool", optarg); - break; - case 'S': - options.insert("runscript", optarg); - break; - case 's': - options.insert("size", optarg); - break; - case 't': - options.insert("theme", optarg); - break; - case 'T': - options.insert("tab", optarg); - break; - case 'u': - options.insert("url", optarg); - break; - case 'v': - options.insert("version", "version"); - break; - case 'x': - options.insert("xpath", optarg); - break; - case 'locm': - options.insert("location-mode", optarg); - break; - case 'tmpm': - options.insert("template-mode", optarg); - break; - case 'nvtx': - options.insert("no-vtx", "no-vtx"); - break; - case 'ulst': - options.insert("url-list", optarg); - break; - case 'unws': - options.insert("url-news", optarg); - break; - case 'uhlp': - options.insert("url-help", optarg); - break; - case 'uuid': - options.insert("uuid", optarg); - break; - case 'vmed': - options.insert("allow-vm-edit", ""); - break; - default: - options.insert("error", "error"); - break; - } - } -} diff --git a/src/command_line_options.h b/src/command_line_options.h deleted file mode 100644 index 8798ff2..0000000 --- a/src/command_line_options.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef VMCHOOSER_COMMAND_LINE_OPTIONS_H -#define VMCHOOSER_COMMAND_LINE_OPTIONS_H - -#include -#include - -class CommandLineOptions { - public: - CommandLineOptions(int argc, char * const argv[]); - - bool contains(const QString& key) const { - return options.contains(key); - } - - QString value(const QString& key) const { - return options.value(key); - } - - private: - QMap options; -}; - -#endif // VMCHOOSER_COMMAND_LINE_OPTIONS_H diff --git a/src/config.cpp b/src/config.cpp new file mode 100644 index 0000000..63630d0 --- /dev/null +++ b/src/config.cpp @@ -0,0 +1,103 @@ +#include "config.h" +#include "globals.h" + +#include +#include +#include +#include + +static QCommandLineParser parser; +static QSettings* configFile = nullptr; + +static inline QStringList combine(const QString &a, const QString &b) +{ + QStringList ret; + if (!a.isEmpty()) { + ret << a; + } + if (!b.isEmpty()) { + ret << b; + } + return ret; +} + +struct ConfigOption +{ + const QCommandLineOption cmdLine; + const QString iniKey; + const QString defaultValue; + const bool withArgument; + ConfigOption(const QString optShort, const QString optLong, const QString iniKey, const QString valueName, const QString defaultValue, const QString description) + : cmdLine(combine(optLong, optShort), description, valueName, defaultValue), iniKey(iniKey), defaultValue(defaultValue), withArgument(!valueName.isEmpty()) + { + if (!cmdLine.names().isEmpty()) { + parser.addOption(cmdLine); + } + } +}; + +const ConfigOption* const Config::ALLOW_VM_EDIT = new ConfigOption("", "allow-vm-edit", "allow-vm-edit", "", "", "Show edit checkbox for VMs/lectures where meta data allows editing"); +const ConfigOption* const Config::AUTOQUIT = new ConfigOption("", "autoquit", "autoquit", "seconds", "120", "Time after which vmchooser will quit if no user interaction is detected"); +const ConfigOption* const Config::BASEDIR = new ConfigOption("b", "base", "base", "path", "/mnt/vmstore", "Base directory where vm meta data is relative to"); +const ConfigOption* const Config::CONFIG = new ConfigOption("c", "config", "", "path", CONFIG_FILE_GLOBAL, "Path to global config file"); +const ConfigOption* const Config::DEBUG = new ConfigOption("D", "debug", "debug", "", "", "Enable debug mode"); +const ConfigOption* const Config::DEFAULT_SESSION = new ConfigOption("d", "default", "", "uuid", "", "Preselect session with given uuid or name"); +const ConfigOption* const Config::EXAM_MODE = new ConfigOption("", "exam-mode", "exam-mode", "", "", "Turn on exam mode: Limits options, forces PVS"); +const ConfigOption* const Config::FULLSCREEN = new ConfigOption("F", "fullscreen", "fullscreen", "", "", "Show vmchooser in fullscreen mode"); +const ConfigOption* const Config::INSECURE = new ConfigOption("k", "insecure", "insecure", "", "", "When using HTTPS, don't check server's certificate"); +const ConfigOption* const Config::LOCATIONS = new ConfigOption("l", "locations", "locations", "ids..", "", "Space separated list of location ids, for list request and location-mode"); +const ConfigOption* const Config::PVS = new ConfigOption("p", "pvs", "pvs", "", "", "Show 'join PVS' checkbox"); +const ConfigOption* const Config::PVS_CHECKED = new ConfigOption("", "pvs-checked", "pvs-checked", "", "", "PVS checkbox is selected by default"); +const ConfigOption* const Config::RUNSCRIPT = new ConfigOption("S", "runscript", "runscript", "path", RUN_VIRT_PATH, "Path to run-virt script"); +const ConfigOption* const Config::WINDOW_SIZE = new ConfigOption("s", "size", "size", "WxH", "640x480", "Size of window if not using fullscreen"); +const ConfigOption* const Config::DEFAULT_TAB = new ConfigOption("T", "tab", "tab", "tabno", "2", "Default tab to show, first tab being 0"); +const ConfigOption* const Config::THEME = new ConfigOption("t", "theme", "theme", "name", "", "Name of theme to load"); +const ConfigOption* const Config::URL_BASE = new ConfigOption("u", "url", "url", "url", "", "Base URL path to fetch resources from"); +const ConfigOption* const Config::URL_LIST = new ConfigOption("", "url-list", "url-list", "url", "", "Use this URL for the VM list instead of /list"); +const ConfigOption* const Config::URL_NEWS = new ConfigOption("", "url-news", "url-news", "url", "", "Use this URL for the news panel instead of /news"); +const ConfigOption* const Config::URL_HELP = new ConfigOption("", "url-help", "url-help", "url", "", "Use this URL for the help panel instead of /help"); +const ConfigOption* const Config::XSESSION_PATH = new ConfigOption("x", "xpath", "xpath", "path", VMCHOOSER_X_SESSIONS_PATH, "Path to xsession files"); +const ConfigOption* const Config::LOCATION_MODE = new ConfigOption("", "location-mode", "location-mode", "mode", "BUMP", "Whether to IGNORE locations, BUMP matching entries, or EXCLUSIVE-ly show only those matching the currently configured location"); +const ConfigOption* const Config::TEMPLATE_MODE = new ConfigOption("", "template-mode", "template-mode", "mode", "BUMP", "Whether to BUMP entries marked as template, or IGNORE the flag"); +const ConfigOption* const Config::AUTOSTART_UUID = new ConfigOption("", "start-uuid", "start-uuid", "uuid", "", "Immediately launch session with given uuid/name"); +const ConfigOption* const Config::NO_VTX = new ConfigOption("", "no-vtx", "no-vtx", "", "0", "Fade all VM sessions that would require VTX/SVM CPU capabilities"); + + +QString Config::get(const ConfigOption* const option) +{ + if (option == nullptr) + return QString(); + if (parser.isSet(option->cmdLine)) + return parser.value(option->cmdLine); + if (configFile != nullptr && !option->iniKey.isEmpty()) + return configFile->value(option->iniKey, option->defaultValue).toString(); + // TODO: CONFIG_FILE_USER is currently not supported, but unused anyways + return option->defaultValue; +} + +bool Config::isSet(const ConfigOption* const option) +{ + if (option == nullptr) + return false; + if (parser.isSet(option->cmdLine)) + return true; + if (configFile != nullptr && !option->iniKey.isEmpty()) + return !configFile->value(option->iniKey, option->defaultValue).isNull(); + return false; +} + +bool Config::init(const QCoreApplication& app, const ConfigOption* const configFileName) +{ + parser.addHelpOption(); + parser.addVersionOption(); + parser.process(app); + if (configFileName != nullptr && parser.isSet(configFileName->cmdLine)) { + QString file(parser.value(configFileName->cmdLine)); + if (!QFileInfo(file).exists()) + return false; + configFile = new QSettings(file, QSettings::IniFormat); + configFile->setIniCodec("UTF-8"); + } + return true; +} + diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..872836d --- /dev/null +++ b/src/config.h @@ -0,0 +1,46 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#include +#include + +struct ConfigOption; + +class Config +{ +public: + static const ConfigOption* const ALLOW_VM_EDIT; + static const ConfigOption* const AUTOQUIT; + static const ConfigOption* const BASEDIR; + static const ConfigOption* const CONFIG; + static const ConfigOption* const DEBUG; + static const ConfigOption* const DEFAULT_SESSION; + static const ConfigOption* const EXAM_MODE; + static const ConfigOption* const FULLSCREEN; + static const ConfigOption* const INSECURE; + static const ConfigOption* const LOCATIONS; + static const ConfigOption* const PVS; + static const ConfigOption* const PVS_CHECKED; + static const ConfigOption* const RUNSCRIPT; + static const ConfigOption* const WINDOW_SIZE; + static const ConfigOption* const DEFAULT_TAB; + static const ConfigOption* const THEME; + static const ConfigOption* const URL_BASE; + static const ConfigOption* const URL_LIST; + static const ConfigOption* const URL_NEWS; + static const ConfigOption* const URL_HELP; + static const ConfigOption* const XSESSION_PATH; + static const ConfigOption* const LOCATION_MODE; + static const ConfigOption* const TEMPLATE_MODE; + static const ConfigOption* const AUTOSTART_UUID; + static const ConfigOption* const NO_VTX; + + static bool init(const QCoreApplication& app, const ConfigOption* const configFile); + static QString get(const ConfigOption* const option); + static bool isSet(const ConfigOption* const option); + +private: + Config() {} +}; + +#endif // CONFIG_H diff --git a/src/dialog.cpp b/src/dialog.cpp index 10ebe22..8c02c9a 100644 --- a/src/dialog.cpp +++ b/src/dialog.cpp @@ -1,4 +1,5 @@ #include "dialog.h" +#include "config.h" #include #include @@ -24,17 +25,13 @@ static bool isProcessRunning(const QString &binary); -Dialog::Dialog(int defaultTab, bool examMode, QWidget *parent) +Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { model_[0] = new SessionTreeModel(parent); model_[1] = new SessionTreeModel(parent); model_[2] = new SessionTreeModel(parent); - if (defaultTab < 0 || defaultTab > TAB_COUNT) defaultTab = TAB_ALL_VMS; - defaultTab_ = defaultTab; - qDebug() << "Default tab: " << defaultTab; userInteracted_ = false; genericExpandedOnce_ = false; - examMode_ = examMode; autoQuit_ = g_autoQuitSeconds; ui->setupUi(this); @@ -71,11 +68,11 @@ Dialog::Dialog(int defaultTab, bool examMode, QWidget *parent) this, SLOT(treeView_selectionChanged(const QModelIndex&, const QModelIndex&))); */ - ui->PVS_checkbox->setVisible(g_pvsEnabled); - ui->PVS_checkbox->setChecked(g_pvsChecked); + ui->PVS_checkbox->setVisible(Config::isSet(Config::PVS)); + ui->PVS_checkbox->setChecked(Config::isSet(Config::PVS_CHECKED)); activeTab_ = -1; - if (examMode_) { + if (Config::isSet(Config::EXAM_MODE)) { ui->tabButtonLocal->setEnabled(false); this->onTabButtonChanged(TAB_ALL_VMS); /* modify the pvs checkbox */ @@ -88,7 +85,7 @@ Dialog::Dialog(int defaultTab, bool examMode, QWidget *parent) this->selectPreviousSession(); } - ui->chkAdminMode->setVisible(g_allowVmEdit); + ui->chkAdminMode->setVisible(Config::isSet(Config::ALLOW_VM_EDIT)); ui->chkAdminMode->setEnabled(false); ui->btnScreenSetup->setVisible(isProcessRunning("beamergui")); @@ -132,7 +129,7 @@ void Dialog::on_treeView_doubleClicked(const QModelIndex& index) return; // These two are up here in case run-virt cares... - if (g_pvsEnabled) { + if (Config::isSet(Config::PVS)) { if (ui->PVS_checkbox->isChecked()) { setenv("PVS_AUTO_CONNECT", "TRUE", 1); } else { @@ -217,7 +214,7 @@ void Dialog::addItems(const QList& entries, int tab) { if (tab < 0 || tab > 2) { return; } - if (examMode_ && tab == TAB_NATIVE) + if (Config::isSet(Config::EXAM_MODE) && tab == TAB_NATIVE) return; this->model_[tab]->addItems(entries); tabs_[tab]->setEnabled(this->model_[tab]->rowCount() != 0); @@ -346,7 +343,10 @@ void Dialog::selectPreviousSession() { qDebug() << "Not selecting previous session as user interacted or session was already selected"; return; } - QString lastSession = ChooserSettings::getSetting("last-session"); + QString lastSession = Config::get(Config::DEFAULT_SESSION); + if (lastSession.isEmpty()) { + lastSession = ChooserSettings::getSetting("last-session"); + } if (!lastSession.isEmpty()) { qDebug() << "Trying to select last session: " << lastSession; ui->treeView->clearSelection(); @@ -362,9 +362,10 @@ void Dialog::selectPreviousSession() { qDebug() << "Trying to select last tab " << lastTab; this->onTabButtonChanged(lastTab.toInt()); } else { - qDebug() << "Selected default tab " << defaultTab_; + int defaultTab = Config::get(Config::DEFAULT_TAB).toInt(); + qDebug() << "Selected default tab " << defaultTab; // Select default tab - this->onTabButtonChanged(defaultTab_); + this->onTabButtonChanged(defaultTab); } } @@ -377,12 +378,15 @@ void Dialog::setTheme() { QString backgroundColor, imageLeft, imageRight; QString themePathBase, themePathIni, themePathImgLeft, themePathImgRight; - if (g_themeName.isEmpty()) return; + if (Config::isSet(Config::THEME)) + return; - themePathBase = QString("%1/%2/").arg(VMCHOOSER_THEME_BASE).arg(g_themeName); - themePathIni = QString("%1%2.ini").arg(themePathBase).arg(g_themeName); + QString theme(Config::get(Config::THEME)); + themePathBase = QString("%1/%2/").arg(VMCHOOSER_THEME_BASE).arg(theme); + themePathIni = QString("%1%2.ini").arg(themePathBase).arg(theme); - if (!QFile::exists(themePathIni)) return; + if (!QFile::exists(themePathIni)) + return; QSettings themeSettings(themePathIni, QSettings::IniFormat); @@ -437,13 +441,15 @@ void Dialog::onCenterTimer() { * Download lecture list, news and help */ void Dialog::downloadData(const QString& locationIds) { - QUrl listUrl(g_urlList); + QUrl listUrl(Config::isSet(Config::URL_LIST) + ? Config::get(Config::URL_LIST) + : Config::get(Config::URL_BASE).append("/list")); QUrlQuery listQuery(listUrl); if (!locationIds.isEmpty()) { listQuery.addQueryItem("locations", locationIds); } - if (examMode_) { + if (Config::isSet(Config::EXAM_MODE)) { listQuery.addQueryItem("exams", "exam-mode"); } listUrl.setQuery(listQuery); @@ -509,7 +515,9 @@ void Dialog::downloadData(const QString& locationIds) { }); // // News - FileDownloader::download(QUrl(g_urlNews), [this](QNetworkReply::NetworkError err, const QByteArray& data) { + FileDownloader::download(QUrl(Config::isSet(Config::URL_NEWS) + ? Config::get(Config::URL_NEWS) + : Config::get(Config::URL_BASE).append("/news")), [this](QNetworkReply::NetworkError err, const QByteArray& data) { if (err != QNetworkReply::NoError) { if (g_debugMode) { qDebug() << "Could not get news. Try to get cached news."; @@ -580,7 +588,9 @@ void Dialog::downloadData(const QString& locationIds) { }); // // Download help - FileDownloader::download(QUrl(g_urlHelp), [this](QNetworkReply::NetworkError err, const QByteArray& data) { + FileDownloader::download(QUrl(Config::isSet(Config::URL_HELP) + ? Config::get(Config::URL_HELP) + : Config::get(Config::URL_BASE).append("/help")), [this](QNetworkReply::NetworkError err, const QByteArray& data) { if (err != QNetworkReply::NoError) { if (g_debugMode) { qDebug() << "Could not get help xml. Try to get cached help..."; @@ -673,7 +683,8 @@ void Dialog::treeView_selectionChanged(const QModelIndex& current, const QModelI ui->label_platform->setText(vs->getAttribute("virtualizer_name", "param")); ui->label_platform->setToolTip(vs->getAttribute("virtualizer_name", "param")); - ui->chkAdminMode->setEnabled(vs->canEdit() || g_allowVmEdit); + // TODO: This is a bug? vs->canEdit() seems completely pointless right now... + ui->chkAdminMode->setEnabled(vs->canEdit() || Config::isSet(Config::ALLOW_VM_EDIT)); if (vs->keywords().length() > 0) { description = "\n\nKeywords: "; @@ -709,7 +720,7 @@ void Dialog::on_tabButtonAllClasses_clicked() { } void Dialog::onTabButtonChanged(int tab) { - if (tab < 0 || tab > 2) { + if (tab < 0 || tab >= TAB_COUNT) { // no valid button return; } diff --git a/src/dialog.h b/src/dialog.h index c2d3959..0d74111 100644 --- a/src/dialog.h +++ b/src/dialog.h @@ -31,7 +31,7 @@ class Dialog : public QDialog { static const int TAB_COUNT = 3; public: // Public methods - explicit Dialog(int defaultTab = -1, bool examMode = false, QWidget *parent = nullptr); + explicit Dialog(QWidget *parent = nullptr); ~Dialog(); void addItems(const QList&, int tab); void addStatusString(const int status); @@ -57,11 +57,9 @@ class Dialog : public QDialog { QTimer *centerTimer_; QString autoStartEntry_; int activeTab_; - int defaultTab_; int autoQuit_; bool userInteracted_; bool genericExpandedOnce_; - bool examMode_; QString strings_[STR__MAX]; void onTabButtonChanged(int tab); void configClearButton(); diff --git a/src/globals.cpp b/src/globals.cpp index 427b4bb..c21598a 100644 --- a/src/globals.cpp +++ b/src/globals.cpp @@ -3,45 +3,24 @@ #include "globals.h" #include "session.h" -#define VMCHOOSER_SCRIPTS_PATH "/opt/openslx/scripts" -#define VMCHOOSER_X_SESSIONS_PATH "/usr/share/xsessions" - static const QString userPath(QDir::homePath() + "/.config/openslx"); -//QString binPath(QApplication::applicationDirPath()); -QString g_xSessionPath(VMCHOOSER_X_SESSIONS_PATH); -QString g_runVmScript(VMCHOOSER_SCRIPTS_PATH "/vmchooser-run_virt"); - const QString SESSION_START_SCRIPT(VMCHOOSER_SESSION_START_SCRIPT); -const QString CONFIG_FILE_GLOBAL("/opt/openslx/vmchooser/config/vmchooser.conf"); const QString CONFIG_FILE_USER(userPath + "/vmchooser.conf"); const QString CONFIG_FILE_XSESSIONS("/opt/openslx/vmchooser/config/xsessions.conf"); const QString PREVIOUS_SESSION_USER(userPath + "/vmchooser2.ini"); bool g_debugMode = false; -bool g_pvsEnabled = false; -bool g_pvsChecked = false; +bool g_fullscreen = false; int g_autoQuitSeconds = 0; -bool g_allowVmEdit = false; - -QString g_currentPoolName; -QString g_themeName; -QString g_vmBasePath; const QString TEMP_PATH_ICONS("/tmp/vmchooser2/icons/"); const QString TEMP_PATH_XML_LIST("/tmp/vmchooser2/vmchooser2.xml"); const QString TEMP_PATH_HELP("/tmp/vmchooser2/vmchooser2_help.xml"); const QString TEMP_PATH_NEWS("/tmp/vmchooser2/vmchooser2_news.xml"); -QString g_urlBase; -QString g_urlList; -QString g_urlNews; -QString g_urlHelp; - -bool g_fullscreen = false; - int g_templateHandling = TEMPLATES_IGNORE; int g_forLocationHandling = LOCATION_BUMP; diff --git a/src/globals.h b/src/globals.h index 860048e..81bf2f5 100644 --- a/src/globals.h +++ b/src/globals.h @@ -5,6 +5,10 @@ #define VMCHOOSER_SESSION_START_SCRIPT "/opt/openslx/vmchooser/sessionstart" #define VMCHOOSER_THEME_BASE "/opt/openslx/vmchooser/themes" +#define VMCHOOSER_X_SESSIONS_PATH "/usr/share/xsessions" +#define RUN_VIRT_PATH "/opt/openslx/scripts/vmchooser-run_virt" + +#define CONFIG_FILE_GLOBAL "/opt/openslx/vmchooser/config/vmchooser.conf" #define VMCHOOSER_DEFAULT_WIDTH 800 #define VMCHOOSER_DEFAULT_HEIGHT 600 @@ -14,40 +18,21 @@ class Session; extern bool g_debugMode; -extern bool g_pvsEnabled; -extern bool g_pvsChecked; +extern bool g_fullscreen; extern int g_autoQuitSeconds; -extern bool g_allowVmEdit; -extern QString g_xSessionPath; - -extern QString g_runVmScript; -extern QString printerScript; -extern QString scannerScript; // Script that is run before the xsession/vsession is started extern const QString SESSION_START_SCRIPT; -extern const QString CONFIG_FILE_GLOBAL; extern const QString CONFIG_FILE_USER; extern const QString CONFIG_FILE_XSESSIONS; extern const QString PREVIOUS_SESSION_USER; -extern QString g_currentPoolName; -extern QString g_themeName; -extern QString g_vmBasePath; - extern const QString TEMP_PATH_ICONS; extern const QString TEMP_PATH_XML_LIST; extern const QString TEMP_PATH_HELP; extern const QString TEMP_PATH_NEWS; -extern QString g_urlBase; -extern QString g_urlList; -extern QString g_urlNews; -extern QString g_urlHelp; - -extern bool g_fullscreen; - #define TEMPLATES_IGNORE (0) #define TEMPLATES_BUMP (1) extern int g_templateHandling; diff --git a/src/main.cpp b/src/main.cpp index 1da6f68..0e3229b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,7 +13,7 @@ #include #include -#include "command_line_options.h" +#include "config.h" #include "dialog.h" #include "globals.h" #include "xsession.h" @@ -25,221 +25,23 @@ int main(int argc, char *argv[]) { translator.load(":" + QLocale::system().name()); a.installTranslator(&translator); - CommandLineOptions cmdOptions(argc, argv); - - QString autostart_uuid(""); - - std::string usage( - a.translate("Console", "Usage: vmchooser [ OPTIONS ]\n\n" - " --allow-vm-edit show the 'edit this vm' checkbox\n" - " --autoquit [secs] automatically exit if no selection is made after secs seconds\n" - " -b --base base directory where VM images are accessible\n" - " -d, --default name of default session\n" - " -c, --config alternative config file\n" - " -l, --locations location id(s), space separated\n" - " --location-mode how to treat entries for this location (IGNORE, BUMP or EXCLUSIVE)\n" - " --exam-mode enable exam mode\n" - " -P, --pool one or more pool names to display (comma separated)\n" - " -f, --file direct boot .desktop file\n" - " -x, --xpath path of X Session .desktop files\n" - " -u, --url url of vmware .xml file\n" - " --url-list url of vms' list as .xml file\n" - " --url-news url of the news to display\n" - " --url-help url of the help to display\n" - " -s, --size window size x\n" - " -t, --theme theme\n" - " --template-mode how to treat template entries (IGNORE or BUMP)\n" - " -p, --pvs show pvs options\n" - " --pvs-checked check pvs box by default\n" - " -D, --debug print debug information\n" - " -v, --version print version and exit\n" - " -h, --help print usage information and exit\n" - " -S, --runscript change path to run-virt.sh\n" - " -T --tab default tab (0=xsession, 1=my vms, 2=all vms)\n" - " --no-vtx Host doesn't support VT-x/AMD-V (mark 64bit guests)\n" - " --start-uuid start lecture with the given uuid\n" - "\nFILE can be a vmware .xml or an X .desktop file\n").toUtf8().data()); - - if (cmdOptions.contains("error")) { - std::cerr << usage; - return EXIT_FAILURE; - } - - if (cmdOptions.contains("usage")) { - std::cout << usage; - return EXIT_SUCCESS; - } - - if (cmdOptions.contains("version")) { - std::cout << "vmchooser " << VMCHOOSER_VERSION << std::endl; - return EXIT_SUCCESS; - } - - if (cmdOptions.contains("uuid")) { - autostart_uuid = cmdOptions.value("uuid"); + if (!Config::init(a, Config::CONFIG)) { + qDebug() << "Error initializing config. Invalid --config passed?"; + return 1; } - if (cmdOptions.contains("file")) { - QString file(cmdOptions.value("file")); - - if (file.endsWith(".desktop")) { - XSession s; - if (s.init(file) && s.run()) { - return EXIT_SUCCESS; - } - std::cerr - << a.translate("Console", - "vmchooser: failed to run session").toUtf8().constData() - << std::endl; - return EXIT_FAILURE; - } else { - std::cerr - << a.translate("Console", "vmchooser: invalid session file").toUtf8().constData() - << std::endl; - return EXIT_FAILURE; - } - } - if (cmdOptions.contains("insecure")) { + if (Config::isSet(Config::INSECURE)) { QSslConfiguration sslConf = QSslConfiguration::defaultConfiguration(); sslConf.setPeerVerifyMode(QSslSocket::VerifyNone); QSslConfiguration::setDefaultConfiguration(sslConf); } - // read configuration file: - // file supplied as command line option or - // user vmchooser.conf or - // global vmchooser.conf - QString confFile; - if (cmdOptions.contains("config")) { - if (QFileInfo(cmdOptions.value("config")).exists()) { - confFile = cmdOptions.value("config"); - } else { - std::cerr << a.translate("Console", "Requested --config not found: ").toUtf8().constData() << cmdOptions.value("config").toUtf8().constData() << std::endl; - } - } - if (confFile.isEmpty() && QFileInfo(CONFIG_FILE_USER).exists()) { - confFile = CONFIG_FILE_USER; - std::cerr << a.translate("Console", "Using user specific config: ").toUtf8().constData() << CONFIG_FILE_USER.toUtf8().constData() << std::endl; - } - if (confFile.isEmpty() && QFileInfo(CONFIG_FILE_GLOBAL).exists()) { - confFile = CONFIG_FILE_GLOBAL; - std::cerr << a.translate("Console", "Using global config: ").toUtf8().constData() << CONFIG_FILE_GLOBAL.toUtf8().constData() << std::endl; - } - if (confFile.isEmpty()) { - std::cerr << a.translate("Console", "No config file found or given").toUtf8().constData() << std::endl; - } - - // TODO: This is the system wide settings, give proper name - QSettings settings(confFile, QSettings::IniFormat); - settings.setIniCodec("UTF-8"); - - if (ChooserSettings::getSetting("last-session").isEmpty()) { - QString defaultSession; - if (cmdOptions.contains("default")) { - defaultSession = cmdOptions.value("default"); - } else if (settings.contains("default")) { - defaultSession = settings.value("default").toString(); - } - ChooserSettings::setSetting("last-session", defaultSession); - } - - if (cmdOptions.contains("xpath")) { - g_xSessionPath = cmdOptions.value("xpath"); - } else if (settings.contains("xpath")) { - g_xSessionPath = settings.value("xpath").toString(); - } // else keep default path - - // Change the runVmScript path - if (cmdOptions.contains("runscript")) { - g_runVmScript = cmdOptions.value("runscript"); - } else if (settings.contains("runscript")) { - g_runVmScript = settings.value("runscript").toString(); - } - - - if (cmdOptions.contains("url")) { - g_urlBase = cmdOptions.value("url"); - } else if (settings.contains("url")) { - g_urlBase = settings.value("url").toString(); - } - - if (!g_urlBase.isNull() && !g_urlBase.isEmpty()) { - if (!g_urlBase.endsWith("/")) { - g_urlBase += "/"; - } - } - // parse urls for resources: list, news, help - QMap resources; - resources["list"] = &g_urlList; - resources["news"] = &g_urlNews; - resources["help"] = &g_urlHelp; - QMap::const_iterator r = resources.constBegin(); - QString cur; - while (r != resources.constEnd()) { - cur = "url-" + r.key(); - if (cmdOptions.contains(cur)) { - *r.value() = cmdOptions.value(cur); - } else { - if (!g_urlBase.isNull()) { - // if not explictly specified, use the old scheme - *r.value() = g_urlBase + r.key(); - } - } - r++; - } - - QString size; - int width = VMCHOOSER_DEFAULT_WIDTH, height = VMCHOOSER_DEFAULT_HEIGHT; - if (cmdOptions.contains("fullscreen")) { - size = "fullscreen"; - } else if (settings.contains("fullscreen")) { - size = "fullscreen"; - } else if (cmdOptions.contains("size")) { - size = cmdOptions.value("size"); - } else if (settings.contains("size")) { - size = settings.value("size").toString(); - } - - if (size != "fullscreen") { - QRegExp rx("^(\\d+)x(\\d+)$"); - if (rx.indexIn(size) != -1) { - QStringList list = rx.capturedTexts(); - width = list.value(1).toInt(); - height = list.value(2).toInt(); - } else if (!size.isEmpty()) { - std::cerr - << a.translate("Console", "vmchooser: invalid size argument").toUtf8().data() - << std::endl; - return EXIT_FAILURE; - } - } - - if (cmdOptions.contains("pool")) { - g_currentPoolName = cmdOptions.value("pool"); - } else if (settings.contains("pool")) { - g_currentPoolName = settings.value("pool").toString(); - } - - if (cmdOptions.contains("theme")) { - g_themeName = cmdOptions.value("theme"); - } else if (settings.contains("theme")) { - g_themeName = settings.value("theme").toString(); - } - - if (cmdOptions.contains("debugMode")) { + if (Config::isSet(Config::DEBUG)) { g_debugMode = true; } - if (cmdOptions.contains("base")) { - g_vmBasePath = cmdOptions.value("base"); - } else if (settings.contains("base")) { - g_vmBasePath = settings.value("base").toString(); - } else if (settings.contains("path")) { // Compatibility to v1.0 - g_vmBasePath = settings.value("path").toString(); - } - - if (cmdOptions.contains("location-mode")) { - QString mode = cmdOptions.value("location-mode"); + if (Config::isSet(Config::LOCATION_MODE)) { + QString mode = Config::get(Config::LOCATION_MODE); if (mode == "IGNORE") { g_forLocationHandling = LOCATION_IGNORE; } else if (mode == "BUMP") { @@ -253,12 +55,12 @@ int main(int argc, char *argv[]) { } } - if (cmdOptions.contains("template-mode")) { - QString mode = cmdOptions.value("template-mode"); + if (Config::isSet(Config::TEMPLATE_MODE)) { + QString mode = Config::get(Config::TEMPLATE_MODE); if (mode == "IGNORE") { - g_templateHandling = LOCATION_IGNORE; + g_templateHandling = TEMPLATES_IGNORE; } else if (mode == "BUMP") { - g_templateHandling = LOCATION_BUMP; + g_templateHandling = TEMPLATES_BUMP; } else { qDebug() << "Invalid template mode: " << mode; QMessageBox::critical(nullptr, "Error", "Invalid template mode: " + mode); @@ -266,55 +68,47 @@ int main(int argc, char *argv[]) { } } - int defaultTab = -1; - if (cmdOptions.contains("tab")) { - defaultTab = cmdOptions.value("tab").toInt(); - } - - QString locationIds; - if (cmdOptions.contains("locations")) { - locationIds = cmdOptions.value("locations"); - } - - if (cmdOptions.contains("no-vtx")) { - g_noVtx = true; - } + g_noVtx = Config::isSet(Config::NO_VTX); - if (cmdOptions.contains("pvs")) { - g_pvsEnabled = true; - } - if (cmdOptions.contains("pvs-checked")) { - g_pvsChecked = true; - } - - if (cmdOptions.contains("autoquit")) { + if (Config::isSet(Config::AUTOQUIT)) { bool ok = false; - g_autoQuitSeconds = cmdOptions.value("autoquit").toInt(&ok, 10); + g_autoQuitSeconds = Config::get(Config::AUTOQUIT).toInt(&ok, 10); if (!ok) { g_autoQuitSeconds = 0; } } - g_allowVmEdit = cmdOptions.contains("allow-vm-edit"); - /* read session files */ - QList xsessions(XSession::readSessions(g_xSessionPath)); + QList xsessions(XSession::readSessions(Config::get(Config::XSESSION_PATH))); - Dialog w(defaultTab, cmdOptions.contains("exam-mode")); - - w.downloadData(locationIds); - - w.setTheme(); - - w.setWindowFlags(Qt::FramelessWindowHint); + Dialog w; QRect desktopRect = QApplication::desktop()->availableGeometry(&w); - if (size == "fullscreen") { + int width = VMCHOOSER_DEFAULT_WIDTH, height = VMCHOOSER_DEFAULT_HEIGHT; + if (Config::isSet(Config::FULLSCREEN) || Config::get(Config::WINDOW_SIZE) == QLatin1String("fullscreen")) { width = desktopRect.width(); height = desktopRect.height(); g_fullscreen = true; + } else { + QString size(Config::get(Config::WINDOW_SIZE)); + if (!size.isEmpty()) { + QRegExp rx("^(\\d+)x(\\d+)$"); + if (rx.indexIn(size) != -1) { + QStringList list = rx.capturedTexts(); + width = list.value(1).toInt(); + height = list.value(2).toInt(); + } else { + std::cerr + << a.translate("Console", "vmchooser: invalid size argument").toUtf8().data() + << std::endl; + return EXIT_FAILURE; + } + } } + w.downloadData(Config::get(Config::LOCATIONS)); + w.setTheme(); + w.setWindowFlags(Qt::FramelessWindowHint); w.resize(width, height); if (xsessions.size()) { @@ -324,9 +118,9 @@ int main(int argc, char *argv[]) { w.show(); - if (autostart_uuid != "") { + if (Config::isSet(Config::AUTOSTART_UUID)) { qDebug() << "using startSession() from main.cpp"; - w.startSession(autostart_uuid); + w.startSession(Config::get(Config::AUTOSTART_UUID)); } diff --git a/src/vsession.cpp b/src/vsession.cpp index e35c1af..a4e5a7b 100644 --- a/src/vsession.cpp +++ b/src/vsession.cpp @@ -1,3 +1,5 @@ +#include "config.h" + #include #include #include @@ -107,7 +109,7 @@ QString VSession::toXml() const { .toElement(); if (QFileInfo(image).isRelative()) { // make path to image absolute - path.setAttribute("param", g_vmBasePath + "/" + image); + path.setAttribute("param", Config::get(Config::BASEDIR) + "/" + image); } else { path.setAttribute("param", image); } @@ -205,15 +207,7 @@ bool VSession::isActive() const { return false; } } - // Filtering by pool name - if (!g_currentPoolName.isEmpty()) { - QStringList pools = getAttribute("pools").split("\\s*,\\s*"); - if (!pools.isEmpty() && !pools.contains(g_currentPoolName)) { - // pools does not contain pool - if (g_debugMode) qDebug() << "'" << shortDescription() << "' not active. Reason: '" << g_currentPoolName << "' is not part of active pool list (" << pools << ")"; - return false; - } - } + // Filter by LDAP data if (!UserLdapData::isEmpty()) { QDomElement el(eintrag_.namedItem("filters").firstChildElement("filter")); @@ -286,7 +280,7 @@ bool VSession::run() const { tmpfile.close(); QObject::connect(&_process, SIGNAL(finished(int, QProcess::ExitStatus)), QApplication::instance(), SLOT(quit())); - _process.start(g_runVmScript, QStringList(tmpFileName)); + _process.start(Config::get(Config::RUNSCRIPT), QStringList(tmpFileName)); _process.waitForStarted(10); if (_process.state() == QProcess::Starting || _process.state() == QProcess::Running) return true; -- cgit v1.2.3-55-g7522