Files
qt-creator/src/plugins/updateinfo/updateinfoplugin.cpp

269 lines
8.8 KiB
C++
Raw Normal View History

/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** 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 Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/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 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "settingspage.h"
#include "updateinfoplugin.h"
#include "updateinfobutton.h"
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
#include <coreplugin/settingsdatabase.h>
#include <qtconcurrentrun.h>
#include <QBasicTimer>
#include <QDomDocument>
#include <QFile>
#include <QFutureWatcher>
#include <QMenu>
#include <QProcess>
#include <QtPlugin>
namespace {
static const quint32 OneMinute = 60000;
}
using namespace Core;
namespace UpdateInfo {
namespace Internal {
class UpdateInfoPluginPrivate
{
public:
UpdateInfoPluginPrivate()
: progressUpdateInfoButton(0),
checkUpdateInfoWatcher(0),
m_settingsPage(0)
{
}
QString updaterProgram;
QString updaterRunUiArgument;
QString updaterCheckOnlyArgument;
QFuture<QDomDocument> lastCheckUpdateInfoTask;
QPointer<FutureProgress> updateInfoProgress;
UpdateInfoButton *progressUpdateInfoButton;
QFutureWatcher<QDomDocument> *checkUpdateInfoWatcher;
QBasicTimer m_timer;
QDate m_lastDayChecked;
QTime m_scheduledUpdateTime;
SettingsPage *m_settingsPage;
};
UpdateInfoPlugin::UpdateInfoPlugin()
: d(new UpdateInfoPluginPrivate)
{
}
UpdateInfoPlugin::~UpdateInfoPlugin()
{
delete d;
}
bool UpdateInfoPlugin::delayedInitialize()
{
d->checkUpdateInfoWatcher = new QFutureWatcher<QDomDocument>(this);
connect(d->checkUpdateInfoWatcher, SIGNAL(finished()), this, SLOT(parseUpdates()));
d->m_timer.start(OneMinute, this);
return true;
}
void UpdateInfoPlugin::extensionsInitialized()
{
}
bool UpdateInfoPlugin::initialize(const QStringList & /* arguments */, QString *errorMessage)
{
loadSettings();
if (d->updaterProgram.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);
return false;
}
d->m_settingsPage = new SettingsPage(this);
addAutoReleasedObject(d->m_settingsPage);
ActionContainer *const container = ActionManager::actionContainer(Core::Constants::M_HELP);
container->menu()->addAction(tr("Start Updater"), this, SLOT(startUpdaterUiApplication()));
return true;
}
void UpdateInfoPlugin::loadSettings()
{
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());
}
}
void UpdateInfoPlugin::saveSettings()
{
SettingsDatabase *settings = ICore::settingsDatabase();
if (settings) {
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();
}
}
QTime UpdateInfoPlugin::scheduledUpdateTime() const
{
return d->m_scheduledUpdateTime;
}
void UpdateInfoPlugin::setScheduledUpdateTime(const QTime &time)
{
d->m_scheduledUpdateTime = time;
}
// -- protected
void UpdateInfoPlugin::timerEvent(QTimerEvent *event)
{
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);
}
}
// -- private slots
void UpdateInfoPlugin::parseUpdates()
{
QDomDocument updatesDomDocument = d->checkUpdateInfoWatcher->result();
if (updatesDomDocument.isNull() || !updatesDomDocument.firstChildElement().hasChildNodes())
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()));
}
void UpdateInfoPlugin::startUpdaterUiApplication()
{
QProcess::startDetached(d->updaterProgram, QStringList() << d->updaterRunUiArgument);
if (!d->updateInfoProgress.isNull()) //this is fading out the last update info
d->updateInfoProgress->setKeepOnFinish(FutureProgress::HideOnFinish);
}
// -- private
QDomDocument UpdateInfoPlugin::update()
{
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);
updater.waitForFinished();
// process return value
QDomDocument updates;
if (updater.exitStatus() != QProcess::CrashExit) {
d->m_timer.stop();
d->m_lastDayChecked = QDate::currentDate();
updates.setContent(updater.readAllStandardOutput());
saveSettings(); // force writing out the last update date
} else {
qWarning() << "Updater application crashed.";
}
return updates;
}
template <typename T>
void UpdateInfoPlugin::settingsHelper(T *settings)
{
settings->beginGroup(QLatin1String("Updater"));
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();
settings->endGroup();
}
} //namespace Internal
} //namespace UpdateInfo
Q_EXPORT_PLUGIN(UpdateInfo::Internal::UpdateInfoPlugin)