1
0
Fork 0

Very crude work on GUI base package selection.

- feedback on wording greatly appreciated.
- needed to make nightly builds usable without bundled data.
This commit is contained in:
James Turner 2015-03-06 18:52:06 +00:00
parent 8d9db2824e
commit a466dbce73
14 changed files with 405 additions and 44 deletions

View file

@ -168,6 +168,7 @@ option(SYSTEM_SPEEX "Set to ON to build IAXClient with the system's speex a
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)
@ -287,9 +288,6 @@ if (USE_DBUS)
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)

View file

@ -70,7 +70,7 @@ endif()
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)
@ -81,6 +81,8 @@ if (HAVE_QT)
AirportDiagram.hxx
EditRatingsFilterDialog.cxx
EditRatingsFilterDialog.hxx
SetupRootDialog.cxx
SetupRootDialog.hxx
${uic_sources}
${qrc_sources})

View file

@ -27,6 +27,7 @@
#include <QMessageBox>
#include <QDataStream>
#include <QDateTime>
#include <QApplication>
// Simgear
#include <simgear/timing/timestamp.hxx>
@ -42,6 +43,7 @@
#include <Airports/airport.hxx>
#include <Airports/dynamics.hxx> // for parking
#include <Main/options.hxx>
#include <Viewer/WindowBuilder.hxx>
using namespace flightgear;
@ -1066,9 +1068,26 @@ QtLauncher::~QtLauncher()
}
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)

View file

@ -23,6 +23,8 @@ public:
QtLauncher();
virtual ~QtLauncher();
static void initApp(int argc, char** argv);
static bool runLauncherDialog();
private slots:

169
src/GUI/SetupRootDialog.cxx Normal file
View file

@ -0,0 +1,169 @@
#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);
}

View file

@ -0,0 +1,44 @@
#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;
};

113
src/GUI/SetupRootDialog.ui Normal file
View file

@ -0,0 +1,113 @@
<?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>

View file

@ -4,5 +4,6 @@
<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>

View file

@ -1,6 +1,8 @@
#cmakedefine FG_NDEBUG
#cmakedefine FG_NIGHTLY
#cmakedefine ENABLE_SP_FDM
#cmakedefine JSBSIM_USE_GROUNDREACTIONS

View file

@ -160,14 +160,14 @@ using namespace simgear::pkg;
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();
}

View file

@ -30,9 +30,10 @@
// forward decls
class SGPropertyNode;
class SGPath;
// Return the current base package version
std::string fgBasePackageVersion();
std::string fgBasePackageVersion(const SGPath& path);
bool fgInitHome();

View file

@ -68,7 +68,6 @@ extern bool global_crashRptEnabled;
#include <Viewer/WindowSystemAdapter.hxx>
#include <Navaids/NavDataCache.hxx>
#include <Include/version.h>
#include <Viewer/WindowBuilder.hxx>
#include "fg_commands.hxx"
#include "fg_io.hxx"
@ -83,7 +82,6 @@ extern bool global_crashRptEnabled;
#include "options.hxx"
#if defined(HAVE_QT)
#include <QApplication>
#include <GUI/QtLauncher.hxx>
#endif
@ -459,15 +457,7 @@ int fgMainInit( int argc, char **argv )
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);
QtLauncher::initApp(argc, argv);
if (!QtLauncher::runLauncherDialog()) {
return EXIT_SUCCESS;
}

View file

@ -55,6 +55,8 @@
#include <GUI/gui.h>
#include <GUI/MessageBox.hxx>
#include <GUI/QtLauncher.hxx>
#include <GUI/SetupRootDialog.hxx>
#include <Main/locale.hxx>
#include "globals.hxx"
@ -71,13 +73,8 @@
#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;
@ -1904,7 +1901,7 @@ void Options::init(int argc, char **argv, const SGPath& appDataPath)
fgOptLogLevel(valueForOption("log-level", "alert").c_str());
if (!p->shouldLoadDefaultConfig) {
setupRoot();
setupRoot(argc, argv);
return;
}
@ -1939,7 +1936,7 @@ void Options::init(int argc, char **argv, const SGPath& appDataPath)
}
// setup FG_ROOT
setupRoot();
setupRoot(argc, argv);
// system.fgfsrc handling
if( ! hostname.empty() ) {
@ -2436,9 +2433,11 @@ string Options::platformDefaultRoot() const
}
#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 {
@ -2447,16 +2446,32 @@ void Options::setupRoot()
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);
static char required_version[] = FLIGHTGEAR_VERSION;
string base_version = fgBasePackageVersion(root);
// validate it
static char required_version[] = FLIGHTGEAR_VERSION;
string base_version = fgBasePackageVersion();
#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.",
@ -2465,9 +2480,7 @@ void Options::setupRoot()
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 +
@ -2476,6 +2489,7 @@ void Options::setupRoot()
exit(-1);
}
#endif
}
bool Options::shouldLoadDefaultConfig() const

View file

@ -132,7 +132,13 @@ private:
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;