]> git.mxchange.org Git - flightgear.git/commitdiff
Allow scenery installation from the launcher.
authorJames Turner <zakalawe@mac.com>
Wed, 15 Jun 2016 21:28:27 +0000 (22:28 +0100)
committerRoland Haeder <roland@mxchange.org>
Thu, 22 Sep 2016 21:27:36 +0000 (23:27 +0200)
Replaces FGadmin functionality.

src/GUI/CMakeLists.txt
src/GUI/InstallSceneryDialog.cxx [new file with mode: 0644]
src/GUI/InstallSceneryDialog.hxx [new file with mode: 0644]
src/GUI/InstallSceneryDialog.ui [new file with mode: 0644]
src/GUI/PathsDialog.cxx
src/GUI/PathsDialog.hxx
src/GUI/PathsDialog.ui
utils/TerraSync/CMakeLists.txt

index 02b0bafcd1c8a8ce29eb3b6b09e4205dfa764421..c9afa8e12d8902dd667189cf4650381f4b7b6587 100644 (file)
@@ -76,7 +76,9 @@ if (HAVE_QT)
                             AddCatalogDialog.ui
                             PathsDialog.ui
                             LocationWidget.ui
-                            NoOfficialHangar.ui)
+                            NoOfficialHangar.ui
+                            InstallSceneryDialog.ui
+                            )
     qt5_add_resources(qrc_sources resources.qrc)
 
 
@@ -109,6 +111,8 @@ if (HAVE_QT)
                             QtMessageBox.hxx
                             QtFileDialog.cxx
                             QtFileDialog.hxx
+                            InstallSceneryDialog.hxx
+                            InstallSceneryDialog.cxx
                             ${uic_sources}
                             ${qrc_sources})
 
diff --git a/src/GUI/InstallSceneryDialog.cxx b/src/GUI/InstallSceneryDialog.cxx
new file mode 100644 (file)
index 0000000..53ab348
--- /dev/null
@@ -0,0 +1,273 @@
+// 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"
diff --git a/src/GUI/InstallSceneryDialog.hxx b/src/GUI/InstallSceneryDialog.hxx
new file mode 100644 (file)
index 0000000..e6ffcad
--- /dev/null
@@ -0,0 +1,70 @@
+// 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
diff --git a/src/GUI/InstallSceneryDialog.ui b/src/GUI/InstallSceneryDialog.ui
new file mode 100644 (file)
index 0000000..6a95b6a
--- /dev/null
@@ -0,0 +1,178 @@
+<?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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;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. (&lt;a href=&quot;http://ns334561.ip-5-196-65.eu/~fgscenery/WS2.0/scenery-2.0.1.html&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Click here to download scenery&lt;/span&gt;&lt;/a&gt;)&lt;/p&gt;&lt;p&gt;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.&lt;/p&gt;&lt;p&gt;To begin, click 'Next' and select one more more downloaded scenery archives, which have names such as 'w010n40.tar.gz'&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>
index 10854f9edc2ed9b59675416fc5fe3cecf60f4fba..d02294deb5256622d2dab1a49425febac51ad5de 100644 (file)
@@ -11,6 +11,7 @@
 #include "AddCatalogDialog.hxx"
 #include "AircraftModel.hxx"
 #include "QtLauncher_private.hxx"
+#include "InstallSceneryDialog.hxx"
 
 #include <Main/options.hxx>
 #include <Main/globals.hxx>
@@ -60,6 +61,8 @@ AddOnsPage::AddOnsPage(QWidget *parent, simgear::pkg::RootRef root) :
 
     connect(m_ui->changeDataDir, &QPushButton::clicked,
             this, &AddOnsPage::onChangeDataDir);
+    connect(m_ui->installSceneryButton, &QPushButton::clicked,
+            this, &AddOnsPage::onInstallScenery);
 
     QSettings settings;
             
@@ -180,6 +183,17 @@ void AddOnsPage::saveSceneryPaths()
     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));
@@ -310,6 +324,17 @@ void AddOnsPage::onChangeDataDir()
     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;
index 749bb9318dcc25c5f566f5f4e3e33729aae460ee..3fcaed321c3f493d54375023568bc77db414f9d2 100644 (file)
@@ -41,12 +41,14 @@ private slots:
     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;
index 070c1370a36504f589bed8363fb24b1d7dc7ee73..89cd1e42f5f4361f3849e1ee97481fa52b3298d1 100644 (file)
      </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">
index cc27ec82b4890b9ec3973693290bf0f1dd7963d9..f97996a9a8fa7cd78b75cb4411f574bce2ad073c 100644 (file)
@@ -1,9 +1,9 @@
 
-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)