Allows exposing aircraft data to QML (via a helper object) outside the context of the model.
305 lines
9.2 KiB
C++
305 lines
9.2 KiB
C++
#include "PathsDialog.hxx"
|
|
#include "ui_PathsDialog.h"
|
|
|
|
#include <QSettings>
|
|
#include <QFileDialog>
|
|
#include <QMessageBox>
|
|
#include <QDebug>
|
|
#include <QProcess>
|
|
|
|
#include "CatalogListModel.hxx"
|
|
#include "AddCatalogDialog.hxx"
|
|
#include "AircraftModel.hxx"
|
|
#include "InstallSceneryDialog.hxx"
|
|
#include "QtLauncher.hxx"
|
|
#include "LocalAircraftCache.hxx"
|
|
|
|
#include <Main/options.hxx>
|
|
#include <Main/globals.hxx>
|
|
#include <Network/HTTPClient.hxx>
|
|
|
|
AddOnsPage::AddOnsPage(QWidget *parent, simgear::pkg::RootRef root) :
|
|
QWidget(parent),
|
|
m_ui(new Ui::AddOnsPage),
|
|
m_packageRoot(root)
|
|
{
|
|
m_ui->setupUi(this);
|
|
|
|
m_catalogsModel = new CatalogListModel(this, m_packageRoot);
|
|
m_ui->catalogsList->setModel(m_catalogsModel);
|
|
|
|
// enable drag-drop to re-order the paths
|
|
m_ui->sceneryPathsList->setDragEnabled(true);
|
|
m_ui->sceneryPathsList->setDragDropMode(QAbstractItemView::InternalMove);
|
|
m_ui->sceneryPathsList->setDropIndicatorShown(true);
|
|
|
|
m_ui->aircraftPathsList->setDragEnabled(true);
|
|
m_ui->aircraftPathsList->setDragDropMode(QAbstractItemView::InternalMove);
|
|
m_ui->aircraftPathsList->setDropIndicatorShown(true);
|
|
|
|
connect(m_ui->addCatalog, &QToolButton::clicked,
|
|
this, &AddOnsPage::onAddCatalog);
|
|
connect(m_ui->addDefaultCatalogButton, &QPushButton::clicked,
|
|
this, &AddOnsPage::onAddDefaultCatalog);
|
|
connect(m_ui->removeCatalog, &QToolButton::clicked,
|
|
this, &AddOnsPage::onRemoveCatalog);
|
|
|
|
connect(m_ui->addSceneryPath, &QToolButton::clicked,
|
|
this, &AddOnsPage::onAddSceneryPath);
|
|
connect(m_ui->removeSceneryPath, &QToolButton::clicked,
|
|
this, &AddOnsPage::onRemoveSceneryPath);
|
|
|
|
connect(m_ui->addAircraftPath, &QToolButton::clicked,
|
|
this, &AddOnsPage::onAddAircraftPath);
|
|
connect(m_ui->removeAircraftPath, &QToolButton::clicked,
|
|
this, &AddOnsPage::onRemoveAircraftPath);
|
|
|
|
connect(m_ui->installSceneryButton, &QPushButton::clicked,
|
|
this, &AddOnsPage::onInstallScenery);
|
|
|
|
m_ui->sceneryPathsList->setToolTip(
|
|
tr("After changing this list, please restart the launcher to avoid "
|
|
"possibly inconsistent behavior."));
|
|
m_ui->installSceneryButton->setToolTip(
|
|
tr("After installing scenery, you may have to restart the launcher "
|
|
"to avoid inconsistent behavior."));
|
|
|
|
QSettings settings;
|
|
|
|
QStringList sceneryPaths = settings.value("scenery-paths").toStringList();
|
|
m_ui->sceneryPathsList->addItems(sceneryPaths);
|
|
|
|
connect(m_ui->sceneryPathsList->model(), &QAbstractItemModel::rowsMoved,
|
|
this, &AddOnsPage::saveSceneryPaths);
|
|
|
|
QStringList aircraftPaths = settings.value("aircraft-paths").toStringList();
|
|
m_ui->aircraftPathsList->addItems(aircraftPaths);
|
|
|
|
connect(m_ui->aircraftPathsList->model(), &QAbstractItemModel::rowsMoved,
|
|
this, &AddOnsPage::saveAircraftPaths);
|
|
|
|
updateUi();
|
|
}
|
|
|
|
AddOnsPage::~AddOnsPage()
|
|
{
|
|
delete m_ui;
|
|
}
|
|
|
|
void AddOnsPage::onAddSceneryPath()
|
|
{
|
|
QString path = QFileDialog::getExistingDirectory(this, tr("Choose scenery folder"));
|
|
if (!path.isEmpty()) {
|
|
// validation
|
|
|
|
SGPath p(path.toStdString());
|
|
bool isValid = false;
|
|
|
|
for (const auto& dir: {"Objects", "Terrain", "Buildings", "Roads",
|
|
"Pylons", "NavData"}) {
|
|
if ((p / dir).exists()) {
|
|
isValid = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!isValid) {
|
|
QMessageBox mb;
|
|
mb.setText(tr("The folder '%1' doesn't appear to contain scenery - add anyway?").arg(path));
|
|
mb.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
|
mb.setDefaultButton(QMessageBox::No);
|
|
mb.setInformativeText(tr("Added scenery should contain at least one of the following "
|
|
"folders: Objects, Terrain, Buildings, Roads, Pylons, NavData."));
|
|
mb.exec();
|
|
|
|
if (mb.result() == QMessageBox::No) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
m_ui->sceneryPathsList->addItem(path);
|
|
saveSceneryPaths();
|
|
}
|
|
}
|
|
|
|
void AddOnsPage::onRemoveSceneryPath()
|
|
{
|
|
if (m_ui->sceneryPathsList->currentItem()) {
|
|
delete m_ui->sceneryPathsList->currentItem();
|
|
saveSceneryPaths();
|
|
}
|
|
}
|
|
|
|
void AddOnsPage::onAddAircraftPath()
|
|
{
|
|
QString path = QFileDialog::getExistingDirectory(this, tr("Choose aircraft folder"));
|
|
if (!path.isEmpty()) {
|
|
// the user might add a directory containing an 'Aircraft' subdir. Let's attempt
|
|
// to check for that case and handle it gracefully.
|
|
bool pathOk = false;
|
|
|
|
if (LocalAircraftCache::isCandidateAircraftPath(path)) {
|
|
m_ui->aircraftPathsList->addItem(path);
|
|
pathOk = true;
|
|
} else {
|
|
// no aircraft in speciied path, look for Aircraft/ subdir
|
|
QDir d(path);
|
|
if (d.exists("Aircraft")) {
|
|
QString p2 = d.filePath("Aircraft");
|
|
if (LocalAircraftCache::isCandidateAircraftPath(p2)) {
|
|
m_ui->aircraftPathsList->addItem(p2);
|
|
pathOk = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!pathOk) {
|
|
QMessageBox mb;
|
|
mb.setText(tr("No aircraft found in the folder '%1' - add anyway?").arg(path));
|
|
mb.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
|
mb.setDefaultButton(QMessageBox::No);
|
|
mb.exec();
|
|
|
|
if (mb.result() == QMessageBox::Yes) {
|
|
m_ui->aircraftPathsList->addItem(path);
|
|
}
|
|
}
|
|
|
|
saveAircraftPaths();
|
|
}
|
|
}
|
|
|
|
void AddOnsPage::onRemoveAircraftPath()
|
|
{
|
|
if (m_ui->aircraftPathsList->currentItem()) {
|
|
delete m_ui->aircraftPathsList->currentItem();
|
|
saveAircraftPaths();
|
|
}
|
|
}
|
|
|
|
void AddOnsPage::saveAircraftPaths()
|
|
{
|
|
QSettings settings;
|
|
QStringList paths;
|
|
|
|
for (int i=0; i<m_ui->aircraftPathsList->count(); ++i) {
|
|
paths.append(m_ui->aircraftPathsList->item(i)->text());
|
|
}
|
|
|
|
settings.setValue("aircraft-paths", paths);
|
|
emit aircraftPathsChanged();
|
|
}
|
|
|
|
void AddOnsPage::saveSceneryPaths()
|
|
{
|
|
QSettings settings;
|
|
QStringList paths;
|
|
for (int i=0; i<m_ui->sceneryPathsList->count(); ++i) {
|
|
paths.append(m_ui->sceneryPathsList->item(i)->text());
|
|
}
|
|
|
|
settings.setValue("scenery-paths", paths);
|
|
|
|
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));
|
|
dlg->exec();
|
|
if (dlg->result() == QDialog::Accepted) {
|
|
m_catalogsModel->refresh();
|
|
}
|
|
}
|
|
|
|
void AddOnsPage::onAddDefaultCatalog()
|
|
{
|
|
addDefaultCatalog(this, false /* not silent */);
|
|
|
|
m_catalogsModel->refresh();
|
|
updateUi();
|
|
}
|
|
|
|
void AddOnsPage::addDefaultCatalog(QWidget* pr, bool silent)
|
|
{
|
|
// check it's not a duplicate somehow
|
|
FGHTTPClient* http = globals->get_subsystem<FGHTTPClient>();
|
|
if (http->isDefaultCatalogInstalled())
|
|
return;
|
|
|
|
QScopedPointer<AddCatalogDialog> dlg(new AddCatalogDialog(pr, globals->packageRoot()));
|
|
QUrl url(QString::fromStdString(http->getDefaultCatalogUrl()));
|
|
if (silent) {
|
|
dlg->setNonInteractiveMode();
|
|
}
|
|
dlg->setUrlAndDownload(url);
|
|
dlg->exec();
|
|
|
|
}
|
|
|
|
void AddOnsPage::onRemoveCatalog()
|
|
{
|
|
QModelIndex mi = m_ui->catalogsList->currentIndex();
|
|
FGHTTPClient* http = globals->get_subsystem<FGHTTPClient>();
|
|
|
|
if (mi.isValid()) {
|
|
QString s = tr("Remove aircraft hangar '%1'? All installed aircraft from this "
|
|
"hangar will be removed.");
|
|
QString pkgId = mi.data(CatalogIdRole).toString();
|
|
|
|
if (pkgId.toStdString() == http->getDefaultCatalogId()) {
|
|
s = tr("Remove the default aircraft hangar? "
|
|
"This hangar contains all the default aircraft included with FlightGear. "
|
|
"If you change your mind in the future, click the 'restore' button.");
|
|
} else {
|
|
s = s.arg(mi.data(Qt::DisplayRole).toString());
|
|
}
|
|
|
|
QMessageBox mb;
|
|
mb.setText(s);
|
|
mb.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
|
mb.setDefaultButton(QMessageBox::No);
|
|
mb.exec();
|
|
|
|
if (mb.result() == QMessageBox::Yes) {
|
|
m_packageRoot->removeCatalogById(pkgId.toStdString());
|
|
}
|
|
}
|
|
|
|
updateUi();
|
|
}
|
|
|
|
void AddOnsPage::onInstallScenery()
|
|
{
|
|
QSettings settings;
|
|
QString downloadDir = settings.value("download-dir").toString();
|
|
InstallSceneryDialog dlg(this, downloadDir);
|
|
if (dlg.exec() == QDialog::Accepted) {
|
|
if (!haveSceneryPath(dlg.sceneryPath())) {
|
|
m_ui->sceneryPathsList->addItem(dlg.sceneryPath());
|
|
saveSceneryPaths();
|
|
}
|
|
}
|
|
}
|
|
|
|
void AddOnsPage::updateUi()
|
|
{
|
|
FGHTTPClient* http = globals->get_subsystem<FGHTTPClient>();
|
|
m_ui->addDefaultCatalogButton->setEnabled(!http->isDefaultCatalogInstalled());
|
|
}
|
|
|
|
void AddOnsPage::onDraggedAircraftList()
|
|
{
|
|
qWarning() << "did drag aircraft list";
|
|
}
|