6 #include <QDesktopServices>
11 #include <QStandardPaths>
14 #include "ui_downloadcomponent.h"
24 using namespace swift::config;
26 using namespace swift::misc::db;
27 using namespace swift::misc::network;
28 using namespace swift::misc::simulation;
32 CDownloadComponent::CDownloadComponent(QWidget *parent)
39 ui->le_DownloadDir->setText(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
40 ui->prb_Current->setMinimum(0);
41 ui->prb_Current->setMaximum(1);
42 ui->prb_Current->setValue(0);
43 ui->prb_Total->setMinimum(0);
44 ui->prb_Total->setMaximum(1);
45 ui->prb_Total->setValue(0);
47 connect(ui->tb_DialogDownloadDir, &QToolButton::pressed,
this, &CDownloadComponent::selectDownloadDirectory);
48 connect(ui->tb_ResetDownloadDir, &QToolButton::pressed,
this, &CDownloadComponent::resetDownloadDir);
50 connect(ui->pb_Download, &QPushButton::pressed, [=] { this->triggerDownloadingOfFiles(); });
51 connect(ui->pb_OpenDownloadDir, &QPushButton::pressed,
this, &CDownloadComponent::openDownloadDir);
52 connect(ui->pb_Launch, &QPushButton::pressed,
this, &CDownloadComponent::startDownloadedExecutable);
64 if (!m_waitingForDownload.
isEmpty()) {
return false; }
65 m_remoteFiles = remoteFiles;
73 if (!d.exists())
return false;
74 ui->le_DownloadDir->setText(d.absolutePath());
78 void CDownloadComponent::selectDownloadDirectory()
80 QString downloadDir = ui->le_DownloadDir->text().trimmed();
81 downloadDir = QFileDialog::getExistingDirectory(parentWidget(), tr(
"Choose your download directory"),
82 downloadDir, m_fileDialogOptions);
84 if (downloadDir.isEmpty()) {
return; }
85 if (!QDir(downloadDir).exists())
93 ui->le_DownloadDir->setText(downloadDir);
98 ui->pb_Download->setEnabled(
false);
99 ui->pb_Launch->setEnabled(
false);
100 if (m_remoteFiles.
isEmpty()) {
return false; }
101 if (!m_waitingForDownload.
isEmpty()) {
return false; }
104 const QPointer<CDownloadComponent> myself(
this);
107 this->triggerDownloadingOfFiles();
111 m_waitingForDownload = m_remoteFiles;
112 this->showFileInfo();
113 return this->triggerDownloadingOfNextFile();
121 if (!m_waitingForDownload.
isEmpty()) {
return false; }
146 m_waitingForDownload.
clear();
149 ui->prb_Current->setValue(0);
150 ui->prb_Total->setValue(0);
152 ui->le_Completed->clear();
153 ui->le_CompletedNumber->clear();
154 ui->le_CompletedUrl->clear();
155 ui->le_Started->clear();
156 ui->le_StartedNumber->clear();
157 ui->le_StartedUrl->clear();
158 this->showFileInfo();
159 ui->pb_Download->setEnabled(
true);
162 bool CDownloadComponent::triggerDownloadingOfNextFile()
164 if (m_waitingForDownload.
isEmpty()) {
return false; }
167 return this->triggerDownloadingOfFile(rf);
170 bool CDownloadComponent::triggerDownloadingOfFile(
const CRemoteFile &remoteFile)
173 if (!this->existsDownloadDir())
185 CStatusMessage(
this, CLogCategories::validation()).
error(u
"No download URL for file name '%1'")
191 this->showStartedFileMessage(remoteFile);
192 m_fileInProgress = remoteFile;
193 const QString saveAsFile = CFileUtils::appendFilePaths(ui->le_DownloadDir->text(), remoteFile.
getBaseName());
194 const QFileInfo fiSaveAs(saveAsFile);
195 if (fiSaveAs.exists())
197 const QString msg = QStringLiteral(
"File '%1' already exists locally.\n\nDo you want to reload the file?")
198 .arg(fiSaveAs.absoluteFilePath());
199 QMessageBox::StandardButton reply =
200 QMessageBox::question(
this,
"File exists", msg, QMessageBox::Yes | QMessageBox::No);
201 if (reply != QMessageBox::Yes)
203 const QPointer<CDownloadComponent> myself(
this);
206 this->downloadedFile(
CStatusMessage(
this).info(u
"File was already downloaded"));
212 QNetworkReply *reply =
214 bool success =
false;
219 connect(reply, &QNetworkReply::downloadProgress,
this, &CDownloadComponent::downloadProgress,
220 Qt::QueuedConnection);
227 CStatusMessage(
this, CLogCategories::validation()).
error(u
"Starting download for '%1' failed")
234 void CDownloadComponent::downloadedFile(
const CStatusMessage &status)
237 const CRemoteFile justDownloaded(m_fileInProgress);
240 this->showCompletedFileMessage(justDownloaded);
251 const bool t = this->triggerDownloadingOfNextFile();
252 if (!t) { this->lastFileDownloaded(); }
255 void CDownloadComponent::lastFileDownloaded()
257 const QPointer<CDownloadComponent> myself(
this);
260 myself->ui->pb_Download->setEnabled(
true);
261 myself->ui->pb_Launch->setEnabled(
true);
264 this->startDownloadedExecutable();
267 void CDownloadComponent::startDownloadedExecutable()
269 if (!ui->cb_StartAfterDownload->isChecked()) {
return; }
272 if (executables.
isEmpty()) {
return; }
275 const QDir dir(ui->le_DownloadDir->text());
276 if (!dir.exists()) {
return; }
279 if (CBuildConfig::isRunningOnMacOSPlatform())
281 msg =
"To install close swift, "
282 "mount the disk image '%1' and run the installer inside "
283 "to proceed with the update.";
285 else { msg = ui->cb_Shutdown->isChecked() ? QString(
"Start '%1' and close swift?") : QString(
"Start '%1'?"); }
289 const QString executable = CFileUtils::appendFilePaths(dir.absolutePath(), rf.
getBaseName());
290 QFile executableFile(executable);
291 if (!executableFile.exists()) {
continue; }
293 QMessageBox::StandardButton reply =
294 QMessageBox::question(
this,
"Start?", msg.arg(rf.
getName()), QMessageBox::Yes | QMessageBox::No);
295 if (reply != QMessageBox::Yes) {
return; }
298 if (!CPlatform::canRunOnCurrentPlatform(p))
302 ui->pb_OpenDownloadDir->click();
306 if (CBuildConfig::isRunningOnLinuxPlatform() && !executableFile.permissions().testFlag(QFile::ExeOwner))
308 executableFile.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner |
309 QFile::ReadGroup | QFile::ExeGroup | QFile::ReadOther | QFile::ExeOther);
312 const bool shutdown = ui->cb_Shutdown->isChecked();
313 const bool started = QProcess::startDetached(executable, {}, dir.absolutePath());
314 if (started && shutdown &&
sGui)
317 if (!
sGui) {
return; }
325 bool CDownloadComponent::existsDownloadDir()
const
327 if (ui->le_DownloadDir->text().isEmpty()) {
return false; }
328 const QDir dir(ui->le_DownloadDir->text());
329 return dir.exists() && dir.isReadable();
332 void CDownloadComponent::openDownloadDir()
334 if (!this->existsDownloadDir()) {
return; }
335 QDesktopServices::openUrl(QUrl::fromLocalFile(ui->le_DownloadDir->text()));
338 void CDownloadComponent::resetDownloadDir()
340 ui->le_DownloadDir->setText(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
343 void CDownloadComponent::showStartedFileMessage(
const CRemoteFile &rf)
345 const int current = m_remoteFiles.
size() - m_waitingForDownload.
size();
347 ui->le_StartedNumber->setText(QStringLiteral(
"%1/%2").arg(current).arg(m_remoteFiles.
size()));
349 ui->prb_Total->setMaximum(m_remoteFiles.
size());
350 ui->prb_Total->setValue(current - 1);
353 void CDownloadComponent::showCompletedFileMessage(
const CRemoteFile &rf)
355 const int current = m_remoteFiles.
size() - m_waitingForDownload.
size();
357 ui->le_CompletedNumber->setText(QStringLiteral(
"%1/%2").arg(current).arg(m_remoteFiles.
size()));
359 ui->prb_Total->setMaximum(m_remoteFiles.
size());
360 ui->prb_Total->setValue(current);
365 void CDownloadComponent::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
367 ui->prb_Current->setMaximum(
static_cast<int>(bytesTotal));
368 ui->prb_Current->setValue(
static_cast<int>(bytesReceived));
371 void CDownloadComponent::showFileInfo()
373 ui->le_Info->setText(QStringLiteral(
"Files: %1 size: %2")
374 .arg(m_remoteFiles.
size())
QNetworkReply * downloadFromNetwork(const swift::misc::network::CUrl &url, const QString &saveAsFileName, const swift::misc::CSlot< void(const swift::misc::CStatusMessage &)> &callback, int maxRedirects=DefaultMaxRedirects)
Download file from network and store it as passed.
bool hasWebDataServices() const
Web data services available?
bool isShuttingDown() const
Is application shutting down?
static void exit(int retcode=0)
Exit application, perform graceful shutdown and exit.
Enable widget class for load indicator.
void hideLoading()
Hide load indicator.
bool showOverlayMessage(const swift::misc::CStatusMessage &message, std::chrono::milliseconds timeout=std::chrono::milliseconds(0))
Show single message.
void setForceSmall(bool force)
Force small (smaller layout)
void setOverlaySizeFactors(double widthFactor, double heightFactor, double middleFactor=2)
Set the size factors.
Using this class provides a QFrame with the overlay functionality already integrated.
@ ShutdownSwift
for installers, stop swift before running
@ StartAfterDownload
download, then install
@ JustDownload
download, that's it
bool triggerDownloadingOfFiles(int delayMs=-1)
Trigger downloading of the file.
bool setDownloadFile(const swift::misc::network::CRemoteFile &remoteFile)
Set file to be downloaded.
void allDownloadsCompleted()
All downloads have been completed.
virtual ~CDownloadComponent()
Dtor.
void clear()
Clear all values.
bool haveAllDownloadsCompleted() const
Have all downloads completed?
bool setDownloadDirectory(const QString &path)
Set donwload directory.
Mode getMode() const
Get the mode.
bool isDownloading() const
Downloads in progress.
void setMode(Mode mode)
Set the mode.
bool setDownloadFiles(const swift::misc::network::CRemoteFileList &remoteFiles)
Set files to be downloaded.
void cancelOngoingDownloads()
Cancel ongoing downloads.
Class for emitting a log message.
Derived & warning(const char16_t(&format)[N])
Set the severity to warning, providing a format string.
Derived & error(const char16_t(&format)[N])
Set the severity to error, providing a format string.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
size_type size() const
Returns number of elements in the sequence.
reference front()
Access the first element.
void clear()
Removes all elements in the sequence.
bool isEmpty() const
Synonym for empty.
void pop_front()
Removes an element at the front of the sequence.
Streamable status message, e.g.
bool isWarningOrAbove() const
Warning or above.
QString getBaseName() const
Name with directory stripped.
CUrl getSmartUrl() const
Automatically concatenates the name if missing.
const CUrl & getUrl() const
Get URL.
bool hasName() const
Has name?
QString getBaseNameAndSize() const
Name + human readable size.
const QString & getName() const
Name.
Value object encapsulating a list of remote files.
QString getTotalFileSizeHumanReadable() const
Size formatted.
CRemoteFileList findExecutableFiles() const
Find all executable files (decided by appendix)
Value object encapsulating information of a location, kind of simplified CValueObject compliant versi...
bool isEmpty() const
Empty.
const QString & getHost() const
Get host.
QString getFullUrl(bool withQuery=true) const
Qualified name.
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
High level reusable GUI components.
Free functions in swift::misc.
auto singleShot(int msec, QObject *target, F &&task)
Starts a single-shot timer which will call a task in the thread of the given object when it times out...