From d81d3539402f2e5672dba26ec98008f7034179fd Mon Sep 17 00:00:00 2001 From: James Turner Date: Sun, 17 Jan 2016 13:10:22 -0600 Subject: [PATCH] Improved fg-root control from the Qt Launcher - add a button to the main dialog, explaining how to adjust the fg-root path via the GUI - tweak the GUI flow to support explicitly changing the path even when the default path is acceptable. --- src/GUI/Launcher.ui | 15 ++++-- src/GUI/QtLauncher.cxx | 70 +++++++++++++++++++++++--- src/GUI/QtLauncher_private.hxx | 2 +- src/GUI/SetupRootDialog.cxx | 82 +++++++++++++++++++++++++----- src/GUI/SetupRootDialog.hxx | 26 +++++++--- src/GUI/SetupRootDialog.ui | 91 ++++++++++++++++++++++------------ src/Main/options.cxx | 29 +++++------ src/Main/options.hxx | 5 +- 8 files changed, 240 insertions(+), 80 deletions(-) diff --git a/src/GUI/Launcher.ui b/src/GUI/Launcher.ui index b10749fd2..3ba4e55a5 100644 --- a/src/GUI/Launcher.ui +++ b/src/GUI/Launcher.ui @@ -150,9 +150,6 @@ 4 - - - @@ -234,6 +231,9 @@ + + + @@ -486,13 +486,20 @@ - Configure add-on aircraft and scenery + Configure add-on aircraft and scenery… true + + + + Change data files location… + + + diff --git a/src/GUI/QtLauncher.cxx b/src/GUI/QtLauncher.cxx index 367527c34..f8aad70ad 100644 --- a/src/GUI/QtLauncher.cxx +++ b/src/GUI/QtLauncher.cxx @@ -44,6 +44,7 @@ #include #include #include +#include // Simgear #include @@ -353,13 +354,14 @@ void initApp(int& argc, char** argv) flightgear::WindowBuilder::setPoseAsStandaloneApp(false); Qt::KeyboardModifiers mods = app->queryKeyboardModifiers(); - if (mods & Qt::AltModifier) { - qWarning() << "Alt pressed during launch"; + if (mods & (Qt::AltModifier | Qt::ShiftModifier)) { + qWarning() << "Alt/shift pressed during launch"; // wipe out our settings QSettings settings; settings.clear(); + settings.setValue("fg-root", "!ask"); Options::sharedInstance()->addOption("restore-defaults", ""); } @@ -418,10 +420,12 @@ bool runLauncherDialog() loadNaturalEarthData(); QtLauncher dlg; - dlg.exec(); + dlg.show(); - if (dlg.result() != QDialog::Accepted) { - return false; + int appResult = qApp->exec(); + qDebug() << "App result:" << appResult; + if (appResult < 0) { + return false; // quit } // don't set scenery paths twice @@ -487,6 +491,8 @@ QtLauncher::QtLauncher() : connect(m_ui->runButton, SIGNAL(clicked()), this, SLOT(onRun())); connect(m_ui->quitButton, SIGNAL(clicked()), this, SLOT(onQuit())); + connect(m_ui->changeRootButton, SIGNAL(clicked()), this, SLOT(onChangeRoot())); + connect(m_ui->aircraftHistory, &QPushButton::clicked, this, &QtLauncher::onPopupAircraftHistory); @@ -713,8 +719,6 @@ void QtLauncher::setEnableDisableOptionFromCheckbox(QCheckBox* cbox, QString nam void QtLauncher::onRun() { - accept(); - flightgear::Options* opt = flightgear::Options::sharedInstance(); setEnableDisableOptionFromCheckbox(m_ui->terrasyncCheck, "terrasync"); setEnableDisableOptionFromCheckbox(m_ui->fetchRealWxrCheckbox, "real-weather-fetch"); @@ -820,6 +824,8 @@ void QtLauncher::onRun() } saveSettings(); + + qApp->exit(0); } @@ -864,7 +870,7 @@ void QtLauncher::onApply() void QtLauncher::onQuit() { - reject(); + qApp->exit(-1); } void QtLauncher::onToggleTerrasync(bool enabled) @@ -1126,6 +1132,54 @@ void QtLauncher::onEditPaths() } } +void QtLauncher::onChangeRoot() +{ + QMessageBox mbox(this); + mbox.setText(tr("Change the data files location used by FlightGear?")); + mbox.setInformativeText(tr("FlightGear cannot work without its data files. " + "(Also called the base package) " + "To change which files are used, quit FlightGear and open it again, " + "while holding down the 'shift' key, and you will be able to choose a " + "different data files location, or restore the default setting.")); + QPushButton* quitButton = mbox.addButton(tr("Quit FlightGear now"), QMessageBox::YesRole); + mbox.addButton(QMessageBox::Cancel); + mbox.setDefaultButton(QMessageBox::Cancel); + mbox.setIconPixmap(QPixmap(":/app-icon-large")); + + mbox.exec(); + if (mbox.clickedButton() != quitButton) { + return; + } + + // following code doesn't work reliably, so we take the simpler + // option of asking the user to re-launch us while holding down + // the hot-key (shift) +#if 0 + { + QSettings settings; + // set the option to the magic marker value + settings.setValue("fg-root", "!ask"); + } // scope the ensure settings are written nicel + + // Spawn a new instance of myApplication: + QProcess proc; +#if defined(Q_OS_MAC) + QStringList args; + + QDir dir(qApp->applicationDirPath()); // returns the 'MacOS' dir + dir.cdUp(); // up to 'contents' dir + dir.cdUp(); // up to .app dir + args << dir.absolutePath(); + proc.startDetached("open", args); +#else + proc.startDetached(qApp->applicationFilePath()); +#endif +#endif + + qDebug() << "doing app exit"; + qApp->exit(-1); +} + simgear::pkg::PackageRef QtLauncher::packageForAircraftURI(QUrl uri) const { if (uri.scheme() != "package") { diff --git a/src/GUI/QtLauncher_private.hxx b/src/GUI/QtLauncher_private.hxx index 104c8ddb5..f5eea7ade 100644 --- a/src/GUI/QtLauncher_private.hxx +++ b/src/GUI/QtLauncher_private.hxx @@ -82,7 +82,7 @@ private slots: void onSubsytemIdleTimeout(); void onEditPaths(); - + void onChangeRoot(); void onAircraftInstalledCompleted(QModelIndex index); void onAircraftInstallFailed(QModelIndex index, QString errorMessage); diff --git a/src/GUI/SetupRootDialog.cxx b/src/GUI/SetupRootDialog.cxx index 707bc0962..93999f476 100644 --- a/src/GUI/SetupRootDialog.cxx +++ b/src/GUI/SetupRootDialog.cxx @@ -38,10 +38,12 @@ #include
#include
+#include
#include -SetupRootDialog::SetupRootDialog(bool usedDefaultPath) : - QDialog() +SetupRootDialog::SetupRootDialog(PromptState prompt) : + QDialog(), + m_promptState(prompt) { m_ui.reset(new Ui::SetupRootDialog); m_ui->setupUi(this); @@ -52,28 +54,63 @@ SetupRootDialog::SetupRootDialog(bool usedDefaultPath) : this, &SetupRootDialog::onDownload); connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + connect(m_ui->useDefaultsButton, &QPushButton::clicked, + this, &SetupRootDialog::onUseDefaults); - m_promptState = usedDefaultPath ? DefaultPathCheckFailed : ExplicitPathCheckFailed; - std::string ver = fgBasePackageVersion(globals->get_fg_root()); - if (!ver.empty()) { - Q_ASSERT(ver != FLIGHTGEAR_VERSION); // otherwise what are we doing in here?! - m_promptState = VersionCheckFailed; - } + // decide if the 'use defaults' button should be enabled or not + bool ok = defaultRootAcceptable(); + m_ui->useDefaultsButton->setEnabled(ok); + m_ui->useDefaultLabel->setEnabled(ok); m_ui->versionLabel->setText(tr("FlightGear version %1").arg(FLIGHTGEAR_VERSION)); m_ui->bigIcon->setPixmap(QPixmap(":/app-icon-large")); updatePromptText(); } -bool SetupRootDialog::restoreUserSelectedRoot() +bool SetupRootDialog::runDialog(bool usingDefaultRoot) +{ + SetupRootDialog::PromptState prompt = + usingDefaultRoot ? DefaultPathCheckFailed : ExplicitPathCheckFailed; + return runDialog(prompt); +} + +bool SetupRootDialog::runDialog(PromptState prompt) +{ + SetupRootDialog dlg(prompt); + dlg.exec(); + if (dlg.result() != QDialog::Accepted) { + exit(-1); + } + + return true; +} + +std::string SetupRootDialog::restoreUserSelectedRoot() { QSettings settings; QString path = settings.value("fg-root").toString(); + if (path == "!ask") { + bool ok = runDialog(ManualChoiceRequested); + Q_ASSERT(ok); + // run dialog either exit()s or sets fg_root, so this + // behaviour is safe and correct. + return globals->get_fg_root(); + } + + if (path.isEmpty()) { + return std::string(); // use the default path + } + if (validatePath(path) && validateVersion(path)) { - globals->set_fg_root(path.toStdString()); - return true; + return path.toStdString(); } else { - return false; + // we have an existing path but it's invalid. Let's ask the + // user what they want + bool ok = runDialog(VersionCheckFailed); + Q_ASSERT(ok); + // run dialog either exit()s or sets fg_root, so this + // behaviour is safe and correct. + return globals->get_fg_root(); } } @@ -109,6 +146,13 @@ bool SetupRootDialog::validateVersion(QString path) return (ver == FLIGHTGEAR_VERSION); } +bool SetupRootDialog::defaultRootAcceptable() +{ + std::string r = flightgear::Options::sharedInstance()->platformDefaultRoot(); + QString defaultRoot = QString::fromStdString(r); + return validatePath(defaultRoot) && validateVersion(defaultRoot); +} + SetupRootDialog::~SetupRootDialog() { @@ -148,6 +192,16 @@ void SetupRootDialog::onDownload() QDesktopServices::openUrl(downloadUrl); } +void SetupRootDialog::onUseDefaults() +{ + std::string r = flightgear::Options::sharedInstance()->platformDefaultRoot(); + m_browsedPath = QString::fromStdString(r); + globals->set_fg_root(r); + QSettings settings; + settings.remove("fg-root"); // remove any setting + accept(); +} + void SetupRootDialog::updatePromptText() { QString t; @@ -171,6 +225,10 @@ void SetupRootDialog::updatePromptText() break; } + case ManualChoiceRequested: + t = tr("Please select or download a copy of the FlightGear data files."); + break; + case ChoseInvalidLocation: t = tr("The choosen location (%1) does not appear to contain FlightGear data files. Please try another location.").arg(m_browsedPath); break; diff --git a/src/GUI/SetupRootDialog.hxx b/src/GUI/SetupRootDialog.hxx index 9d01b7247..2a1d4eae3 100644 --- a/src/GUI/SetupRootDialog.hxx +++ b/src/GUI/SetupRootDialog.hxx @@ -22,6 +22,8 @@ #include #include +#include + namespace Ui { class SetupRootDialog; @@ -31,33 +33,43 @@ class SetupRootDialog : public QDialog { Q_OBJECT public: - SetupRootDialog(bool usedDefaultPath); ~SetupRootDialog(); - static bool restoreUserSelectedRoot(); + static bool runDialog(bool usingDefaultRoot); + + static std::string restoreUserSelectedRoot(); private slots: void onBrowse(); void onDownload(); + void onUseDefaults(); + void updatePromptText(); private: - - static bool validatePath(QString path); - static bool validateVersion(QString path); - enum PromptState { DefaultPathCheckFailed, ExplicitPathCheckFailed, VersionCheckFailed, + ManualChoiceRequested, ChoseInvalidLocation, ChoseInvalidVersion }; + + SetupRootDialog(PromptState prompt); + + static bool runDialog(PromptState prompt); + + static bool validatePath(QString path); + static bool validateVersion(QString path); + + static bool defaultRootAcceptable(); + PromptState m_promptState; QScopedPointer m_ui; QString m_browsedPath; -}; \ No newline at end of file +}; diff --git a/src/GUI/SetupRootDialog.ui b/src/GUI/SetupRootDialog.ui index 572e570cb..9e8465a56 100644 --- a/src/GUI/SetupRootDialog.ui +++ b/src/GUI/SetupRootDialog.ui @@ -9,14 +9,27 @@ 0 0 - 618 - 338 + 627 + 392 Setup required data files - + + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -30,24 +43,38 @@ - - + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel + + + + + - Download + FlightGear version 3.4.5 - - + + - To download a compressed archive of the files, click the 'Download' button. Once the download is complete, extract the files to a suitabe location and choose the folder using the button above. + Use built-in data files - - true + + + + + + Download - + @@ -66,7 +93,7 @@ - + Choose folder... @@ -76,35 +103,35 @@ - - + + - FlightGear version 3.4.5 + To use the files included with this copy of FlightGear, click this button + + + true - - - - Qt::Horizontal + + + + To download a compressed archive of the files, click the 'Download' button. Once the download is complete, extract the files to a suitabe location and choose the folder using the button above. - - QDialogButtonBox::Cancel + + true - - - - Qt::Vertical + + + + To browse to a downloaded copy of the files on your computer, click this button - - - 20 - 40 - + + true - + diff --git a/src/Main/options.cxx b/src/Main/options.cxx index 9cfbb6c9d..2c01e0203 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -2493,19 +2493,26 @@ string Options::platformDefaultRoot() const void Options::setupRoot(int argc, char **argv) { - string root; + string root; bool usingDefaultRoot = false; +#if defined(HAVE_QT) + flightgear::initApp(argc, argv); + root = SetupRootDialog::restoreUserSelectedRoot(); +#endif + if (isOptionSet("fg-root")) { root = valueForOption("fg-root"); // easy! } else { + // Next check if fg-root is set as an env variable char *envp = ::getenv( "FG_ROOT" ); if ( envp != NULL ) { root = envp; - } else { +// if we didn't restore a path from the Qt launcher, use the default here + } else if (root.empty()) { usingDefaultRoot = true; - root = platformDefaultRoot(); + root = platformDefaultRoot(); } } @@ -2515,18 +2522,12 @@ void Options::setupRoot(int argc, char **argv) string base_version = fgBasePackageVersion(root); #if defined(HAVE_QT) + // note we never end up here is resotring a user selected root via + // the Qt GUI, since that code pre-validates the path. But if we're using + // a command-line, env-var or default root this check can fail and + // we still want to use the GUI in that case if (base_version != required_version) { - flightgear::initApp(argc, argv); - if (SetupRootDialog::restoreUserSelectedRoot()) { - SG_LOG(SG_GENERAL, SG_INFO, "restored user selected fg_root = " << globals->get_fg_root() ); - return; - } - - SetupRootDialog dlg(usingDefaultRoot); - dlg.exec(); - if (dlg.result() != QDialog::Accepted) { - exit(-1); - } + SetupRootDialog::runDialog(usingDefaultRoot); } #else // validate it diff --git a/src/Main/options.hxx b/src/Main/options.hxx index a74e1a15b..f6f23b0d4 100644 --- a/src/Main/options.hxx +++ b/src/Main/options.hxx @@ -134,6 +134,8 @@ public: * Used by early startup code before Options object is created */ static bool checkForArg(int argc, char* argv[], const char* arg); + + std::string platformDefaultRoot() const; private: void showUsage() const; @@ -148,8 +150,7 @@ private: * to help the user our (finding a base package), and hence need to init Qt. */ void setupRoot(int argc, char **argv); - - std::string platformDefaultRoot() const; + class OptionsPrivate; std::auto_ptr p; -- 2.39.5