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.
This commit is contained in:
parent
bf851605fb
commit
d81d353940
8 changed files with 243 additions and 83 deletions
|
@ -150,9 +150,6 @@
|
|||
<property name="bottomMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QListView" name="aircraftList"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
|
@ -234,6 +231,9 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListView" name="aircraftList"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="locationTab">
|
||||
|
@ -486,13 +486,20 @@
|
|||
<item row="6" column="0">
|
||||
<widget class="QPushButton" name="pathsButton">
|
||||
<property name="text">
|
||||
<string>Configure add-on aircraft and scenery</string>
|
||||
<string>Configure add-on aircraft and scenery…</string>
|
||||
</property>
|
||||
<property name="startupOnly" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QPushButton" name="changeRootButton">
|
||||
<property name="text">
|
||||
<string>Change data files location…</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include <QApplication>
|
||||
#include <QSpinBox>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QProcess>
|
||||
|
||||
// Simgear
|
||||
#include <simgear/timing/timestamp.hxx>
|
||||
|
@ -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") {
|
||||
|
|
|
@ -82,7 +82,7 @@ private slots:
|
|||
void onSubsytemIdleTimeout();
|
||||
|
||||
void onEditPaths();
|
||||
|
||||
void onChangeRoot();
|
||||
|
||||
void onAircraftInstalledCompleted(QModelIndex index);
|
||||
void onAircraftInstallFailed(QModelIndex index, QString errorMessage);
|
||||
|
|
|
@ -38,10 +38,12 @@
|
|||
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_init.hxx>
|
||||
#include <Main/options.hxx>
|
||||
#include <Include/version.h>
|
||||
|
||||
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;
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <QScopedPointer>
|
||||
#include <QString>
|
||||
|
||||
#include <string>
|
||||
|
||||
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<Ui::SetupRootDialog> m_ui;
|
||||
QString m_browsedPath;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -9,14 +9,27 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>618</width>
|
||||
<height>338</height>
|
||||
<width>627</width>
|
||||
<height>392</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Setup required data files</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1">
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1,0">
|
||||
<item row="7" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="2">
|
||||
<widget class="QLabel" name="bigIcon">
|
||||
<property name="minimumSize">
|
||||
|
@ -30,24 +43,38 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="8" column="1" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QLabel" name="versionLabel">
|
||||
<property name="text">
|
||||
<string>FlightGear version 3.4.5</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2" alignment="Qt::AlignTop">
|
||||
<widget class="QPushButton" name="useDefaultsButton">
|
||||
<property name="text">
|
||||
<string>Use built-in data files</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2" alignment="Qt::AlignTop">
|
||||
<widget class="QPushButton" name="downloadButton">
|
||||
<property name="text">
|
||||
<string>Download </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>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.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QLabel" name="promptText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
|
@ -66,7 +93,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="2" column="2" alignment="Qt::AlignTop">
|
||||
<widget class="QPushButton" name="browseButton">
|
||||
<property name="text">
|
||||
<string>Choose folder...</string>
|
||||
|
@ -76,35 +103,35 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="versionLabel">
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="useDefaultLabel">
|
||||
<property name="text">
|
||||
<string>FlightGear version 3.4.5</string>
|
||||
<string>To use the files included with this copy of FlightGear, click this button</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>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.</string>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel</set>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>To browse to a downloaded copy of the files on your computer, click this button</string>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</spacer>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<OptionsPrivate> p;
|
||||
|
|
Loading…
Add table
Reference in a new issue