1
0
Fork 0

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:
James Turner 2016-01-17 13:10:22 -06:00
parent bf851605fb
commit d81d353940
8 changed files with 243 additions and 83 deletions

View file

@ -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>

View file

@ -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") {

View file

@ -82,7 +82,7 @@ private slots:
void onSubsytemIdleTimeout();
void onEditPaths();
void onChangeRoot();
void onAircraftInstalledCompleted(QModelIndex index);
void onAircraftInstallFailed(QModelIndex index, QString errorMessage);

View file

@ -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;

View file

@ -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;
};
};

View file

@ -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>

View file

@ -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

View file

@ -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;