- feedback on wording greatly appreciated.
- needed to make nightly builds usable without bundled data.
option(SYSTEM_GSM "Set to ON to build IAXClient with the system's GSM library" ${SYSTEM_GSM_DEFAULT})
option(SYSTEM_FLITE "Set to ON to build Flightgear with the system's Flite library" ${SYSTEM_FLITE_DEFAULT})
option(SYSTEM_HTS_ENGINE "Set to ON to build Flightgear with the system's HTS Engine library" ${SYSTEM_HTS_ENGINE_DEFAULT})
+option(FG_NIGHTLY "Set to ON to mark this as a nightly build" OFF)
# additional utilities
option(ENABLE_FGADMIN "Set to ON to build the FGADMIN application (default)" ON)
else()
endif (USE_DBUS)
-# Sqlite always depends on the threading lib
-list(APPEND SQLITE3_LIBRARY ${CMAKE_THREAD_LIBS_INIT})
-
##############################################################################
## Qt5 setup setup
if (ENABLE_QT)
if (HAVE_QT)
- qt5_wrap_ui(uic_sources Launcher.ui EditRatingsFilterDialog.ui)
+ qt5_wrap_ui(uic_sources Launcher.ui EditRatingsFilterDialog.ui SetupRootDialog.ui)
qt5_add_resources(qrc_sources resources.qrc)
include_directories(${PROJECT_BINARY_DIR}/src/GUI)
AirportDiagram.hxx
EditRatingsFilterDialog.cxx
EditRatingsFilterDialog.hxx
+ SetupRootDialog.cxx
+ SetupRootDialog.hxx
${uic_sources}
${qrc_sources})
#include <QMessageBox>
#include <QDataStream>
#include <QDateTime>
+#include <QApplication>
// Simgear
#include <simgear/timing/timestamp.hxx>
#include <Airports/airport.hxx>
#include <Airports/dynamics.hxx> // for parking
#include <Main/options.hxx>
+#include <Viewer/WindowBuilder.hxx>
using namespace flightgear;
}
+void QtLauncher::initApp(int argc, char** argv)
+{
+ static bool qtInitDone = false;
+ if (!qtInitDone) {
+ qtInitDone = true;
+
+ QApplication* app = new QApplication(argc, argv);
+ app->setOrganizationName("FlightGear");
+ app->setApplicationName("FlightGear");
+ app->setOrganizationDomain("flightgear.org");
+
+ // avoid double Apple menu and other weirdness if both Qt and OSG
+ // try to initialise various Cocoa structures.
+ flightgear::WindowBuilder::setPoseAsStandaloneApp(false);
+ }
+}
+
bool QtLauncher::runLauncherDialog()
{
- Q_INIT_RESOURCE(resources);
+ Q_INIT_RESOURCE(resources);
// startup the nav-cache now. This pre-empts normal startup of
// the cache, but no harm done. (Providing scenery paths are consistent)
public:
QtLauncher();
virtual ~QtLauncher();
-
+
+ static void initApp(int argc, char** argv);
+
static bool runLauncherDialog();
private slots:
--- /dev/null
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SetupRootDialog.hxx"
+
+#include <QFileDialog>
+#include <QDesktopServices>
+#include <QDir>
+#include <QFileInfo>
+#include <QMessageBox>
+#include <QSettings>
+#include <QDebug>
+#include <QSettings>
+
+#include "ui_SetupRootDialog.h"
+
+#include <Main/globals.hxx>
+#include <Main/fg_init.hxx>
+#include <Include/version.h>
+
+SetupRootDialog::SetupRootDialog(bool usedDefaultPath) :
+ QDialog()
+{
+ m_ui.reset(new Ui::SetupRootDialog);
+ m_ui->setupUi(this);
+
+ connect(m_ui->browseButton, &QPushButton::clicked,
+ this, &SetupRootDialog::onBrowse);
+ connect(m_ui->downloadButton, &QPushButton::clicked,
+ this, &SetupRootDialog::onDownload);
+ connect(m_ui->buttonBox, &QDialogButtonBox::rejected,
+ this, &QDialog::reject);
+
+ 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;
+ }
+
+ m_ui->versionLabel->setText(tr("FlightGear version %1").arg(FLIGHTGEAR_VERSION));
+ m_ui->bigIcon->setPixmap(QPixmap(":/app-icon-large"));
+ updatePromptText();
+}
+
+bool SetupRootDialog::restoreUserSelectedRoot()
+{
+ QSettings settings;
+ QString path = settings.value("fg-root").toString();
+ if (validatePath(path) && validateVersion(path)) {
+ qDebug() << "Restoring FG-root:" << path;
+ globals->set_fg_root(path.toStdString());
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool SetupRootDialog::validatePath(QString path)
+{
+ // check assorted files exist in the root location, to avoid any chance of
+ // selecting an incomplete base package. This is probably overkill but does
+ // no harm
+ QStringList files = QStringList()
+ << "version"
+ << "preferences.xml"
+ << "Materials/base/materials-base.xml"
+ << "gui/menubar.xml"
+ << "Timezone/zone.tab";
+
+ QDir d(path);
+ if (!d.exists()) {
+ return false;
+ }
+
+ Q_FOREACH(QString s, files) {
+ if (!d.exists(s)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool SetupRootDialog::validateVersion(QString path)
+{
+ std::string ver = fgBasePackageVersion(SGPath(path.toStdString()));
+ return (ver == FLIGHTGEAR_VERSION);
+}
+
+SetupRootDialog::~SetupRootDialog()
+{
+
+}
+
+void SetupRootDialog::onBrowse()
+{
+ m_browsedPath = QFileDialog::getExistingDirectory(this,
+ tr("Choose FlightGear data folder"));
+ if (m_browsedPath.isEmpty()) {
+ return;
+ }
+
+ if (!validatePath(m_browsedPath)) {
+ m_promptState = ChoseInvalidLocation;
+ updatePromptText();
+ return;
+ }
+
+ if (!validateVersion(m_browsedPath)) {
+ m_promptState = ChoseInvalidVersion;
+ updatePromptText();
+ return;
+ }
+
+ globals->set_fg_root(m_browsedPath.toStdString());
+
+ QSettings settings;
+ settings.setValue("fg-root", m_browsedPath);
+
+ accept(); // we're done
+}
+
+void SetupRootDialog::onDownload()
+{
+ QUrl downloadUrl("http://download.flightgear.org/flightgear/Shared/");
+ QDesktopServices::openUrl(downloadUrl);
+}
+
+void SetupRootDialog::updatePromptText()
+{
+ QString t;
+ QString curRoot = QString::fromStdString(globals->get_fg_root());
+ switch (m_promptState) {
+ case DefaultPathCheckFailed:
+ t = tr("This copy of FlightGear does not include the base data files. " \
+ "Please select a suitable folder containing a previously download set of files.");
+ break;
+
+ case ExplicitPathCheckFailed:
+ t = tr("The requested location '%1' does not appear to be a valid set of data files for FlightGear").arg(curRoot);
+ break;
+
+ case VersionCheckFailed:
+ {
+ QString curVer = QString::fromStdString(fgBasePackageVersion(globals->get_fg_root()));
+ t = tr("Detected incompatible version of the data files: version %1 found, but this is FlightGear %2. " \
+ "(At location: '%3') " \
+ "Please install or select a matching set of data files.").arg(curVer).arg(QString::fromLatin1(FLIGHTGEAR_VERSION)).arg(curRoot);
+ 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;
+
+ case ChoseInvalidVersion:
+ {
+ QString curVer = QString::fromStdString(fgBasePackageVersion(m_browsedPath.toStdString()));
+ t = tr("The choosen location (%1) contains files for version %2, but this is FlightGear %3. " \
+ "Please update or try another location").arg(m_browsedPath).arg(curVer).arg(QString::fromLatin1(FLIGHTGEAR_VERSION));
+ break;
+ }
+ }
+
+ m_ui->promptText->setText(t);
+}
+
--- /dev/null
+
+#include <QDialog>
+#include <QScopedPointer>
+#include <QString>
+
+namespace Ui
+{
+ class SetupRootDialog;
+}
+
+class SetupRootDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ SetupRootDialog(bool usedDefaultPath);
+
+ ~SetupRootDialog();
+
+ static bool restoreUserSelectedRoot();
+private slots:
+
+ void onBrowse();
+
+ void onDownload();
+
+ void updatePromptText();
+private:
+
+ static bool validatePath(QString path);
+ static bool validateVersion(QString path);
+
+ enum PromptState
+ {
+ DefaultPathCheckFailed,
+ ExplicitPathCheckFailed,
+ VersionCheckFailed,
+ ChoseInvalidLocation,
+ ChoseInvalidVersion
+ };
+
+ PromptState m_promptState;
+ QScopedPointer<Ui::SetupRootDialog> m_ui;
+ QString m_browsedPath;
+};
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SetupRootDialog</class>
+ <widget class="QDialog" name="SetupRootDialog">
+ <property name="windowModality">
+ <enum>Qt::ApplicationModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>618</width>
+ <height>338</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Setup required data files</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout" columnstretch="0,1">
+ <item row="0" column="0" rowspan="2">
+ <widget class="QLabel" name="bigIcon">
+ <property name="minimumSize">
+ <size>
+ <width>128</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <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">
+ <widget class="QLabel" name="promptText">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>80</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Replace me</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QPushButton" name="browseButton">
+ <property name="text">
+ <string>Choose folder...</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="versionLabel">
+ <property name="text">
+ <string>FlightGear version 3.4.5</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0" 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="5" 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>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
<file alias="search-icon">large-search-icon.png</file>
<file alias="right-arrow-icon">arrow-right-icon.png</file>
<file alias="left-arrow-icon">arrow-left-icon.png</file>
+ <file alias="app-icon-large">../../icons/128x128/apps/flightgear.png</file>
</qresource>
</RCC>
\ No newline at end of file
#cmakedefine FG_NDEBUG
+#cmakedefine FG_NIGHTLY
+
#cmakedefine ENABLE_SP_FDM
#cmakedefine JSBSIM_USE_GROUNDREACTIONS
extern osg::ref_ptr<osgViewer::Viewer> viewer;
// Return the current base package version
-string fgBasePackageVersion() {
- SGPath base_path( globals->get_fg_root() );
- base_path.append("version");
- if (!base_path.exists()) {
+string fgBasePackageVersion(const SGPath& base_path) {
+ SGPath p(base_path);
+ p.append("version");
+ if (!p.exists()) {
return string();
}
- sg_gzifstream in( base_path.str() );
+ sg_gzifstream in( p.str() );
if (!in.is_open()) {
return string();
}
// forward decls
class SGPropertyNode;
+class SGPath;
// Return the current base package version
-std::string fgBasePackageVersion();
+std::string fgBasePackageVersion(const SGPath& path);
bool fgInitHome();
#include <Viewer/WindowSystemAdapter.hxx>
#include <Navaids/NavDataCache.hxx>
#include <Include/version.h>
-#include <Viewer/WindowBuilder.hxx>
#include "fg_commands.hxx"
#include "fg_io.hxx"
#include "options.hxx"
#if defined(HAVE_QT)
-#include <QApplication>
#include <GUI/QtLauncher.hxx>
#endif
// environment variables. This avoids needed a wrapper shell-script on OS-X.
showLauncher |= (::getenv("FG_LAUNCHER") != 0);
- if (showLauncher) {
- QApplication app(argc, argv);
- app.setOrganizationName("FlightGear");
- app.setApplicationName("FlightGear");
- app.setOrganizationDomain("flightgear.org");
-
- // avoid double Apple menu and other weirdness if both Qt and OSG
- // try to initialise various Cocoa structures.
- flightgear::WindowBuilder::setPoseAsStandaloneApp(false);
-
+ if (showLauncher) {
+ QtLauncher::initApp(argc, argv);
if (!QtLauncher::runLauncherDialog()) {
return EXIT_SUCCESS;
}
#include <GUI/gui.h>
#include <GUI/MessageBox.hxx>
+#include <GUI/QtLauncher.hxx>
+#include <GUI/SetupRootDialog.hxx>
#include <Main/locale.hxx>
#include "globals.hxx"
#include "AircraftDirVisitorBase.hxx"
#include <osg/Version>
-
-#if defined( HAVE_VERSION_H ) && HAVE_VERSION_H
-# include <Include/version.h>
-# include <simgear/version.h>
-#else
-# include <Include/no_version.h>
-#endif
+#include <Include/version.h>
+#include <simgear/version.h>
using std::string;
using std::sort;
fgOptLogLevel(valueForOption("log-level", "alert").c_str());
if (!p->shouldLoadDefaultConfig) {
- setupRoot();
+ setupRoot(argc, argv);
return;
}
}
// setup FG_ROOT
- setupRoot();
+ setupRoot(argc, argv);
// system.fgfsrc handling
if( ! hostname.empty() ) {
}
#endif
-void Options::setupRoot()
+void Options::setupRoot(int argc, char **argv)
{
string root;
+ bool usingDefaultRoot = false;
+
if (isOptionSet("fg-root")) {
root = valueForOption("fg-root"); // easy!
} else {
if ( envp != NULL ) {
root = envp;
} else {
+ usingDefaultRoot = true;
root = platformDefaultRoot();
}
}
- SG_LOG(SG_INPUT, SG_INFO, "fg_root = " << root );
+ SG_LOG(SG_GENERAL, SG_INFO, "fg_root = " << root );
globals->set_fg_root(root);
-
-// validate it
- static char required_version[] = FLIGHTGEAR_VERSION;
- string base_version = fgBasePackageVersion();
+ static char required_version[] = FLIGHTGEAR_VERSION;
+ string base_version = fgBasePackageVersion(root);
+
+#if defined(HAVE_QT)
+ if (base_version != required_version) {
+ QtLauncher::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);
+ }
+ }
+#else
+ // validate it
if (base_version.empty()) {
flightgear::fatalMessageBox("Base package not found",
"Required data files not found, check your installation.",
exit(-1);
}
- if (base_version != required_version) {
- // tell the operator how to use this application
-
+ if (base_version != required_version) {
flightgear::fatalMessageBox("Base package version mismatch",
"Version check failed: please check your installation.",
"Found data files for version '" + base_version +
exit(-1);
}
+#endif
}
bool Options::shouldLoadDefaultConfig() const
int parseOption(const std::string& s);
void processArgResult(int result);
-
- void setupRoot();
+
+ /**
+ * Setup the root base, and check it's valid. Bails out with exit(-1) if
+ * the root package was not found or is the incorrect version. Argv/argv
+ * are passed since we might potentially show a GUI dialog at this point
+ * 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;