diff options
author | Fabian Müller <fmueller@owncloud.com> | 2022-01-21 02:54:40 +0300 |
---|---|---|
committer | Hannah von Reth <vonreth@kde.org> | 2022-03-14 16:23:05 +0300 |
commit | d762e822ec35b99f9907c4a1e62d54f21020a4f0 (patch) | |
tree | 31009adf9813b131bcde778aba41b5f0f3b240af /src/gui/updater | |
parent | d76f27f19ee91d4018dc2b407fb6516cc2d535f0 (diff) |
Ask user whether to update or not
TODO: remember whether "skip update" button was pushed
Diffstat (limited to 'src/gui/updater')
-rw-r--r-- | src/gui/updater/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/gui/updater/appimageupdateavailabledialog.cpp | 66 | ||||
-rw-r--r-- | src/gui/updater/appimageupdateavailabledialog.h | 49 | ||||
-rw-r--r-- | src/gui/updater/appimageupdateavailabledialog.ui | 185 | ||||
-rw-r--r-- | src/gui/updater/appimageupdater.cpp | 52 |
5 files changed, 340 insertions, 15 deletions
diff --git a/src/gui/updater/CMakeLists.txt b/src/gui/updater/CMakeLists.txt index 0f8021962..e0d36e984 100644 --- a/src/gui/updater/CMakeLists.txt +++ b/src/gui/updater/CMakeLists.txt @@ -33,6 +33,9 @@ if(WITH_APPIMAGEUPDATER) message(STATUS "Including built-in libappimageupdate based updater") set(appimageupdater_sources + ${CMAKE_CURRENT_SOURCE_DIR}/appimageupdateavailabledialog.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/appimageupdateavailabledialog.h + ${CMAKE_CURRENT_SOURCE_DIR}/appimageupdateavailabledialog.ui ${CMAKE_CURRENT_SOURCE_DIR}/appimageupdater.cpp ${CMAKE_CURRENT_SOURCE_DIR}/appimageupdater.h ) diff --git a/src/gui/updater/appimageupdateavailabledialog.cpp b/src/gui/updater/appimageupdateavailabledialog.cpp new file mode 100644 index 000000000..13096e6ae --- /dev/null +++ b/src/gui/updater/appimageupdateavailabledialog.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2022 by Fabian Müller <fmueller@owncloud.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. + */ + +#include "appimageupdateavailabledialog.h" +#include <QStyle> + +#include "guiutility.h" +#include "theme.h" +#include "ui_appimageupdateavailabledialog.h" + +namespace OCC::Ui { + +AppImageUpdateAvailableDialog::AppImageUpdateAvailableDialog(const QVersionNumber ¤tVersion, const QVersionNumber &newVersion, QWidget *parent) + : QDialog(parent) + , _ui(new ::Ui::AppImageUpdateAvailableDialogUi) +{ + _ui->setupUi(this); + + setWindowIcon(style()->standardIcon(QStyle::SP_MessageBoxInformation)); + + // we want an immediate response from the user + setModal(true); + + const auto *theme = Theme::instance(); + + // the strings in the .ui file are not marked for translation, they're just placeholders + _ui->installedVersionLabel->setText(tr("Installed version: %1").arg(currentVersion.toString())); + _ui->availableVersionLabel->setText(tr("Available update: %1").arg(newVersion.toString())); + _ui->infoLabel->setText(tr("An update is available for this AppImage of %1. Do you want to install this update?\n\nThe update will be performed in the background, and overwrite the current AppImage file. You need to restart the app to complete the update.").arg(theme->appNameGUI())); + + _ui->appIconLabel->setPixmap(theme->aboutIcon().pixmap(QSize(128, 128))); + + // we use custom icons to ensure a unified look on all platforms + _ui->buttonBox->button(QDialogButtonBox::Ok)->setIcon(Utility::getCoreIcon(QStringLiteral("check"))); + _ui->buttonBox->button(QDialogButtonBox::Cancel)->setIcon(Utility::getCoreIcon(QStringLiteral("ban"))); + _ui->skipButton->setIcon(Utility::getCoreIcon(QStringLiteral("step-forward"))); + + // the minimum size of the info label (and a few other labels) depends on their contents + // we can't persuade the dialog to resize automatically to the recommended size in Qt Designer, so we do it manually + resize(sizeHint()); + // also, we want to prevent users from reducing the widget size too much, i.e., widgets would be hidden partially + setMinimumSize(sizeHint()); + + connect(_ui->skipButton, &QPushButton::clicked, this, [this]() { + emit skipUpdateButtonClicked(); + reject(); + }); +} + +AppImageUpdateAvailableDialog::~AppImageUpdateAvailableDialog() +{ + delete _ui; +} + +} diff --git a/src/gui/updater/appimageupdateavailabledialog.h b/src/gui/updater/appimageupdateavailabledialog.h new file mode 100644 index 000000000..9b6313c0b --- /dev/null +++ b/src/gui/updater/appimageupdateavailabledialog.h @@ -0,0 +1,49 @@ +/* +* Copyright (C) 2022 by Fabian Müller <fmueller@owncloud.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. + */ + +#pragma once + +#include <QDialog> +#include <QScopedPointer> +#include <QVersionNumber> + +namespace Ui { +class AppImageUpdateAvailableDialogUi; +} + +namespace OCC::Ui { + +/** + * @brief Dialog shown when updates for the running AppImage are available + * @ingroup gui + */ +class AppImageUpdateAvailableDialog : public QDialog +{ + Q_OBJECT +public: + explicit AppImageUpdateAvailableDialog(const QVersionNumber ¤tVersion, const QVersionNumber &newVersion, QWidget *parent = nullptr); + + ~AppImageUpdateAvailableDialog() override; + +signals: + /** + * Emitted when an update is explicitly skipped by the user. + */ + void skipUpdateButtonClicked(); + +private: + ::Ui::AppImageUpdateAvailableDialogUi *_ui; +}; + +} diff --git a/src/gui/updater/appimageupdateavailabledialog.ui b/src/gui/updater/appimageupdateavailabledialog.ui new file mode 100644 index 000000000..10b77efb3 --- /dev/null +++ b/src/gui/updater/appimageupdateavailabledialog.ui @@ -0,0 +1,185 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>AppImageUpdateAvailableDialogUi</class> + <widget class="QDialog" name="AppImageUpdateAvailableDialogUi"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>556</width> + <height>241</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string extracomment="AppImage update available dialog">Update available</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="sizeConstraint"> + <enum>QLayout::SetMinimumSize</enum> + </property> + <item> + <widget class="QLabel" name="appIconLabel"> + <property name="text"> + <string>TextLabel</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> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>6</number> + </property> + <item> + <widget class="QLabel" name="installedVersionLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string notr="true">Installed version:</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="availableVersionLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string notr="true">Available version:</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Minimum</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>10</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="infoLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>350</width> + <height>10</height> + </size> + </property> + <property name="text"> + <string notr="true">Info text placeholder</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="topMargin"> + <number>10</number> + </property> + <item> + <widget class="QPushButton" name="skipButton"> + <property name="text"> + <string>Skip this version</string> + </property> + </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> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>AppImageUpdateAvailableDialogUi</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>AppImageUpdateAvailableDialogUi</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> diff --git a/src/gui/updater/appimageupdater.cpp b/src/gui/updater/appimageupdater.cpp index d28b99a38..aaa1ec0f3 100644 --- a/src/gui/updater/appimageupdater.cpp +++ b/src/gui/updater/appimageupdater.cpp @@ -12,12 +12,18 @@ * for more details. */ +#include <QMessageBox> #include <QTimer> #include <appimage/update.h> #include <chrono> #include "appimageupdater.h" #include "common/version.h" +#include "theme.h" +#include "settingsdialog.h" + +#include "appimageupdateavailabledialog.h" +#include "application.h" using namespace OCC; using namespace std::chrono_literals; @@ -123,38 +129,54 @@ bool AppImageUpdater::handleStartup() void AppImageUpdater::versionInfoArrived(const UpdateInfo &info) { - if (info.version().isEmpty() || Version::versionWithBuildNumber() >= QVersionNumber::fromString(info.version())) { + const auto ¤tVersion = Version::versionWithBuildNumber(); + const auto newVersion = QVersionNumber::fromString(info.version()); + + if (info.version().isEmpty() || currentVersion >= newVersion) { qCInfo(lcUpdater) << "Client is on latest version!"; setDownloadState(UpToDate); return; } - const auto AppImageUpdaterShim = AppImageUpdaterShim::makeInstance(info.downloadUrl(), this); + const auto appImageUpdaterShim = AppImageUpdaterShim::makeInstance(info.downloadUrl(), this); - if (AppImageUpdaterShim == nullptr) { + if (appImageUpdaterShim == nullptr) { setDownloadState(DownloadFailed); return; } - if (!AppImageUpdaterShim->isUpdateAvailable()) { + if (!appImageUpdaterShim->isUpdateAvailable()) { qCCritical(lcUpdater) << "Update server reported that update is available, but AppImageUpdate disagrees, aborting"; setDownloadState(DownloadFailed); return; } - // binding AppImageUpdaterShim shared pointer to finished callback makes sure the updater is cleaned up when it's done - connect(AppImageUpdaterShim, &AppImageUpdaterShim::finished, this, [this](bool succeeded) { - if (succeeded) { - qCInfo(lcUpdater) << "AppImage update complete"; - setDownloadState(DownloadComplete); - } else { - qCInfo(lcUpdater) << "AppImage update failed"; - setDownloadState(DownloadFailed); - } + auto dialog = new Ui::AppImageUpdateAvailableDialog(currentVersion, newVersion, ocApp()->gui()->settingsDialog()); + + connect(dialog, &Ui::AppImageUpdateAvailableDialog::skipUpdateButtonClicked, this, [this]() { + qCInfo(lcUpdater) << "Update skipped by user"; + + // TODO: remember this setting + }); + + connect(dialog, &QDialog::accepted, this, [this, appImageUpdaterShim]() { + // binding AppImageUpdaterShim shared pointer to finished callback makes sure the updater is cleaned up when it's done + connect(appImageUpdaterShim, &AppImageUpdaterShim::finished, this, [this](bool succeeded) { + if (succeeded) { + qCInfo(lcUpdater) << "AppImage update complete"; + setDownloadState(DownloadComplete); + } else { + qCInfo(lcUpdater) << "AppImage update failed"; + setDownloadState(DownloadFailed); + } + }); + + setDownloadState(Downloading); + appImageUpdaterShim->startUpdateInBackground(); }); - setDownloadState(Downloading); - AppImageUpdaterShim->startUpdateInBackground(); + dialog->show(); + ownCloudGui::raiseDialog(dialog); } void AppImageUpdater::backgroundCheckForUpdate() |