#include "dlg_update.h" #include "../../../client/settings/cache_settings.h" #include "../client/network/update/client/client_update_checker.h" #include "../client/network/update/client/release_channel.h" #include "../interface/window_main.h" #include #include #include #include #include #include #include #include #include #include DlgUpdate::DlgUpdate(QWidget *parent) : QDialog(parent) { // Handle layout statusLabel = new QLabel(this); statusLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); statusLabel->setWordWrap(true); descriptionLabel = new QLabel(tr("Current release channel") + QString(": %1").arg(tr(SettingsCache::instance().getUpdateReleaseChannel()->getName().toUtf8())), this); progress = new QProgressBar(this); buttonBox = new QDialogButtonBox(this); buttonBox->setFixedWidth(350); ok = new QPushButton("Close", this); manualDownload = new QPushButton(tr("Reinstall"), this); stopDownload = new QPushButton(tr("Cancel Download"), this); gotoDownload = new QPushButton(tr("Open Download Page"), this); addStopDownloadAndRemoveOthers(false); // Add all buttons to box enableUpdateButton(false); // Unless we know there's an update available, you can't install buttonBox->addButton(ok, QDialogButtonBox::AcceptRole); connect(gotoDownload, &QPushButton::clicked, this, &DlgUpdate::gotoDownloadPage); // TODO: make reinstall button actually do something when clicked // connect(manualDownload, &QPushButton::clicked, this, &DlgUpdate::downloadUpdate); connect(stopDownload, &QPushButton::clicked, this, &DlgUpdate::cancelDownload); connect(ok, &QPushButton::clicked, this, &DlgUpdate::closeDialog); auto *parentLayout = new QVBoxLayout(this); parentLayout->addWidget(descriptionLabel); parentLayout->addWidget(statusLabel); parentLayout->addWidget(progress); parentLayout->addWidget(buttonBox); setLayout(parentLayout); setWindowTitle(tr("Check for Client Updates")); setFixedHeight(this->sizeHint().height()); setFixedWidth(this->sizeHint().width()); // Check for SSL (this probably isn't necessary) if (!QSslSocket::supportsSsl()) { enableUpdateButton(false); QMessageBox::critical(this, tr("Error"), tr("Cockatrice was not built with SSL support, therefore you cannot download updates " "automatically! \nPlease visit the download page to update manually.")); } // Initialize the checker and downloader class uDownloader = new UpdateDownloader(this); connect(uDownloader, &UpdateDownloader::downloadSuccessful, this, &DlgUpdate::downloadSuccessful); connect(uDownloader, &UpdateDownloader::progressMade, this, &DlgUpdate::downloadProgressMade); connect(uDownloader, &UpdateDownloader::error, this, &DlgUpdate::downloadError); // Check for updates beginUpdateCheck(); } void DlgUpdate::closeDialog() { accept(); } void DlgUpdate::gotoDownloadPage() { QDesktopServices::openUrl(SettingsCache::instance().getUpdateReleaseChannel()->getManualDownloadUrl()); } void DlgUpdate::downloadUpdate(const QString &releaseName) { setLabel(tr("Downloading update: %1").arg(releaseName)); addStopDownloadAndRemoveOthers(true); // Will remove all other buttons uDownloader->beginDownload(updateUrl); } void DlgUpdate::cancelDownload() { emit uDownloader->stopDownload(); setLabel("Download canceled"); addStopDownloadAndRemoveOthers(false); downloadProgressMade(0, 1); } void DlgUpdate::beginUpdateCheck() { progress->setMinimum(0); progress->setMaximum(0); setLabel(tr("Checking for updates...")); auto checker = new ClientUpdateChecker(this); connect(checker, &ClientUpdateChecker::finishedCheck, this, &DlgUpdate::finishedUpdateCheck); connect(checker, &ClientUpdateChecker::error, this, &DlgUpdate::updateCheckError); checker->check(); } void DlgUpdate::finishedUpdateCheck(bool needToUpdate, bool isCompatible, Release *release) { QString publishDate, versionName; // Update the UI to say we've finished progress->setMaximum(100); setLabel(tr("Finished checking for updates")); // If there are no available builds, then they can't auto update. enableUpdateButton(isCompatible); if (isCompatible) { // If there is an update, save its URL and work out its name updateUrl = release->getDownloadUrl(); } // Give the user the appropriate message if (!needToUpdate) { // If there's no need to update, tell them that. However we still allow them to run the // downloader themselves if there's a compatible build QMessageBox::information( this, tr("No Update Available"), tr("Cockatrice is up to date!") + "

