diff --git a/VERSION.cmake b/VERSION.cmake index 50bd2dfc264c2..27bbf8f801af6 100644 --- a/VERSION.cmake +++ b/VERSION.cmake @@ -18,7 +18,7 @@ set(NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_MINOR 0) set(NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_PATCH 3) if ( NOT DEFINED MIRALL_VERSION_SUFFIX ) - set( MIRALL_VERSION_SUFFIX "git") #e.g. beta1, beta2, rc1 + set( MIRALL_VERSION_SUFFIX "daily") #e.g. beta1, beta2, rc1 endif( NOT DEFINED MIRALL_VERSION_SUFFIX ) if( NOT DEFINED MIRALL_VERSION_BUILD ) diff --git a/src/gui/generalsettings.cpp b/src/gui/generalsettings.cpp index b57745fc2c9b2..fee6efa1512e7 100644 --- a/src/gui/generalsettings.cpp +++ b/src/gui/generalsettings.cpp @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include @@ -190,8 +192,6 @@ GeneralSettings::GeneralSettings(QWidget *parent) }); loadMiscSettings(); - // updater info now set in: customizeStyle - //slotUpdateInfo(); // misc connect(_ui->monoIconsCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::saveMiscSettings); @@ -281,13 +281,44 @@ void GeneralSettings::loadMiscSettings() _ui->stopExistingFolderNowBigSyncCheckBox->setChecked(_ui->existingFolderLimitCheckBox->isChecked() && cfgFile.stopSyncingExistingFoldersOverLimit()); _ui->newExternalStorage->setChecked(cfgFile.confirmExternalStorage()); _ui->monoIconsCheckBox->setChecked(cfgFile.monoIcons()); + +#if defined(BUILD_UPDATER) + const auto updateChannelToLocalized = [](const QString &channel) { + if (channel == QStringLiteral("stable")) { + return tr("stable"); + } + + if (channel == QStringLiteral("beta")) { + return tr("beta"); + } + + if (channel == QStringLiteral("daily")) { + return tr("daily"); + } + + return QString{}; + }; + + _updateChannelGroup = new QButtonGroup(this); + auto position = _ui->updateChannelLayout->indexOf(_ui->updateChannelLabel); + for (const auto &channel : cfgFile.validUpdateChannels()) { + auto channelRadioButton = new QRadioButton(updateChannelToLocalized(channel), this); + _updateChannelGroup->addButton(channelRadioButton, cfgFile.validUpdateChannels().indexOf(channel)); + position++; + _ui->updateChannelLayout->insertWidget(position, channelRadioButton); + channelRadioButton->setChecked(cfgFile.currentUpdateChannel() == channel); + } + connect(_updateChannelGroup, &QButtonGroup::idClicked, this, &GeneralSettings::slotUpdateChannelChanged); + +#endif } #if defined(BUILD_UPDATER) void GeneralSettings::slotUpdateInfo() { + ConfigFile config; const auto updater = Updater::instance(); - if (ConfigFile().skipUpdateCheck() || !updater) { + if (config.skipUpdateCheck() || !updater) { // updater disabled on compile _ui->updatesContainer->setVisible(false); return; @@ -297,22 +328,20 @@ void GeneralSettings::slotUpdateInfo() connect(_ui->updateButton, &QAbstractButton::clicked, this, - &GeneralSettings::slotUpdateCheckNow, Qt::UniqueConnection); connect(_ui->autoCheckForUpdatesCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::slotToggleAutoUpdateCheck, Qt::UniqueConnection); - _ui->autoCheckForUpdatesCheckBox->setChecked(ConfigFile().autoUpdateCheck()); + _ui->autoCheckForUpdatesCheckBox->setChecked(config.autoUpdateCheck()); } // Note: the sparkle-updater is not an OCUpdater - auto *ocupdater = qobject_cast(updater); + const auto *ocupdater = qobject_cast(updater); if (ocupdater) { connect(ocupdater, &OCUpdater::downloadStateChanged, this, &GeneralSettings::slotUpdateInfo, Qt::UniqueConnection); connect(_ui->restartButton, &QAbstractButton::clicked, ocupdater, &OCUpdater::slotStartInstaller, Qt::UniqueConnection); - //connect(_ui->restartButton, &QAbstractButton::clicked, qApp, &QApplication::quit, Qt::UniqueConnection); - QString status = ocupdater->statusString(OCUpdater::UpdateStatusStringFormat::Html); + auto status = ocupdater->statusString(OCUpdater::UpdateStatusStringFormat::Html); Theme::replaceLinkColorStringBackgroundAware(status); _ui->updateStateLabel->setOpenExternalLinks(false); @@ -320,9 +349,7 @@ void GeneralSettings::slotUpdateInfo() Utility::openBrowser(QUrl(link)); }); _ui->updateStateLabel->setText(status); - _ui->restartButton->setVisible(ocupdater->downloadState() == OCUpdater::DownloadComplete); - _ui->updateButton->setEnabled(ocupdater->downloadState() != OCUpdater::CheckingServer && ocupdater->downloadState() != OCUpdater::Downloading && ocupdater->downloadState() != OCUpdater::DownloadComplete); @@ -339,59 +366,42 @@ void GeneralSettings::slotUpdateInfo() _ui->updateButton->setEnabled(enableUpdateButton); } #endif - - // Channel selection - _ui->updateChannel->setCurrentIndex(ConfigFile().updateChannel() == "beta" ? 1 : 0); - connect(_ui->updateChannel, &QComboBox::currentTextChanged, - this, &GeneralSettings::slotUpdateChannelChanged, Qt::UniqueConnection); } -void GeneralSettings::slotUpdateChannelChanged() +void GeneralSettings::slotUpdateChannelChanged(const int id) { - const auto updateChannelToLocalized = [](const QString &channel) { - auto decodedTranslatedChannel = QString{}; + auto updateChannelselected = _updateChannelGroup->button(id); + const auto updateChannelFromLocalized = [](const QString &channel) { - if (channel == QStringLiteral("stable")) { - decodedTranslatedChannel = tr("stable"); - } else if (channel == QStringLiteral("beta")) { - decodedTranslatedChannel = tr("beta"); + if (channel == tr("daily")) { + return QStringLiteral("daily"); } - return decodedTranslatedChannel; - }; - - const auto updateChannelFromLocalized = [](const int index) { - if (index == 1) { + if (channel == tr("beta")) { return QStringLiteral("beta"); } return QStringLiteral("stable"); }; - const auto channel = updateChannelFromLocalized(_ui->updateChannel->currentIndex()); - if (channel == ConfigFile().updateChannel()) { + const auto channel = updateChannelFromLocalized(updateChannelselected->text()); + if (channel == ConfigFile().currentUpdateChannel()) { return; } auto msgBox = new QMessageBox( QMessageBox::Warning, - tr("Change update channel?"), - tr("The update channel determines which client updates will be offered " - "for installation. The \"stable\" channel contains only upgrades that " - "are considered reliable, while the versions in the \"beta\" channel " - "may contain newer features and bugfixes, but have not yet been tested " - "thoroughly." - "\n\n" - "Note that this selects only what pool upgrades are taken from, and that " - "there are no downgrades: So going back from the beta channel to " - "the stable channel usually cannot be done immediately and means waiting " - "for a stable version that is newer than the currently installed beta " - "version."), + tr("Changing update channel?"), + tr("The channel determines which upgrades will be offered to install:\n" + "- stable: contains tested versions considered reliable\n" + "- beta: contains versions with new features that may not be tested thoroughly\n" + "- daily: contains versions created daily only for testing and development\n\n" + "Downgrading versions is not possible immediately: changing from beta to stable means waiting for the new stable version."), QMessageBox::NoButton, this); - auto acceptButton = msgBox->addButton(tr("Change update channel"), QMessageBox::AcceptRole); + const auto acceptButton = msgBox->addButton(tr("Change update channel"), QMessageBox::AcceptRole); msgBox->addButton(tr("Cancel"), QMessageBox::RejectRole); - connect(msgBox, &QMessageBox::finished, msgBox, [this, channel, msgBox, acceptButton, updateChannelToLocalized] { + connect(msgBox, &QMessageBox::finished, msgBox, [this, channel, msgBox, acceptButton] { msgBox->deleteLater(); if (msgBox->clickedButton() == acceptButton) { ConfigFile().setUpdateChannel(channel); @@ -406,7 +416,8 @@ void GeneralSettings::slotUpdateChannelChanged() } #endif } else { - _ui->updateChannel->setCurrentText(updateChannelToLocalized(ConfigFile().updateChannel())); + auto currentUpdateChannel = _updateChannelGroup->button(ConfigFile().validUpdateChannels().indexOf(ConfigFile().currentUpdateChannel())); + currentUpdateChannel->setChecked(true); } }); msgBox->open(); diff --git a/src/gui/generalsettings.h b/src/gui/generalsettings.h index 70a726142db8b..4c59eaaef0f62 100644 --- a/src/gui/generalsettings.h +++ b/src/gui/generalsettings.h @@ -20,6 +20,8 @@ #include #include +class QButtonGroup; + namespace OCC { class IgnoreListEditor; class SyncLogDialog; @@ -56,7 +58,7 @@ private slots: void slotShowLegalNotice(); #if defined(BUILD_UPDATER) void slotUpdateInfo(); - void slotUpdateChannelChanged(); + void slotUpdateChannelChanged(const int id); void slotUpdateCheckNow(); void slotToggleAutoUpdateCheck(); #endif @@ -67,6 +69,7 @@ private slots: Ui::GeneralSettings *_ui; QPointer _ignoreEditor; bool _currentlyLoading = false; + QButtonGroup *_updateChannelGroup; }; diff --git a/src/gui/generalsettings.ui b/src/gui/generalsettings.ui index 54f79b55d4750..c01f8e77a9009 100644 --- a/src/gui/generalsettings.ui +++ b/src/gui/generalsettings.ui @@ -6,7 +6,7 @@ 0 0 - 601 + 933 663 @@ -14,6 +14,59 @@ Form + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + General Settings + + + + + + For System Tray + + + Use &monochrome icons + + + + + + + &Launch on system startup + + + + + + + Show server &notifications + + + + + + + Show call notifications + + + + + + @@ -40,7 +93,7 @@ - Qt::Horizontal + Qt::Vertical QSizePolicy::Fixed @@ -77,7 +130,7 @@ - Qt::Horizontal + Qt::Vertical QSizePolicy::Fixed @@ -104,7 +157,7 @@ - Qt::Horizontal + Qt::Vertical QSizePolicy::Fixed @@ -197,7 +250,7 @@ - Qt::Horizontal + Qt::Vertical @@ -247,7 +300,7 @@ 0 - + @@ -262,23 +315,16 @@ - + 0 0 - - - stable - - - - - beta - - + + &Restart && Update + @@ -294,19 +340,6 @@ - - - - - 0 - 0 - - - - &Restart && Update - - - @@ -341,10 +374,23 @@ - + Qt::Horizontal + + + 20 + 20 + + + + + + + + Qt::Vertical + 40 @@ -372,10 +418,23 @@ - + Qt::Horizontal + + + 20 + 20 + + + + + + + + Qt::Vertical + 40 @@ -392,59 +451,6 @@ - - - - Qt::Vertical - - - - 20 - 0 - - - - - - - - General Settings - - - - - - For System Tray - - - Use &monochrome icons - - - - - - - &Launch on system startup - - - - - - - Show server &notifications - - - - - - - Show call notifications - - - - - - @@ -455,7 +461,6 @@ newFolderLimitCheckBox newFolderLimitSpinBox crashreporterCheckBox - restartButton diff --git a/src/gui/updater/updater.cpp b/src/gui/updater/updater.cpp index 4365ae5837ab4..87957c724e3d7 100644 --- a/src/gui/updater/updater.cpp +++ b/src/gui/updater/updater.cpp @@ -75,9 +75,7 @@ QUrl Updater::updateUrl() QUrlQuery Updater::getQueryParams() { - QUrlQuery query; - Theme *theme = Theme::instance(); - QString platform = QStringLiteral("stranger"); + auto platform = QStringLiteral("stranger"); if (Utility::isLinux()) { platform = QStringLiteral("linux"); } else if (Utility::isBSD()) { @@ -88,8 +86,8 @@ QUrlQuery Updater::getQueryParams() platform = QStringLiteral("macos"); } - QString sysInfo = getSystemInfo(); - if (!sysInfo.isEmpty()) { + QUrlQuery query; + if (const auto sysInfo = getSystemInfo(); !sysInfo.isEmpty()) { query.addQueryItem(QStringLiteral("client"), sysInfo); } query.addQueryItem(QStringLiteral("version"), clientVersion()); @@ -97,27 +95,18 @@ QUrlQuery Updater::getQueryParams() query.addQueryItem(QStringLiteral("osRelease"), QSysInfo::productType()); query.addQueryItem(QStringLiteral("osVersion"), QSysInfo::productVersion()); query.addQueryItem(QStringLiteral("kernelVersion"), QSysInfo::kernelVersion()); - query.addQueryItem(QStringLiteral("oem"), theme->appName()); + query.addQueryItem(QStringLiteral("oem"), Theme::instance()->appName()); query.addQueryItem(QStringLiteral("buildArch"), QSysInfo::buildCpuArchitecture()); query.addQueryItem(QStringLiteral("currentArch"), QSysInfo::currentCpuArchitecture()); + query.addQueryItem(QStringLiteral("versionsuffix"), Theme::instance()->versionSuffix()); - QString suffix = QStringLiteral(MIRALL_STRINGIFY(MIRALL_VERSION_SUFFIX)); - query.addQueryItem(QStringLiteral("versionsuffix"), suffix); - - auto channel = ConfigFile().updateChannel(); - if (channel != QLatin1String("stable")) { - query.addQueryItem(QStringLiteral("channel"), channel); - } - - // updateSegment (see configfile.h) - ConfigFile cfg; - auto updateSegment = cfg.updateSegment(); - query.addQueryItem(QLatin1String("updatesegment"), QString::number(updateSegment)); + ConfigFile config; + query.addQueryItem(QStringLiteral("channel"), config.currentUpdateChannel()); + query.addQueryItem(QLatin1String("updatesegment"), QString::number(config.updateSegment())); return query; } - QString Updater::getSystemInfo() { #ifdef Q_OS_LINUX diff --git a/src/libsync/configfile.cpp b/src/libsync/configfile.cpp index abc9eb8a84a60..0a803595f2248 100644 --- a/src/libsync/configfile.cpp +++ b/src/libsync/configfile.cpp @@ -110,7 +110,8 @@ static constexpr char forceLoginV2C[] = "forceLoginV2"; static constexpr char certPath[] = "http_certificatePath"; static constexpr char certPasswd[] = "http_certificatePasswd"; -static const QSet validUpdateChannels { QStringLiteral("stable"), QStringLiteral("beta") }; +static const QStringList validUpdateChannelsList { QStringLiteral("stable"), QStringLiteral("beta"), QStringLiteral("daily") }; +static const char stableUpdateChannel[] = "stable"; } namespace OCC { @@ -686,37 +687,39 @@ int ConfigFile::updateSegment() const return segment; } -QString ConfigFile::updateChannel() const +QStringList ConfigFile::validUpdateChannels() const { - QString defaultUpdateChannel = QStringLiteral("stable"); - QString suffix = QString::fromLatin1(MIRALL_STRINGIFY(MIRALL_VERSION_SUFFIX)); - if (suffix.startsWith("daily") - || suffix.startsWith("nightly") - || suffix.startsWith("alpha") - || suffix.startsWith("rc") - || suffix.startsWith("beta")) { - defaultUpdateChannel = QStringLiteral("beta"); + return validUpdateChannelsList; +} + +QString ConfigFile::defaultUpdateChannel() const +{ + if (const auto currentVersionSuffix = Theme::instance()->versionSuffix();validUpdateChannels().contains(currentVersionSuffix)) { + qCWarning(lcConfigFile()) << "Enforcing update channel" << currentVersionSuffix << "because of the version suffix of the current client."; + return currentVersionSuffix; } + return stableUpdateChannel; +} + +QString ConfigFile::currentUpdateChannel() const +{ QSettings settings(configFile(), QSettings::IniFormat); - const auto channel = settings.value(QLatin1String(updateChannelC), defaultUpdateChannel).toString(); - if (!validUpdateChannels.contains(channel)) { - qCWarning(lcConfigFile()) << "Received invalid update channel from confog:" - << channel - << "defaulting to:" - << defaultUpdateChannel; - return defaultUpdateChannel; + if (const auto configUpdateChannel = settings.value(QLatin1String(updateChannelC), defaultUpdateChannel()).toString(); + validUpdateChannels().contains(configUpdateChannel)) { + qCWarning(lcConfigFile()) << "Config file has a valid update channel:" << configUpdateChannel; + return configUpdateChannel; } - return channel; + return defaultUpdateChannel(); } void ConfigFile::setUpdateChannel(const QString &channel) { - if (!validUpdateChannels.contains(channel)) { + if (!validUpdateChannels().contains(channel)) { qCWarning(lcConfigFile()) << "Received invalid update channel:" << channel - << "can only accept 'stable' or 'beta'. Ignoring."; + << "can only accept 'stable', 'beta' or 'daily'. Ignoring."; return; } diff --git a/src/libsync/configfile.h b/src/libsync/configfile.h index 97ec16e2f5ad7..6b10a8f2fd1fe 100644 --- a/src/libsync/configfile.h +++ b/src/libsync/configfile.h @@ -195,7 +195,9 @@ class OWNCLOUDSYNC_EXPORT ConfigFile See: https://github.com/nextcloud/client_updater_server/pull/36 */ [[nodiscard]] int updateSegment() const; - [[nodiscard]] QString updateChannel() const; + [[nodiscard]] QString currentUpdateChannel() const; + [[nodiscard]] QString defaultUpdateChannel() const; + [[nodiscard]] QStringList validUpdateChannels() const; void setUpdateChannel(const QString &channel); [[nodiscard]] QString overrideServerUrl() const; diff --git a/src/libsync/theme.cpp b/src/libsync/theme.cpp index bb4bae4c4be86..b20ef2a6798af 100644 --- a/src/libsync/theme.cpp +++ b/src/libsync/theme.cpp @@ -195,6 +195,11 @@ QString Theme::version() const return MIRALL_VERSION_STRING; } +QString Theme::versionSuffix() const +{ + return QString::fromLatin1(MIRALL_STRINGIFY(MIRALL_VERSION_SUFFIX)); +} + QString Theme::configFileName() const { return QStringLiteral(APPLICATION_CONFIG_NAME ".cfg"); diff --git a/src/libsync/theme.h b/src/libsync/theme.h index c59266f65cf81..e5d312ddee400 100644 --- a/src/libsync/theme.h +++ b/src/libsync/theme.h @@ -196,6 +196,7 @@ class OWNCLOUDSYNC_EXPORT Theme : public QObject [[nodiscard]] QString statusHeaderText(SyncResult::Status) const; [[nodiscard]] QString version() const; + [[nodiscard]] QString versionSuffix() const; /** * Characteristics: bool if more than one sync folder is allowed