From 13fcf5ad3c3705ae87556b2072889daa519ff1b3 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Tue, 19 May 2015 15:15:15 +0200 Subject: Refactor UpdateInfo plugin Change-Id: I63fc40b12e29204d9ecd4ed3fd33e7ad3171918d Reviewed-by: Eike Ziller --- src/plugins/updateinfo/settingspage.cpp | 125 ++++++++++- src/plugins/updateinfo/settingspage.h | 10 + src/plugins/updateinfo/settingspage.ui | 278 +++++++++-------------- src/plugins/updateinfo/updateinfo.pro | 2 - src/plugins/updateinfo/updateinfo.qbs | 2 - src/plugins/updateinfo/updateinfobutton.cpp | 77 ------- src/plugins/updateinfo/updateinfobutton.h | 52 ----- src/plugins/updateinfo/updateinfoplugin.cpp | 336 ++++++++++++++++------------ src/plugins/updateinfo/updateinfoplugin.h | 57 +++-- 9 files changed, 456 insertions(+), 483 deletions(-) delete mode 100644 src/plugins/updateinfo/updateinfobutton.cpp delete mode 100644 src/plugins/updateinfo/updateinfobutton.h (limited to 'src/plugins/updateinfo') diff --git a/src/plugins/updateinfo/settingspage.cpp b/src/plugins/updateinfo/settingspage.cpp index 6565760dc0..291424fd41 100644 --- a/src/plugins/updateinfo/settingspage.cpp +++ b/src/plugins/updateinfo/settingspage.cpp @@ -29,21 +29,31 @@ ****************************************************************************/ #include "settingspage.h" -#include "updateinfoplugin.h" #include +#include +#include + +#include using namespace UpdateInfo; using namespace UpdateInfo::Internal; +namespace { + +static const char FILTER_OPTIONS_PAGE_ID[] = "Update"; +static const char FILTER_OPTIONS_PAGE[] = QT_TRANSLATE_NOOP("Update", "Update"); + +} + SettingsPage::SettingsPage(UpdateInfoPlugin *plugin) : m_widget(0) , m_plugin(plugin) { - setId(Constants::FILTER_OPTIONS_PAGE); + setId(FILTER_OPTIONS_PAGE_ID); setCategory(Core::Constants::SETTINGS_CATEGORY_CORE); setCategoryIcon(QLatin1String(Core::Constants::SETTINGS_CATEGORY_CORE_ICON)); - setDisplayName(QCoreApplication::translate("Update", UpdateInfo::Constants::FILTER_OPTIONS_PAGE)); + setDisplayName(QCoreApplication::translate("Update", FILTER_OPTIONS_PAGE)); setDisplayCategory(QCoreApplication::translate("Core", Core::Constants::SETTINGS_TR_CATEGORY_CORE)); } @@ -52,17 +62,116 @@ QWidget *SettingsPage::widget() if (!m_widget) { m_widget = new QWidget; m_ui.setupUi(m_widget); - m_ui.m_timeTable->setItemText(m_ui.m_timeTable->currentIndex(), QTime(m_plugin->scheduledUpdateTime()) - .toString(QLatin1String("hh:mm"))); + m_ui.m_checkIntervalComboBox->addItem(tr("Daily"), UpdateInfoPlugin::DailyCheck); + m_ui.m_checkIntervalComboBox->addItem(tr("Weekly"), UpdateInfoPlugin::WeeklyCheck); + m_ui.m_checkIntervalComboBox->addItem(tr("Monthly"), UpdateInfoPlugin::MonthlyCheck); + UpdateInfoPlugin::CheckUpdateInterval interval = m_plugin->checkUpdateInterval(); + for (int i = 0; i < m_ui.m_checkIntervalComboBox->count(); i++) { + if (m_ui.m_checkIntervalComboBox->itemData(i).toInt() == interval) { + m_ui.m_checkIntervalComboBox->setCurrentIndex(i); + break; + } + } + + m_ui.m_updatesGroupBox->setChecked(m_plugin->isAutomaticCheck()); + + updateLastCheckDate(); + checkRunningChanged(m_plugin->isCheckForUpdatesRunning()); + + connect(m_ui.m_checkNowButton, &QPushButton::clicked, + m_plugin, &UpdateInfoPlugin::startCheckForUpdates); + connect(m_ui.m_checkIntervalComboBox, + static_cast(&QComboBox::currentIndexChanged), + this, &SettingsPage::updateNextCheckDate); + connect(m_plugin, &UpdateInfoPlugin::lastCheckDateChanged, + this, &SettingsPage::updateLastCheckDate); + connect(m_plugin, &UpdateInfoPlugin::checkForUpdatesRunningChanged, + this, &SettingsPage::checkRunningChanged); + connect(m_plugin, &UpdateInfoPlugin::newUpdatesAvailable, + this, &SettingsPage::newUpdatesAvailable); } return m_widget; } +UpdateInfoPlugin::CheckUpdateInterval SettingsPage::currentCheckInterval() const +{ + QTC_ASSERT(m_widget, return UpdateInfoPlugin::WeeklyCheck); + + return static_cast + (m_ui.m_checkIntervalComboBox->itemData(m_ui.m_checkIntervalComboBox->currentIndex()).toInt()); +} + +void SettingsPage::newUpdatesAvailable(bool available) +{ + if (!m_widget) + return; + + const QString message = available + ? tr("New updates are available.") + : tr("No new updates are available."); + m_ui.m_messageLabel->setText(message); +} + +void SettingsPage::checkRunningChanged(bool running) +{ + if (!m_widget) + return; + + m_ui.m_checkNowButton->setDisabled(running); + + if (running) { + if (!m_progressIndicator) { + m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicator::Large); + m_progressIndicator->attachToWidget(m_widget); + } + m_progressIndicator->show(); + } else { + if (m_progressIndicator) { + delete m_progressIndicator; + } + } + + const QString message = running + ? tr("Checking for updates...") : QString(); + m_ui.m_messageLabel->setText(message); +} + +void SettingsPage::updateLastCheckDate() +{ + if (!m_widget) + return; + + const QDate date = m_plugin->lastCheckDate(); + QString lastCheckDateString; + if (date.isValid()) + lastCheckDateString = date.toString(); + else + lastCheckDateString = tr("Not checked yet"); + + m_ui.m_lastCheckDateLabel->setText(lastCheckDateString); + + updateNextCheckDate(); +} + +void SettingsPage::updateNextCheckDate() +{ + if (!m_widget) + return; + + QDate date = m_plugin->nextCheckDate(currentCheckInterval()); + if (!date.isValid() || date < QDate::currentDate()) + date = QDate::currentDate(); + + m_ui.m_nextCheckDateLabel->setText(date.toString()); +} + void SettingsPage::apply() { - m_plugin->setScheduledUpdateTime(QTime::fromString(m_ui.m_timeTable->currentText(), - QLatin1String("hh:mm"))); - m_plugin->saveSettings(); + if (!m_widget) + return; + + m_plugin->setCheckUpdateInterval(currentCheckInterval()); + m_plugin->setAutomaticCheck(m_ui.m_updatesGroupBox->isChecked()); } void SettingsPage::finish() diff --git a/src/plugins/updateinfo/settingspage.h b/src/plugins/updateinfo/settingspage.h index 43bdd0b533..77cf685a89 100644 --- a/src/plugins/updateinfo/settingspage.h +++ b/src/plugins/updateinfo/settingspage.h @@ -32,11 +32,14 @@ #define SETTINGSPAGE_H #include "ui_settingspage.h" +#include "updateinfoplugin.h" #include #include +namespace Utils { class ProgressIndicator; } + namespace UpdateInfo { namespace Internal { @@ -54,7 +57,14 @@ public: void finish(); private: + void newUpdatesAvailable(bool available); + void checkRunningChanged(bool running); + void updateLastCheckDate(); + void updateNextCheckDate(); + UpdateInfoPlugin::CheckUpdateInterval currentCheckInterval() const; + QPointer m_widget; + QPointer m_progressIndicator; Ui::SettingsWidget m_ui; UpdateInfoPlugin *m_plugin; }; diff --git a/src/plugins/updateinfo/settingspage.ui b/src/plugins/updateinfo/settingspage.ui index fee80c0e94..d34ef304e6 100644 --- a/src/plugins/updateinfo/settingspage.ui +++ b/src/plugins/updateinfo/settingspage.ui @@ -7,21 +7,34 @@ 0 0 482 - 364 + 242 Configure Filters - - - + + + - Qt Creator Update Settings + Automatic Check for Updates - - - + + true + + + true + + + + + + Check interval basis: + + + + + 0 @@ -29,196 +42,107 @@ - Qt Creator automatically runs a scheduled update check on a daily basis. If Qt Creator is not in use on the scheduled time or maintenance is behind schedule, the automatic update check will be run next time Qt Creator starts. + Qt Creator automatically runs a scheduled check for updates on a time interval basis. If Qt Creator is not in use on the scheduled date, the automatic check for updates will be performed next time Qt Creator starts. true - - - - Qt::Vertical + + + + -1 - - QSizePolicy::Fixed + + + + + + Qt::Horizontal - 20 + 171 20 - - - - - - Run update check daily at: - - - - - - - 12 - - - - 00:00 - - - - - 01:00 - - - - - 02:00 - - - - - 03:00 - - - - - 04:00 - - - - - 05:00 - - - - - 06:00 - - - - - 07:00 - - - - - 08:00 - - - - - 09:00 - - - - - 10:00 - - - - - 11:00 - - - - - 12:00 - - - - - 13:00 - - - - - 14:00 - - - - - 15:00 - - - - - 16:00 - - - - - 17:00 - - - - - 18:00 - - - - - 19:00 - - - - - 20:00 - - - - - 21:00 - - - - - 22:00 - - - - - 23:00 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical + + + + Next check date: - - - 20 - 253 - + + + + + + - + + + + + Last check date: + + + + + + + Not checked yet + + + + + + + Qt::Horizontal + + + + 167 + 20 + + + + + + + + Check Now + + + + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + 20 + 233 + + + + diff --git a/src/plugins/updateinfo/updateinfo.pro b/src/plugins/updateinfo/updateinfo.pro index 7654a4f6c5..8a66ba3898 100644 --- a/src/plugins/updateinfo/updateinfo.pro +++ b/src/plugins/updateinfo/updateinfo.pro @@ -1,10 +1,8 @@ QT += network xml HEADERS += updateinfoplugin.h \ - updateinfobutton.h \ settingspage.h SOURCES += updateinfoplugin.cpp \ - updateinfobutton.cpp \ settingspage.cpp FORMS += settingspage.ui RESOURCES += updateinfo.qrc diff --git a/src/plugins/updateinfo/updateinfo.qbs b/src/plugins/updateinfo/updateinfo.qbs index 02161420e3..2a875c4d7f 100644 --- a/src/plugins/updateinfo/updateinfo.qbs +++ b/src/plugins/updateinfo/updateinfo.qbs @@ -14,8 +14,6 @@ QtcPlugin { pluginJsonReplacements: ({"UPDATEINFO_EXPERIMENTAL_STR": (enable ? "false": "true")}) files: [ - "updateinfobutton.cpp", - "updateinfobutton.h", "updateinfoplugin.cpp", "updateinfoplugin.h", "settingspage.cpp", diff --git a/src/plugins/updateinfo/updateinfobutton.cpp b/src/plugins/updateinfo/updateinfobutton.cpp deleted file mode 100644 index e049626923..0000000000 --- a/src/plugins/updateinfo/updateinfobutton.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms and -** conditions see http://www.qt.io/terms-conditions. For further information -** use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "updateinfobutton.h" - -#include -#include - -#include -#include - - -namespace UpdateInfo { -namespace Internal { - -UpdateInfoButton::UpdateInfoButton(QWidget *parent) : - QAbstractButton(parent) -{ - setIcon(QIcon(QLatin1String(":/updateinfo/images/update_available_logo.png"))); -} - -//copied from fancytoolbutton -QSize UpdateInfoButton::minimumSizeHint() const -{ - return QSize(8, 8); -} - -//copied from fancytoolbutton -QSize UpdateInfoButton::sizeHint() const -{ - return iconSize().expandedTo(QSize(64, 38)); -} - -//copied from fancytoolbutton and removed unused things -void UpdateInfoButton::paintEvent(QPaintEvent *event) -{ - Q_UNUSED(event) - QPainter painter(this); - - QRect iconRect(0, 0, Core::Constants::TARGET_ICON_SIZE, Core::Constants::TARGET_ICON_SIZE); - - - iconRect.moveCenter(rect().center()); - Utils::StyleHelper::drawIconWithShadow(icon(), iconRect, &painter, isEnabled() ? QIcon::Normal : QIcon::Disabled); - -} - - -} //Internal -} //namespace UpdateInfo diff --git a/src/plugins/updateinfo/updateinfobutton.h b/src/plugins/updateinfo/updateinfobutton.h deleted file mode 100644 index d99827ee4b..0000000000 --- a/src/plugins/updateinfo/updateinfobutton.h +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms and -** conditions see http://www.qt.io/terms-conditions. For further information -** use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef UPDATEINFOBUTTON_H -#define UPDATEINFOBUTTON_H - -#include - -namespace UpdateInfo { -namespace Internal { - -class UpdateInfoButton : public QAbstractButton -{ - Q_OBJECT -public: - explicit UpdateInfoButton(QWidget *parent = 0); - void paintEvent(QPaintEvent *event); - QSize sizeHint() const; - QSize minimumSizeHint() const; -}; - -} //namespace Internal -} //namespace UpdateInfo - -#endif // UPDATEINFOBUTTON_H diff --git a/src/plugins/updateinfo/updateinfoplugin.cpp b/src/plugins/updateinfo/updateinfoplugin.cpp index 1def9167f4..b327d2eb2e 100644 --- a/src/plugins/updateinfo/updateinfoplugin.cpp +++ b/src/plugins/updateinfo/updateinfoplugin.cpp @@ -30,28 +30,34 @@ #include "settingspage.h" #include "updateinfoplugin.h" -#include "updateinfobutton.h" #include #include #include #include -#include -#include #include +#include +#include -#include - -#include +#include #include #include -#include +#include #include -#include +#include +#include +#include +#include #include namespace { + static const char UpdaterGroup[] = "Updater"; + static const char MaintenanceToolKey[] = "MaintenanceTool"; + static const char AutomaticCheckKey[] = "AutomaticCheck"; + static const char CheckIntervalKey[] = "CheckUpdateInterval"; + static const char LastCheckDateKey[] = "LastCheckDate"; static const quint32 OneMinute = 60000; + static const quint32 OneHour = 3600000; } using namespace Core; @@ -63,47 +69,120 @@ class UpdateInfoPluginPrivate { public: UpdateInfoPluginPrivate() - : progressUpdateInfoButton(0), - checkUpdateInfoWatcher(0), - m_settingsPage(0) - { - } + { } - QString updaterProgram; - QString updaterRunUiArgument; - QString updaterCheckOnlyArgument; + QString m_maintenanceTool; + ShellCommand *m_checkUpdatesCommand = 0; + QString m_collectedOutput; + QTimer *m_checkUpdatesTimer = 0; - QFuture lastCheckUpdateInfoTask; - QPointer updateInfoProgress; - UpdateInfoButton *progressUpdateInfoButton; - QFutureWatcher *checkUpdateInfoWatcher; - - QBasicTimer m_timer; - QDate m_lastDayChecked; - QTime m_scheduledUpdateTime; - SettingsPage *m_settingsPage; + bool m_automaticCheck = true; + UpdateInfoPlugin::CheckUpdateInterval m_checkInterval = UpdateInfoPlugin::WeeklyCheck; + QDate m_lastCheckDate; }; UpdateInfoPlugin::UpdateInfoPlugin() : d(new UpdateInfoPluginPrivate) { + d->m_checkUpdatesTimer = new QTimer(this); + d->m_checkUpdatesTimer->setTimerType(Qt::VeryCoarseTimer); + d->m_checkUpdatesTimer->setInterval(OneHour); + connect(d->m_checkUpdatesTimer, &QTimer::timeout, + this, &UpdateInfoPlugin::doAutoCheckForUpdates); } UpdateInfoPlugin::~UpdateInfoPlugin() { - d->lastCheckUpdateInfoTask.cancel(); - d->lastCheckUpdateInfoTask.waitForFinished(); + stopCheckForUpdates(); + if (!d->m_maintenanceTool.isEmpty()) + saveSettings(); delete d; } +void UpdateInfoPlugin::startAutoCheckForUpdates() +{ + doAutoCheckForUpdates(); + + d->m_checkUpdatesTimer->start(); +} + +void UpdateInfoPlugin::stopAutoCheckForUpdates() +{ + d->m_checkUpdatesTimer->stop(); +} + +void UpdateInfoPlugin::doAutoCheckForUpdates() +{ + if (d->m_checkUpdatesCommand) + return; // update task is still running (might have been run manually just before) + + if (nextCheckDate().isValid() && nextCheckDate() > QDate::currentDate()) + return; // not a time for check yet + + startCheckForUpdates(); +} + +void UpdateInfoPlugin::startCheckForUpdates() +{ + stopCheckForUpdates(); + + d->m_checkUpdatesCommand = new ShellCommand(QString(), QProcessEnvironment()); + connect(d->m_checkUpdatesCommand, &ShellCommand::stdOutText, this, &UpdateInfoPlugin::collectCheckForUpdatesOutput); + connect(d->m_checkUpdatesCommand, &ShellCommand::finished, this, &UpdateInfoPlugin::checkForUpdatesFinished); + d->m_checkUpdatesCommand->addJob(Utils::FileName(QFileInfo(d->m_maintenanceTool)), QStringList(QLatin1String("--checkupdates"))); + d->m_checkUpdatesCommand->execute(); + emit checkForUpdatesRunningChanged(true); +} + +void UpdateInfoPlugin::stopCheckForUpdates() +{ + if (!d->m_checkUpdatesCommand) + return; + + d->m_collectedOutput = QString(); + d->m_checkUpdatesCommand->disconnect(); + d->m_checkUpdatesCommand->cancel(); + d->m_checkUpdatesCommand = 0; + emit checkForUpdatesRunningChanged(false); +} + +void UpdateInfoPlugin::collectCheckForUpdatesOutput(const QString &contents) +{ + d->m_collectedOutput += contents; +} + +void UpdateInfoPlugin::checkForUpdatesFinished() +{ + setLastCheckDate(QDate::currentDate()); + + QDomDocument document; + document.setContent(d->m_collectedOutput); + + stopCheckForUpdates(); + + if (!document.isNull() && document.firstChildElement().hasChildNodes()) { + emit newUpdatesAvailable(true); + if (QMessageBox::question(0, tr("Updater"), + tr("New updates are available. Do you want to start update?")) + == QMessageBox::Yes) + startUpdater(); + } else { + emit newUpdatesAvailable(false); + } +} + +bool UpdateInfoPlugin::isCheckForUpdatesRunning() const +{ + return d->m_checkUpdatesCommand; +} + bool UpdateInfoPlugin::delayedInitialize() { - d->checkUpdateInfoWatcher = new QFutureWatcher(this); - connect(d->checkUpdateInfoWatcher, SIGNAL(finished()), this, SLOT(parseUpdates())); + if (isAutomaticCheck()) + QTimer::singleShot(OneMinute, this, &UpdateInfoPlugin::startAutoCheckForUpdates); - d->m_timer.start(OneMinute, this); return true; } @@ -114,167 +193,132 @@ void UpdateInfoPlugin::extensionsInitialized() bool UpdateInfoPlugin::initialize(const QStringList & /* arguments */, QString *errorMessage) { loadSettings(); - if (d->updaterProgram.isEmpty()) { + + if (d->m_maintenanceTool.isEmpty()) { *errorMessage = tr("Could not determine location of maintenance tool. Please check " "your installation if you did not enable this plugin manually."); return false; } - if (!QFile::exists(d->updaterProgram)) { - *errorMessage = tr("Could not find maintenance tool at \"%1\". Check your installation.") - .arg(d->updaterProgram); + if (!QFileInfo(d->m_maintenanceTool).isExecutable()) { + *errorMessage = tr("The maintenance tool at \"%1\" is not an executable. Check your installation.") + .arg(d->m_maintenanceTool); + d->m_maintenanceTool = QString(); return false; } - d->m_settingsPage = new SettingsPage(this); - addAutoReleasedObject(d->m_settingsPage); + connect(ICore::instance(), &ICore::saveSettingsRequested, + this, &UpdateInfoPlugin::saveSettings); + + addAutoReleasedObject(new SettingsPage(this)); - ActionContainer *const container = ActionManager::actionContainer(Core::Constants::M_HELP); - container->menu()->addAction(tr("Start Updater"), this, SLOT(startUpdaterUiApplication())); + QAction *checkForUpdatesAction = new QAction(tr("Check for Updates"), this); + Core::Command *checkForUpdatesCommand = Core::ActionManager::registerAction(checkForUpdatesAction, "Updates.CheckForUpdates"); + connect(checkForUpdatesAction, &QAction::triggered, this, &UpdateInfoPlugin::startCheckForUpdates); + ActionContainer *const helpContainer = ActionManager::actionContainer(Core::Constants::M_HELP); + helpContainer->addAction(checkForUpdatesCommand, Constants::G_HELP_UPDATES); return true; } -void UpdateInfoPlugin::loadSettings() +void UpdateInfoPlugin::loadSettings() const { - QSettings *qs = ICore::settings(); - if (qs->contains(QLatin1String("Updater/Application"))) { - settingsHelper(qs); - qs->remove(QLatin1String("Updater")); - saveSettings(); // update to the new settings location - } else { - settingsHelper(ICore::settingsDatabase()); + QSettings *settings = ICore::settings(); + const QString updaterKey = QLatin1String(UpdaterGroup) + QLatin1Char('/'); + d->m_maintenanceTool = settings->value(updaterKey + QLatin1String(MaintenanceToolKey)).toString(); + d->m_lastCheckDate = settings->value(updaterKey + QLatin1String(LastCheckDateKey), QDate()).toDate(); + d->m_automaticCheck = settings->value(updaterKey + QLatin1String(AutomaticCheckKey), true).toBool(); + const QString checkInterval = settings->value(updaterKey + QLatin1String(CheckIntervalKey)).toString(); + const QMetaObject *mo = metaObject(); + const QMetaEnum me = mo->enumerator(mo->indexOfEnumerator(CheckIntervalKey)); + if (me.isValid()) { + bool ok = false; + const int newValue = me.keyToValue(checkInterval.toUtf8(), &ok); + if (ok) + d->m_checkInterval = static_cast(newValue); } } void UpdateInfoPlugin::saveSettings() { - SettingsDatabase *settings = ICore::settingsDatabase(); - if (settings) { - settings->beginTransaction(); - settings->beginGroup(QLatin1String("Updater")); - settings->setValue(QLatin1String("Application"), d->updaterProgram); - settings->setValue(QLatin1String("LastDayChecked"), d->m_lastDayChecked); - settings->setValue(QLatin1String("RunUiArgument"), d->updaterRunUiArgument); - settings->setValue(QLatin1String("CheckOnlyArgument"), d->updaterCheckOnlyArgument); - settings->setValue(QLatin1String("ScheduledUpdateTime"), d->m_scheduledUpdateTime); - settings->endGroup(); - settings->endTransaction(); - } + QSettings *settings = ICore::settings(); + settings->beginGroup(QLatin1String(UpdaterGroup)); + settings->setValue(QLatin1String(LastCheckDateKey), d->m_lastCheckDate); + settings->setValue(QLatin1String(AutomaticCheckKey), d->m_automaticCheck); + // Note: don't save MaintenanceToolKey on purpose! This setting may be set only by installer. + // If creator is run not from installed SDK, the setting can be manually created here: + // [CREATOR_INSTALLATION_LOCATION]/share/qtcreator/QtProject/QtCreator.ini or + // [CREATOR_INSTALLATION_LOCATION]/Qt Creator.app/Contents/Resources/QtProject/QtCreator.ini on OS X + const QMetaObject *mo = metaObject(); + const QMetaEnum me = mo->enumerator(mo->indexOfEnumerator(CheckIntervalKey)); + settings->setValue(QLatin1String(CheckIntervalKey), QLatin1String(me.valueToKey(d->m_checkInterval))); + settings->endGroup(); } -QTime UpdateInfoPlugin::scheduledUpdateTime() const +bool UpdateInfoPlugin::isAutomaticCheck() const { - return d->m_scheduledUpdateTime; + return d->m_automaticCheck; } -void UpdateInfoPlugin::setScheduledUpdateTime(const QTime &time) +void UpdateInfoPlugin::setAutomaticCheck(bool on) { - d->m_scheduledUpdateTime = time; -} + if (d->m_automaticCheck == on) + return; -// -- protected + d->m_automaticCheck = on; + if (on) + startAutoCheckForUpdates(); + else + stopAutoCheckForUpdates(); +} -void UpdateInfoPlugin::timerEvent(QTimerEvent *event) +UpdateInfoPlugin::CheckUpdateInterval UpdateInfoPlugin::checkUpdateInterval() const { - if (event->timerId() == d->m_timer.timerId()) { - const QDate today = QDate::currentDate(); - if ((d->m_lastDayChecked == today) || (d->lastCheckUpdateInfoTask.isRunning())) - return; // we checked already or the update task is still running - - bool check = false; - if (d->m_lastDayChecked <= today.addDays(-2)) - check = true; // we haven't checked since some days, force check - - if (QTime::currentTime() > d->m_scheduledUpdateTime) - check = true; // we are behind schedule, force check - - if (check) { - d->lastCheckUpdateInfoTask = QtConcurrent::run(this, &UpdateInfoPlugin::update); - d->checkUpdateInfoWatcher->setFuture(d->lastCheckUpdateInfoTask); - } - } else { - // not triggered from our timer - ExtensionSystem::IPlugin::timerEvent(event); - } + return d->m_checkInterval; } -// -- private slots - -void UpdateInfoPlugin::parseUpdates() +void UpdateInfoPlugin::setCheckUpdateInterval(UpdateInfoPlugin::CheckUpdateInterval interval) { - QDomDocument updatesDomDocument = d->checkUpdateInfoWatcher->result(); - if (updatesDomDocument.isNull() || !updatesDomDocument.firstChildElement().hasChildNodes()) + if (d->m_checkInterval == interval) return; - // add the finished task to the progress manager - d->updateInfoProgress - = ProgressManager::addTask(d->lastCheckUpdateInfoTask, tr("Updates Available"), - "Update.GetInfo", ProgressManager::KeepOnFinish); - d->updateInfoProgress->setKeepOnFinish(FutureProgress::KeepOnFinish); - - d->progressUpdateInfoButton = new UpdateInfoButton(); - d->updateInfoProgress->setWidget(d->progressUpdateInfoButton); - connect(d->progressUpdateInfoButton, SIGNAL(released()), this, SLOT(startUpdaterUiApplication())); + d->m_checkInterval = interval; } -void UpdateInfoPlugin::startUpdaterUiApplication() +QDate UpdateInfoPlugin::lastCheckDate() const { - QProcess::startDetached(d->updaterProgram, QStringList() << d->updaterRunUiArgument); - if (!d->updateInfoProgress.isNull()) //this is fading out the last update info - d->updateInfoProgress->setKeepOnFinish(FutureProgress::HideOnFinish); + return d->m_lastCheckDate; } -// -- private - -QDomDocument UpdateInfoPlugin::update() +void UpdateInfoPlugin::setLastCheckDate(const QDate &date) { - if (QThread::currentThread() == QCoreApplication::instance()->thread()) { - qWarning() << Q_FUNC_INFO << " was not designed to run in main/ gui thread, it is using " - "QProcess::waitForFinished()"; - } - - // start - QProcess updater; - updater.start(d->updaterProgram, QStringList() << d->updaterCheckOnlyArgument); - while (updater.state() != QProcess::NotRunning) { - if (!updater.waitForFinished(1000) - && d->lastCheckUpdateInfoTask.isCanceled()) { - updater.kill(); - updater.waitForFinished(-1); - return QDomDocument(); - } - } - - // process return value - QDomDocument updates; - if (updater.exitStatus() != QProcess::CrashExit) { - d->m_timer.stop(); - updates.setContent(updater.readAllStandardOutput()); - saveSettings(); // force writing out the last update date - } else { - qWarning() << "Updater application crashed."; - } + if (d->m_lastCheckDate == date) + return; - d->m_lastDayChecked = QDate::currentDate(); - return updates; + d->m_lastCheckDate = date; + emit lastCheckDateChanged(date); } -template -void UpdateInfoPlugin::settingsHelper(T *settings) +QDate UpdateInfoPlugin::nextCheckDate() const { - settings->beginGroup(QLatin1String("Updater")); + return nextCheckDate(d->m_checkInterval); +} - d->updaterProgram = settings->value(QLatin1String("Application")).toString(); - d->m_lastDayChecked = settings->value(QLatin1String("LastDayChecked"), QDate()).toDate(); - d->updaterRunUiArgument = settings->value(QLatin1String("RunUiArgument"), - QLatin1String("--updater")).toString(); - d->updaterCheckOnlyArgument = settings->value(QLatin1String("CheckOnlyArgument"), - QLatin1String("--checkupdates")).toString(); - d->m_scheduledUpdateTime = settings->value(QLatin1String("ScheduledUpdateTime"), QTime(12, 0)) - .toTime(); +QDate UpdateInfoPlugin::nextCheckDate(CheckUpdateInterval interval) const +{ + if (!d->m_lastCheckDate.isValid()) + return QDate(); + + if (interval == DailyCheck) + return d->m_lastCheckDate.addDays(1); + if (interval == WeeklyCheck) + return d->m_lastCheckDate.addDays(7); + return d->m_lastCheckDate.addMonths(1); +} - settings->endGroup(); +void UpdateInfoPlugin::startUpdater() +{ + QProcess::startDetached(d->m_maintenanceTool, QStringList(QLatin1String("--updater"))); } } //namespace Internal diff --git a/src/plugins/updateinfo/updateinfoplugin.h b/src/plugins/updateinfo/updateinfoplugin.h index 6f4c0576cf..69862e1be5 100644 --- a/src/plugins/updateinfo/updateinfoplugin.h +++ b/src/plugins/updateinfo/updateinfoplugin.h @@ -33,26 +33,28 @@ #include -#include -#include +QT_BEGIN_NAMESPACE +class QDate; +QT_END_NAMESPACE namespace UpdateInfo { -namespace Constants { - const char FILTER_OPTIONS_PAGE[] = QT_TRANSLATE_NOOP("Update", "Update"); -} // namespace Constants - namespace Internal { -class SettingsPage; class UpdateInfoPluginPrivate; class UpdateInfoPlugin : public ExtensionSystem::IPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "UpdateInfo.json") - + Q_ENUMS(CheckUpdateInterval) public: + enum CheckUpdateInterval { + DailyCheck, + WeeklyCheck, + MonthlyCheck + }; + UpdateInfoPlugin(); virtual ~UpdateInfoPlugin(); @@ -60,22 +62,39 @@ public: void extensionsInitialized(); bool initialize(const QStringList &arguments, QString *errorMessage); - void loadSettings(); - void saveSettings(); + bool isAutomaticCheck() const; + void setAutomaticCheck(bool on); + + CheckUpdateInterval checkUpdateInterval() const; + void setCheckUpdateInterval(CheckUpdateInterval interval); - QTime scheduledUpdateTime() const; - void setScheduledUpdateTime(const QTime &time); + QDate lastCheckDate() const; + QDate nextCheckDate() const; + QDate nextCheckDate(CheckUpdateInterval interval) const; -protected: - void timerEvent(QTimerEvent *event); + bool isCheckForUpdatesRunning() const; + void startCheckForUpdates(); -private slots: - void parseUpdates(); - void startUpdaterUiApplication(); +signals: + void lastCheckDateChanged(const QDate &date); + void newUpdatesAvailable(bool available); + void checkForUpdatesRunningChanged(bool running); private: - QDomDocument update(); - template void settingsHelper(T *settings); + void setLastCheckDate(const QDate &date); + + void startAutoCheckForUpdates(); + void stopAutoCheckForUpdates(); + void doAutoCheckForUpdates(); + + void startUpdater(); + void stopCheckForUpdates(); + + void collectCheckForUpdatesOutput(const QString &contents); + void checkForUpdatesFinished(); + + void loadSettings() const; + void saveSettings(); private: UpdateInfoPluginPrivate *d; -- cgit v1.2.3