" + tr("You are already running the latest version available in the chosen release channel.") + "
" + "" + tr("Current version") + QString(": %1
").arg(VERSION_STRING) + "" + tr("Selected release channel") + QString(": %1").arg(tr(SettingsCache::instance().getUpdateReleaseChannel()->getName().toUtf8()))); return; } publishDate = release->getPublishDate().toString(QLocale().dateFormat(QLocale::LongFormat)); if (isCompatible) { int reply; reply = QMessageBox::question( this, tr("Update Available"), tr("A new version of Cockatrice is available!") + "

" + "" + tr("New version") + QString(": %1
").arg(release->getName()) + "" + tr("Released") + QString(": %1 (").arg(publishDate, release->getDescriptionUrl()) + tr("Changelog") + ")

" + tr("Do you want to update now?"), QMessageBox::Yes | QMessageBox::No); if (reply == QMessageBox::Yes) downloadUpdate(release->getName()); } else { QMessageBox::information( this, tr("Update Available"), tr("A new version of Cockatrice is available!") + "

" + "" + tr("New version") + QString(": %1
").arg(release->getName()) + "" + tr("Released") + QString(": %1 (").arg(publishDate, release->getDescriptionUrl()) + tr("Changelog") + ")

" + tr("Unfortunately, the automatic updater failed to find a compatible download. \nYou may have to " "manually download the new version.") + "

" + tr("Please check the releases page on our Github and download the build for your " "system.") .arg(release->getDescriptionUrl())); } } void DlgUpdate::enableUpdateButton(bool enable) { manualDownload->setEnabled(enable); } void DlgUpdate::addStopDownloadAndRemoveOthers(bool enable) { if (enable) { buttonBox->addButton(stopDownload, QDialogButtonBox::ActionRole); buttonBox->removeButton(manualDownload); buttonBox->removeButton(gotoDownload); } else { buttonBox->removeButton(stopDownload); buttonBox->addButton(manualDownload, QDialogButtonBox::ActionRole); buttonBox->addButton(gotoDownload, QDialogButtonBox::ActionRole); } } void DlgUpdate::enableOkButton(bool enable) { ok->setEnabled(enable); } void DlgUpdate::setLabel(const QString &newText) { statusLabel->setText(newText); } void DlgUpdate::updateCheckError(const QString &errorString) { setLabel(tr("Error")); QMessageBox::critical(this, tr("Update Error"), tr("An error occurred while checking for updates:") + QString(" ") + errorString); } void DlgUpdate::downloadError(const QString &errorString) { setLabel(tr("Error")); enableUpdateButton(true); QMessageBox::critical(this, tr("Update Error"), tr("An error occurred while downloading an update:") + QString(" ") + errorString); } void DlgUpdate::downloadSuccessful(const QUrl &filepath) { setLabel(tr("Installing...")); // Try to open the installer. If it opens, quit Cockatrice if (QDesktopServices::openUrl(filepath)) { QMetaObject::invokeMethod(static_cast(parent()), "close", Qt::QueuedConnection); qCInfo(DlgUpdateLog) << "Opened downloaded update file successfully - closing Cockatrice"; close(); } else { setLabel(tr("Error")); QMessageBox::critical(this, tr("Update Error"), tr("Cockatrice is unable to open the installer.") + "

" + tr("Try to update manually by closing Cockatrice and running the installer.") + "
" + tr("Download location") + QString(": %1").arg(filepath.toLocalFile())); } } void DlgUpdate::downloadProgressMade(qint64 bytesRead, qint64 totalBytes) { progress->setMaximum(totalBytes); progress->setValue(bytesRead); }