mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-22 14:55:36 +08:00
On Windows we ship 7za.exe in our binaries. On MacOS we do the same, but the executable needs to be called with the full path. On Linux we don't ship anything but assume it to be available from the distribution.
355 lines
16 KiB
C++
355 lines
16 KiB
C++
/* Copyright (C) 2017
|
|
* swift project Community / Contributors
|
|
*
|
|
* This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level
|
|
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
|
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
|
* contained in the LICENSE file.
|
|
*/
|
|
|
|
#include "installxswiftbuscomponent.h"
|
|
#include "ui_installxswiftbuscomponent.h"
|
|
#include "blackgui/guiapplication.h"
|
|
#include "blackgui/overlaymessagesframe.h"
|
|
#include "blackmisc/simulation/xplane/xplaneutil.h"
|
|
#include "blackmisc/compressutils.h"
|
|
#include "blackmisc/logmessage.h"
|
|
#include "blackmisc/directoryutils.h"
|
|
#include "blackmisc/fileutils.h"
|
|
|
|
#include <QMessageBox>
|
|
#include <QFileDialog>
|
|
#include <QDir>
|
|
#include <QFileInfo>
|
|
#include <QStandardPaths>
|
|
#include <QTimer>
|
|
#include <QDesktopServices>
|
|
|
|
using namespace BlackMisc;
|
|
using namespace BlackMisc::Db;
|
|
using namespace BlackMisc::Network;
|
|
using namespace BlackMisc::Simulation;
|
|
using namespace BlackMisc::Simulation::Settings;
|
|
using namespace BlackMisc::Simulation::XPlane;
|
|
|
|
namespace BlackGui
|
|
{
|
|
namespace Components
|
|
{
|
|
CInstallXSwiftBusComponent::CInstallXSwiftBusComponent(QWidget *parent) :
|
|
COverlayMessagesFrame(parent),
|
|
CLoadIndicatorEnabled(this),
|
|
ui(new Ui::CInstallXSwiftBusComponent)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
ui->le_XSwiftBusPluginDir->setText(this->getXPlanePluginDirectory());
|
|
ui->le_DownloadDir->setText(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
|
|
ui->cb_DownloadFile->setEnabled(false);
|
|
|
|
connect(ui->tb_DialogInstallDir, &QPushButton::pressed, this, &CInstallXSwiftBusComponent::selectPluginDirectory);
|
|
connect(ui->tb_DialogDownloadDir, &QPushButton::pressed, this, &CInstallXSwiftBusComponent::selectDownloadDirectory);
|
|
connect(ui->pb_Download, &QPushButton::pressed, this, &CInstallXSwiftBusComponent::triggerDownloadingOfXSwiftBusFile);
|
|
connect(ui->pb_OpenDownloadDir, &QPushButton::pressed, this, &CInstallXSwiftBusComponent::openDownloadDir);
|
|
connect(ui->pb_OpenInstallDir, &QPushButton::pressed, this, &CInstallXSwiftBusComponent::openInstallDir);
|
|
|
|
// init upate info
|
|
this->updatesChanged();
|
|
}
|
|
|
|
CInstallXSwiftBusComponent::~CInstallXSwiftBusComponent()
|
|
{ }
|
|
|
|
void CInstallXSwiftBusComponent::setDefaultDownloadName(const QString &defaultDownload)
|
|
{
|
|
m_defaultDownloadName = defaultDownload;
|
|
}
|
|
|
|
void CInstallXSwiftBusComponent::selectPluginDirectory()
|
|
{
|
|
QString xPlanePluginDir = CFileUtils::fixWindowsUncPath(ui->le_XSwiftBusPluginDir->text().trimmed());
|
|
xPlanePluginDir = QFileDialog::getExistingDirectory(parentWidget(),
|
|
tr("Choose your X-Plane plugin directory"), xPlanePluginDir, m_fileDialogOptions);
|
|
|
|
if (xPlanePluginDir.isEmpty()) { return; } // canceled
|
|
if (!QDir(xPlanePluginDir).exists())
|
|
{
|
|
const CStatusMessage msg = CStatusMessage(this, CLogCategory::validation()).warning("'%1' is not a valid X-Plane plugin directory") << xPlanePluginDir;
|
|
this->showOverlayMessage(msg, CInstallXSwiftBusComponent::OverlayMsgTimeoutMs);
|
|
return;
|
|
}
|
|
ui->le_XSwiftBusPluginDir->setText(xPlanePluginDir);
|
|
}
|
|
|
|
void CInstallXSwiftBusComponent::selectDownloadDirectory()
|
|
{
|
|
QString downloadDir = CFileUtils::fixWindowsUncPath(ui->le_DownloadDir->text().trimmed());
|
|
downloadDir = QFileDialog::getExistingDirectory(parentWidget(),
|
|
tr("Choose your X-Plane plugin directory"), downloadDir, m_fileDialogOptions);
|
|
|
|
if (downloadDir.isEmpty()) { return; } // canceled
|
|
if (!QDir(downloadDir).exists())
|
|
{
|
|
const CStatusMessage msg = CStatusMessage(this, CLogCategory::validation()).warning("'%1' is not a valid download directory") << downloadDir;
|
|
this->showOverlayMessage(msg, CInstallXSwiftBusComponent::OverlayMsgTimeoutMs);
|
|
return;
|
|
}
|
|
ui->le_DownloadDir->setText(downloadDir);
|
|
}
|
|
|
|
void CInstallXSwiftBusComponent::installXSwiftBus()
|
|
{
|
|
const CRemoteFile rf = this->getRemoteFileSelected();
|
|
const QString downloadFileName = CFileUtils::appendFilePathsAndFixUnc(this->downloadDir(), rf.getName());
|
|
QFile downloadFile(downloadFileName);
|
|
if (!downloadFile.exists())
|
|
{
|
|
const CStatusMessage msg = CStatusMessage(this, CLogCategory::validation()).error("Cannot read downloaded file '%1'") << downloadFileName;
|
|
this->showOverlayMessage(msg, CInstallXSwiftBusComponent::OverlayMsgTimeoutMs);
|
|
return;
|
|
}
|
|
|
|
const QString xSwiftBusDirectory = this->xSwiftBusDir();
|
|
if (xSwiftBusDirectory.isEmpty())
|
|
{
|
|
const CStatusMessage msg = CStatusMessage(this, CLogCategory::validation()).error("No directory to install to'");
|
|
this->showOverlayMessage(msg, CInstallXSwiftBusComponent::OverlayMsgTimeoutMs);
|
|
return;
|
|
}
|
|
|
|
const QDir installDir(xSwiftBusDirectory);
|
|
if (!installDir.exists())
|
|
{
|
|
const CStatusMessage msg = CStatusMessage(this, CLogCategory::validation()).error("Directory '%1' does not exist") << xSwiftBusDirectory;
|
|
this->showOverlayMessage(msg, CInstallXSwiftBusComponent::OverlayMsgTimeoutMs);
|
|
return;
|
|
}
|
|
|
|
const QString destFileName = CFileUtils::appendFilePathsAndFixUnc(xSwiftBusDirectory, rf.getName());
|
|
{
|
|
QFile destFile(destFileName);
|
|
if (destFile.exists())
|
|
{
|
|
const bool removed = destFile.remove();
|
|
if (!removed)
|
|
{
|
|
const CStatusMessage msg = CStatusMessage(this, CLogCategory::validation()).error("Cannot remove '%1'") << destFileName;
|
|
this->showOverlayMessage(msg, CInstallXSwiftBusComponent::OverlayMsgTimeoutMs);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
const bool copied = QFile::copy(downloadFileName, destFileName);
|
|
if (!copied)
|
|
{
|
|
const CStatusMessage msg = CStatusMessage(this, CLogCategory::validation()).error("Cannot copy '%1' to '%2'") << downloadFileName << destFileName;
|
|
this->showOverlayMessage(msg, CInstallXSwiftBusComponent::OverlayMsgTimeoutMs);
|
|
return;
|
|
}
|
|
|
|
// we need to unzip the destination file
|
|
const QFileInfo destFile(destFileName);
|
|
if (!destFile.exists())
|
|
{
|
|
const CStatusMessage msg = CStatusMessage(this, CLogCategory::validation()).error("XSwiftBus file '%1' does not exist") << destFileName;
|
|
this->showOverlayMessage(msg, CInstallXSwiftBusComponent::OverlayMsgTimeoutMs);
|
|
return;
|
|
}
|
|
|
|
// if possible we will unzip
|
|
QStringList stdOutAndError;
|
|
if (CCompressUtils::zip7Uncompress(destFile.absoluteFilePath(), xSwiftBusDirectory, &stdOutAndError))
|
|
{
|
|
// capture values by copy!
|
|
const CStatusMessage msg = CStatusMessage(this, CLogCategory::validation()).info("Uncompressed xSwiftBus in '%1'") << xSwiftBusDirectory;
|
|
this->showOverlayMessagesWithConfirmation(msg, false, "Delete downloaded file?", [ = ]
|
|
{
|
|
QFile downloadFile(downloadFileName);
|
|
if (!downloadFile.exists()) { return; } // removed in meantime
|
|
const bool removed = downloadFile.remove();
|
|
Q_UNUSED(removed);
|
|
});
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
const CStatusMessage msg = CStatusMessage(this, CLogCategory::validation()).warning("Unzip failed: stdout '%1' stderr '%2'") << safeAt(stdOutAndError, 0) << safeAt(stdOutAndError, 1);
|
|
this->showOverlayMessage(msg);
|
|
}
|
|
|
|
//! fixme Ref T253, once we have a zip library we will directly unzip
|
|
const QMessageBox::StandardButton reply = QMessageBox::question(this,
|
|
"Install swiftXDBus",
|
|
"You need to manually unzip XSwiftBus into the plugins directory.\nIt needs to look like 'plugin/xswiftbus'.\n\nOpen the archive?",
|
|
QMessageBox::Yes | QMessageBox::No);
|
|
|
|
if (reply == QMessageBox::Yes)
|
|
{
|
|
QDesktopServices::openUrl(QUrl::fromLocalFile(destFile.absoluteFilePath()));
|
|
}
|
|
}
|
|
|
|
void CInstallXSwiftBusComponent::triggerDownloadingOfXSwiftBusFile()
|
|
{
|
|
if (!sGui || !sGui->hasWebDataServices() || sGui->isShuttingDown()) { return; }
|
|
if (!this->existsDownloadDir())
|
|
{
|
|
const CStatusMessage msg = CStatusMessage(this, CLogCategory::validation()).error("Invalid download directory");
|
|
this->showOverlayMessage(msg, CInstallXSwiftBusComponent::OverlayMsgTimeoutMs);
|
|
return;
|
|
}
|
|
|
|
const CRemoteFile rf = this->getRemoteFileSelected();
|
|
const CUrl download = rf.getSmartUrl();
|
|
if (download.isEmpty())
|
|
{
|
|
const CStatusMessage msg = CStatusMessage(this, CLogCategory::validation()).error("No download URL for file name '%1'") << rf.getNameAndSize();
|
|
this->showOverlayMessage(msg, CInstallXSwiftBusComponent::OverlayMsgTimeoutMs);
|
|
return;
|
|
}
|
|
|
|
const QString saveAsFile = CFileUtils::appendFilePathsAndFixUnc(ui->le_DownloadDir->text(), rf.getName());
|
|
const QFile saveFile(saveAsFile);
|
|
if (saveFile.exists())
|
|
{
|
|
const QMessageBox::StandardButton reply = QMessageBox::question(this,
|
|
"The file already exists",
|
|
"Do you want to use the existing '" + saveAsFile + "'?",
|
|
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
|
|
if (reply == QMessageBox::Cancel) { return; }
|
|
if (reply == QMessageBox::Yes)
|
|
{
|
|
const CStatusMessage msg = CStatusMessage(this).info("Using existing file '%1'") << saveAsFile;
|
|
const QPointer<CInstallXSwiftBusComponent> guard(this);
|
|
QTimer::singleShot(100, this, [ = ]
|
|
{
|
|
if (guard.isNull()) { return; }
|
|
this->downloadedXSwiftBusFile(msg);
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
|
|
const QNetworkReply *r = sGui->downloadFromNetwork(download, saveAsFile, { this, &CInstallXSwiftBusComponent::downloadedXSwiftBusFile});
|
|
if (r)
|
|
{
|
|
CLogMessage(this).info("Triggered downloading of XSwiftBus file from '%1'") << download.getHost();
|
|
this->showLoading(120 * 1000); // timeout in any case
|
|
}
|
|
else
|
|
{
|
|
const CStatusMessage msg = CStatusMessage(this, CLogCategory::validation()).error("Starting download for '%1' failed") << download.getFullUrl();
|
|
this->showOverlayMessage(msg, CInstallXSwiftBusComponent::OverlayMsgTimeoutMs);
|
|
}
|
|
}
|
|
|
|
void CInstallXSwiftBusComponent::downloadedXSwiftBusFile(const CStatusMessage &status)
|
|
{
|
|
this->hideLoading();
|
|
if (sGui && sGui->isShuttingDown()) { return; }
|
|
if (status.isWarningOrAbove())
|
|
{
|
|
this->showOverlayMessage(status);
|
|
return;
|
|
}
|
|
if (!this->existsXSwiftBusPluginDir())
|
|
{
|
|
const CStatusMessage msg = CStatusMessage(this).warning("No valid install directory, cannot continue.");
|
|
this->showOverlayMessage(msg);
|
|
return;
|
|
}
|
|
|
|
static const QString confirm("Install in '%1'?");
|
|
this->showOverlayMessagesWithConfirmation(status, false, confirm.arg(ui->le_XSwiftBusPluginDir->text()), [ = ]
|
|
{
|
|
QTimer::singleShot(0, this, &CInstallXSwiftBusComponent::installXSwiftBus);
|
|
});
|
|
}
|
|
|
|
CRemoteFile CInstallXSwiftBusComponent::getRemoteFileSelected() const
|
|
{
|
|
const QString fileNameAndSize = ui->cb_DownloadFile->currentText();
|
|
const CUpdateInfo update = m_updates.get();
|
|
const CRemoteFileList remoteFiles = update.getArtifactsXSwiftBus().asRemoteFiles();
|
|
return remoteFiles.findFirstByMatchingNameOrDefault(fileNameAndSize);
|
|
}
|
|
|
|
QString CInstallXSwiftBusComponent::downloadDir() const
|
|
{
|
|
return CFileUtils::fixWindowsUncPath(ui->le_DownloadDir->text().trimmed());
|
|
}
|
|
|
|
QString CInstallXSwiftBusComponent::xSwiftBusDir() const
|
|
{
|
|
return CFileUtils::fixWindowsUncPath(ui->le_XSwiftBusPluginDir->text().trimmed());
|
|
}
|
|
|
|
bool CInstallXSwiftBusComponent::existsDownloadDir() const
|
|
{
|
|
const QDir dir(this->downloadDir());
|
|
return dir.exists() && dir.isReadable();
|
|
}
|
|
|
|
bool CInstallXSwiftBusComponent::existsXSwiftBusPluginDir() const
|
|
{
|
|
const QDir dir(this->xSwiftBusDir());
|
|
return dir.exists() && dir.isReadable();
|
|
}
|
|
|
|
QString CInstallXSwiftBusComponent::getXPlanePluginDirectory() const
|
|
{
|
|
const CXPlaneSimulatorSettings settings = m_simulatorSettings.getSettings(CSimulatorInfo::XPLANE);
|
|
return settings.getPluginDirOrDefault();
|
|
}
|
|
|
|
void CInstallXSwiftBusComponent::updatesChanged()
|
|
{
|
|
const CUpdateInfo updateInfo = m_updates.get();
|
|
if (updateInfo.getArtifactsXSwiftBus().isEmpty()) { return; }
|
|
const CArtifactList artifacts = updateInfo.getArtifactsXSwiftBusLatestVersionFirst().findWithUnrestrictedDistributions();
|
|
if (artifacts.isEmpty()) { return; }
|
|
|
|
const CRemoteFileList remoteFiles = artifacts.asRemoteFiles();
|
|
if (!remoteFiles.isEmpty())
|
|
{
|
|
const QStringList xSwiftBusFiles(remoteFiles.getNamesPlusSize(false));
|
|
ui->cb_DownloadFile->addItems(xSwiftBusFiles);
|
|
|
|
// current text
|
|
QString current;
|
|
if (!m_defaultDownloadName.isEmpty())
|
|
{
|
|
const CRemoteFile rf = remoteFiles.findFirstByMatchingNameOrDefault(m_defaultDownloadName);
|
|
current = rf.getNameAndSize();
|
|
}
|
|
ui->cb_DownloadFile->setCurrentText(
|
|
current.isEmpty() ?
|
|
remoteFiles.frontOrDefault().getNameAndSize() :
|
|
current
|
|
); // latest version
|
|
}
|
|
ui->cb_DownloadFile->setEnabled(!remoteFiles.isEmpty());
|
|
}
|
|
|
|
void CInstallXSwiftBusComponent::openInstallDir()
|
|
{
|
|
if (!this->existsXSwiftBusPluginDir()) { return; }
|
|
const QString file = CFileUtils::fixWindowsUncPath(ui->le_XSwiftBusPluginDir->text());
|
|
QDesktopServices::openUrl(QUrl::fromLocalFile(file));
|
|
}
|
|
|
|
void CInstallXSwiftBusComponent::openDownloadDir()
|
|
{
|
|
if (!this->existsDownloadDir()) { return; }
|
|
const QString file = CFileUtils::fixWindowsUncPath(ui->le_DownloadDir->text());
|
|
QDesktopServices::openUrl(QUrl::fromLocalFile(file));
|
|
}
|
|
|
|
bool CInstallXSwiftBusWizardPage::validatePage()
|
|
{
|
|
return true;
|
|
}
|
|
} // ns
|
|
} // ns
|