<property name="bottomMargin">
<number>4</number>
</property>
- <item>
- <widget class="QListView" name="aircraftList"/>
- </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
</item>
</layout>
</item>
+ <item>
+ <widget class="QListView" name="aircraftList"/>
+ </item>
</layout>
</widget>
<widget class="QWidget" name="locationTab">
<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>
#include <QApplication>
#include <QSpinBox>
#include <QDoubleSpinBox>
+#include <QProcess>
// Simgear
#include <simgear/timing/timestamp.hxx>
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", "");
}
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
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);
void QtLauncher::onRun()
{
- accept();
-
flightgear::Options* opt = flightgear::Options::sharedInstance();
setEnableDisableOptionFromCheckbox(m_ui->terrasyncCheck, "terrasync");
setEnableDisableOptionFromCheckbox(m_ui->fetchRealWxrCheckbox, "real-weather-fetch");
}
saveSettings();
+
+ qApp->exit(0);
}
void QtLauncher::onQuit()
{
- reject();
+ qApp->exit(-1);
}
void QtLauncher::onToggleTerrasync(bool enabled)
}
}
+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") {
void onSubsytemIdleTimeout();
void onEditPaths();
-
+ void onChangeRoot();
void onAircraftInstalledCompleted(QModelIndex index);
void onAircraftInstallFailed(QModelIndex index, QString errorMessage);
#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);
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();
}
}
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()
{
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;
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;
#include <QScopedPointer>
#include <QString>
+#include <string>
+
namespace Ui
{
class SetupRootDialog;
{
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;
-};
\ No newline at end of file
+};
<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">
</property>
</widget>
</item>
- <item row="4" column="1">
- <widget class="QPushButton" name="downloadButton">
+ <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>Download </string>
+ <string>FlightGear version 3.4.5</string>
</property>
</widget>
</item>
- <item row="3" column="1">
- <widget class="QLabel" name="label_2">
+ <item row="3" column="2" alignment="Qt::AlignTop">
+ <widget class="QPushButton" name="useDefaultsButton">
<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>
+ <string>Use built-in data files</string>
</property>
- <property name="wordWrap">
- <bool>true</bool>
+ </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="1" column="1">
+ <item row="1" column="1" colspan="2">
<widget class="QLabel" name="promptText">
<property name="minimumSize">
<size>
</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>
</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>
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();
}
}
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
* 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;
* 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;