Replaces FGadmin functionality.
AddCatalogDialog.ui
PathsDialog.ui
LocationWidget.ui
- NoOfficialHangar.ui)
+ NoOfficialHangar.ui
+ InstallSceneryDialog.ui
+ )
qt5_add_resources(qrc_sources resources.qrc)
QtMessageBox.hxx
QtFileDialog.cxx
QtFileDialog.hxx
+ InstallSceneryDialog.hxx
+ InstallSceneryDialog.cxx
${uic_sources}
${qrc_sources})
--- /dev/null
+// InstallSceneryDialog.cxx - part of GUI launcher using Qt5
+//
+// Written by James Turner, started June 2016.
+//
+// Copyright (C) 2016 James Turner <zakalawe@mac.com>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+#include "InstallSceneryDialog.hxx"
+#include "ui_InstallSceneryDialog.h"
+
+#include <QPushButton>
+#include <QDebug>
+#include <QFileDialog>
+#include <QThread>
+#include <QFile>
+#include <QFileInfo>
+#include <QRegularExpression>
+#include <QDir>
+#include <QStandardPaths>
+
+#include <Main/globals.hxx>
+#include <Main/options.hxx>
+#include <Include/version.h>
+
+#include <simgear/io/untar.hxx>
+
+class InstallSceneryThread : public QThread
+{
+ Q_OBJECT
+public:
+ InstallSceneryThread(QString extractDir, QStringList files) :
+ m_extractDir(extractDir),
+ m_remainingPaths(files),
+ m_error(false),
+ m_totalBytes(0),
+ m_bytesRead(0)
+ {
+
+ }
+
+ virtual void run()
+ {
+ // pre-check each file
+ Q_FOREACH (QString path, m_remainingPaths) {
+ QFileInfo finfo(path);
+ QString baseName = finfo.baseName();
+ QRegularExpression re("[e|w]\\d{2}0[n|s]\\d0", QRegularExpression::CaseInsensitiveOption);
+ Q_ASSERT(re.isValid());
+ if (!re.match(baseName).hasMatch()) {
+ emit extractionError(path,tr("scenery archive name is not correct."));
+ m_error = true;
+ return;
+ }
+
+ QFile f(path);
+ f.open(QIODevice::ReadOnly);
+ QByteArray firstData = f.read(8192);
+
+ if (!simgear::TarExtractor::isTarData((uint8_t*) firstData.data(), firstData.count())) {
+ emit extractionError(path,tr("file does not appear to be a scenery archive."));
+ m_error = true;
+ return;
+ }
+
+ m_totalBytes += f.size();
+ }
+
+ while (!m_remainingPaths.isEmpty() && !m_error) {
+ extractNextArchive();
+ }
+ }
+
+signals:
+ void extractionError(QString file, QString msg);
+
+ void progress(int percent);
+private:
+ void extractNextArchive()
+ {
+ SGPath root(m_extractDir.toStdString());
+ m_untar.reset(new simgear::TarExtractor(root));
+
+ QString path = m_remainingPaths.front();
+ m_remainingPaths.pop_front();
+ QFileInfo finfo(path);
+
+ QFile f(path);
+ f.open(QIODevice::ReadOnly);
+ Q_ASSERT(f.isOpen());
+
+ while (!f.atEnd()) {
+ QByteArray bytes = f.read(4 * 1024 * 1024);
+ m_untar->extractBytes(bytes.constData(), bytes.size());
+ m_bytesRead += bytes.size();
+
+ if (m_untar->hasError()) {
+ break;
+ }
+
+ emit progress((m_bytesRead * 100) / m_totalBytes);
+ }
+
+ if (m_untar->hasError() || !m_untar->isAtEndOfArchive()) {
+ emit extractionError(path, tr("unarchiving failed"));
+ m_error = true;
+ // try to clean up?
+ }
+ }
+
+ QString m_extractDir;
+ QStringList m_remainingPaths;
+ std::auto_ptr<simgear::TarExtractor> m_untar;
+ bool m_error;
+ quint64 m_totalBytes;
+ quint64 m_bytesRead;
+};
+
+InstallSceneryDialog::InstallSceneryDialog(QWidget *parent, QString downloadDir) :
+ QDialog(parent, Qt::Dialog
+ | Qt::CustomizeWindowHint
+ | Qt::WindowTitleHint
+ | Qt::WindowSystemMenuHint
+ | Qt::WindowContextHelpButtonHint
+ | Qt::MSWindowsFixedSizeDialogHint),
+ m_state(STATE_START),
+ m_downloadDir(downloadDir),
+ ui(new Ui::InstallSceneryDialog)
+{
+ ui->setupUi(this);
+ if (m_downloadDir.isEmpty()) {
+ m_downloadDir = QString::fromStdString(flightgear::defaultDownloadDir());
+ }
+
+ QString baseIntroString = ui->introText->text();
+ ui->introText->setText(baseIntroString.arg(m_downloadDir));
+ updateUi();
+}
+
+InstallSceneryDialog::~InstallSceneryDialog()
+{
+ delete ui;
+}
+
+void InstallSceneryDialog::updateUi()
+{
+ QPushButton* b = ui->buttonBox->button(QDialogButtonBox::Ok);
+ QPushButton* cancel = ui->buttonBox->button(QDialogButtonBox::Cancel);
+
+ switch (m_state) {
+ case STATE_START:
+ b->setText(tr("Next"));
+ // b->setEnabled(m_catalogUrl.isValid() && !m_catalogUrl.isRelative());
+ break;
+
+ case STATE_EXTRACTING:
+ b->setEnabled(false);
+ cancel->setEnabled(false);
+ ui->stack->setCurrentIndex(1);
+ break;
+
+ case STATE_EXTRACT_FAILED:
+ b->setEnabled(false);
+ cancel->setEnabled(true);
+ ui->stack->setCurrentIndex(2);
+ break;
+
+ case STATE_FINISHED:
+ b->setEnabled(true);
+ cancel->setEnabled(false);
+ b->setText(tr("Okay"));
+ ui->stack->setCurrentIndex(2);
+ QString basicDesc = ui->resultsSummaryLabel->text();
+
+ ui->resultsSummaryLabel->setText(basicDesc.arg(sceneryPath()));
+ break;
+ }
+}
+
+
+void InstallSceneryDialog::accept()
+{
+ switch (m_state) {
+ case STATE_START:
+ pickFiles();
+ break;
+
+ case STATE_EXTRACTING:
+ case STATE_EXTRACT_FAILED:
+ // can't happen, button is disabled
+ break;
+
+ case STATE_FINISHED:
+ // check if download path is in scenery list, add if not
+ QDialog::accept();
+ break;
+ }
+}
+
+void InstallSceneryDialog::reject()
+{
+
+ QDialog::reject();
+}
+
+void InstallSceneryDialog::pickFiles()
+{
+ QStringList downloads = QStandardPaths::standardLocations(QStandardPaths::DownloadLocation);
+ QStringList files = QFileDialog::getOpenFileNames(this, "Choose scenery to install",
+ downloads.first(), "*.tar *.gz *.tgz");
+ if (!files.isEmpty()) {
+ QDir d(m_downloadDir);
+ if (!d.exists("Scenery")) {
+ d.mkdir("Scenery");
+ }
+
+ m_state = STATE_EXTRACTING;
+ m_thread.reset(new InstallSceneryThread(d.filePath("Scenery"), files));
+ // connect up some signals
+ connect(m_thread.data(), &QThread::finished, this, &InstallSceneryDialog::onThreadFinished);
+ connect(m_thread.data(), &InstallSceneryThread::extractionError,
+ this, &InstallSceneryDialog::onExtractError);
+ connect(m_thread.data(), &InstallSceneryThread::progress,
+ this, &InstallSceneryDialog::onExtractProgress);
+ updateUi();
+ m_thread->start();
+ } else {
+ // user cancelled file dialog, cancel us as well
+ QDialog::reject();
+ }
+}
+
+void InstallSceneryDialog::onThreadFinished()
+{
+ m_state = STATE_FINISHED;
+ updateUi();
+}
+
+void InstallSceneryDialog::onExtractError(QString file, QString msg)
+{
+ ui->resultsSummaryLabel->setText(tr("Problems occured extracting the archive '%1': %2").arg(file).arg(msg));
+ m_state = STATE_EXTRACT_FAILED;
+ updateUi();
+}
+
+void InstallSceneryDialog::onExtractProgress(int percent)
+{
+ ui->progressBar->setValue(percent);
+}
+
+QString InstallSceneryDialog::sceneryPath()
+{
+ if (m_state == STATE_FINISHED) {
+ QDir d(m_downloadDir);
+ return d.filePath("Scenery");
+ }
+
+ return QString();
+}
+
+#include "InstallSceneryDialog.moc"
--- /dev/null
+// InstallSceneryDialog.hxx - part of GUI launcher using Qt5
+//
+// Written by James Turner, started June 2016.
+//
+// Copyright (C) 2016 James Turner <zakalawe@mac.com>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+#ifndef FG_GUI_INSTALL_SCENERY_DIALOG_HXX
+#define FG_GUI_INSTALL_SCENERY_DIALOG_HXX
+
+#include <QDialog>
+#include <QUrl>
+
+namespace Ui {
+ class InstallSceneryDialog;
+}
+
+class InstallSceneryThread;
+
+class InstallSceneryDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit InstallSceneryDialog(QWidget *parent, QString downloadDir);
+ ~InstallSceneryDialog();
+
+ QString sceneryPath();
+private slots:
+ virtual void reject();
+ virtual void accept();
+
+private:
+ void updateUi();
+
+ void pickFiles();
+
+ void onThreadFinished();
+ void onExtractError(QString file, QString msg);
+ void onExtractProgress(int percent);
+
+ enum State {
+ STATE_START = 0, // awaiting user input on first screen
+ STATE_EXTRACTING = 1, // in-progress, showing progress page
+ STATE_FINISHED = 2, // catalog added ok, showing summary page
+ STATE_EXTRACT_FAILED = 3
+ };
+
+ State m_state;
+ QString m_downloadDir;
+
+ Ui::InstallSceneryDialog *ui;
+
+ QScopedPointer<InstallSceneryThread> m_thread;
+};
+
+#endif // FG_GUI_INSTALL_SCENERY_DIALOG_HXX
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>InstallSceneryDialog</class>
+ <widget class="QDialog" name="InstallSceneryDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>528</width>
+ <height>311</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Install scenery</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QStackedWidget" name="stack">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="page">
+ <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
+ <item>
+ <widget class="QLabel" name="introText">
+ <property name="text">
+ <string><html><head/><body><p>The easiest way to automatically install scenery is to use TerraSync. If you prefer to download and install scenery manually, you can use this dialog to extract and install the files in the correct place. (<a href="http://ns334561.ip-5-196-65.eu/~fgscenery/WS2.0/scenery-2.0.1.html"><span style=" text-decoration: underline; color:#0000ff;">Click here to download scenery</span></a>)</p><p>Files will be extracted and installed to a 'Scenery' folder inside your chosen downloads location (currently %1), after which you can delete the archives if you wish.</p><p>To begin, click 'Next' and select one more more downloaded scenery archives, which have names such as 'w010n40.tar.gz'</p></body></html></string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <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>
+ <widget class="QWidget" name="page_2">
+ <layout class="QVBoxLayout" name="verticalLayout_3" stretch="0,0,0,1,0">
+ <item>
+ <widget class="QLabel" name="description">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Please wait, verifying and extracting scenery...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <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>
+ <widget class="QLabel" name="progressText">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="progressBar">
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>-1</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_3">
+ <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>
+ <widget class="QWidget" name="page_3">
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QLabel" name="resultsSummaryLabel">
+ <property name="text">
+ <string>Successfully installed the scenery files to '%1'. This location will be added to the list of additional sceneries to be used.</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>InstallSceneryDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>InstallSceneryDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
#include "AddCatalogDialog.hxx"
#include "AircraftModel.hxx"
#include "QtLauncher_private.hxx"
+#include "InstallSceneryDialog.hxx"
#include <Main/options.hxx>
#include <Main/globals.hxx>
connect(m_ui->changeDataDir, &QPushButton::clicked,
this, &AddOnsPage::onChangeDataDir);
+ connect(m_ui->installSceneryButton, &QPushButton::clicked,
+ this, &AddOnsPage::onInstallScenery);
QSettings settings;
emit sceneryPathsChanged();
}
+bool AddOnsPage::haveSceneryPath(QString path) const
+{
+ for (int i=0; i<m_ui->sceneryPathsList->count(); ++i) {
+ if (m_ui->sceneryPathsList->item(i)->text() == path) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void AddOnsPage::onAddCatalog()
{
QScopedPointer<AddCatalogDialog> dlg(new AddCatalogDialog(this, m_packageRoot));
QtLauncher::restartTheApp(QStringList());
}
+void AddOnsPage::onInstallScenery()
+{
+ InstallSceneryDialog dlg(this, m_downloadDir);
+ if (dlg.exec() == QDialog::Accepted) {
+ if (!haveSceneryPath(dlg.sceneryPath())) {
+ m_ui->sceneryPathsList->addItem(dlg.sceneryPath());
+ saveSceneryPaths();
+ }
+ }
+}
+
void AddOnsPage::updateUi()
{
QString s = m_downloadDir;
void onClearDownloadDir();
void onChangeDataDir();
+ void onInstallScenery();
private:
void updateUi();
void setDownloadDir();
void saveAircraftPaths();
void saveSceneryPaths();
+ bool haveSceneryPath(QString path) const;
Ui::AddOnsPage* m_ui;
CatalogListModel* m_catalogsModel;
</item>
</layout>
</item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QPushButton" name="installSceneryButton">
+ <property name="text">
+ <string>Install downloaded scenery...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
-add_executable(terrasync terrasync.cxx)
+#add_executable(terrasync terrasync.cxx)
-target_link_libraries(terrasync
- ${SIMGEAR_CORE_LIBRARIES}
- ${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
-)
+#target_link_libraries(terrasync
+# ${SIMGEAR_CORE_LIBRARIES}
+# ${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
+#)
-install(TARGETS terrasync RUNTIME DESTINATION bin)
+#install(TARGETS terrasync RUNTIME DESTINATION bin)