Navigation Menu

Skip to content

Commit

Permalink
Refactor|Updater: Separated VersionInfo, UpdaterSettings
Browse files Browse the repository at this point in the history
Also added UpdateAvailableDialog that will be shown after checking for
available updates.
  • Loading branch information
skyjake committed May 26, 2012
1 parent fd21288 commit 6d193e2
Show file tree
Hide file tree
Showing 7 changed files with 318 additions and 128 deletions.
7 changes: 6 additions & 1 deletion doomsday/engine/engine.pro
Expand Up @@ -363,7 +363,10 @@ DENG_HEADERS += \
portable/include/vertex.h \
portable/include/wadfile.h \
portable/include/window.h \
portable/include/zipfile.h
portable/include/zipfile.h \
portable/src/updater/updateavailabledialog.h \
portable/src/updater/updatersettings.h \
portable/src/updater/versioninfo.h

INCLUDEPATH += \
$$DENG_INCLUDE_DIR \
Expand Down Expand Up @@ -640,6 +643,8 @@ SOURCES += \
portable/src/ui_mpi.c \
portable/src/ui_panel.c \
portable/src/updater.cpp \
portable/src/updater/updateavailabledialog.cpp \
portable/src/updater/updatersettings.cpp \
portable/src/uri.c \
portable/src/vertex.cpp \
portable/src/wadfile.c \
Expand Down
137 changes: 10 additions & 127 deletions doomsday/engine/portable/src/updater.cpp
Expand Up @@ -24,6 +24,9 @@
#include "dd_version.h"
#include "dd_types.h"
#include "json.h"
#include "updater/updateavailabledialog.h"
#include "updater/updatersettings.h"
#include "updater/versioninfo.h"
#include <de/Time>
#include <de/Log>
#include <QStringList>
Expand All @@ -35,13 +38,6 @@

static Updater* updater = 0;

#define STK_FREQUENCY "updater/frequency"
#define STK_CHANNEL "updater/channel"
#define STK_LAST_CHECKED "updater/lastChecked"
#define STK_ONLY_MANUAL "updater/onlyManually"
#define STK_DELETE "updater/delete"
#define STK_DOWNLOAD_PATH "updater/downloadPath"

/// @todo The platform ID should come from the Builder.
#if defined(WIN32)
# define PLATFORM_ID "win-x86"
Expand All @@ -63,145 +59,28 @@ static Updater* updater = 0;

struct Updater::Instance
{
enum Frequency
{
Daily = 0,
Biweekly = 1, // 3.5 days
Weekly = 2, // 7 days
Monthly = 3 // 30 days
};
enum Channel
{
Stable = 0,
Unstable = 1
};

struct VersionInfo
{
int major;
int minor;
int revision;
int patch;
int build;

/**
* Version information.
* @todo Could be useful as a generic utility class.
*/
VersionInfo() : patch(0), build(de::Time().asBuildNumber())
{
parseVersionString(DOOMSDAY_VERSION_BASE);
#ifdef DOOMSDAY_BUILD_TEXT
build = de::String(DOOMSDAY_BUILD_TEXT).toInt();
#endif
}

VersionInfo(const de::String& version, int buildNumber) : build(buildNumber)
{
parseVersionString(version);
}

QString asText() const
{
if(patch > 0)
{
return QString("%1.%2.%3-%4 Build %5").arg(major).arg(minor).arg(revision).arg(patch).arg(build);
}
return QString("%1.%2.%3 Build %4").arg(major).arg(minor).arg(revision).arg(build);
}

void parseVersionString(const de::String& version)
{
QStringList parts = version.split('.');
major = parts[0].toInt();
minor = parts[1].toInt();
if(parts[2].contains('-'))
{
QStringList rev = parts[2].split('-');
revision = rev[0].toInt();
patch = rev[1].toInt();
}
else
{
revision = parts[2].toInt();
patch = 0;
}
}

bool operator < (const VersionInfo& other) const
{
if(major == other.major)
{
if(minor == other.minor)
{
if(revision == other.revision)
{
return build < other.build;
}
return revision < other.revision;
}
return minor < other.minor;
}
return major < other.major;
}

bool operator == (const VersionInfo& other) const
{
return major == other.major && minor == other.minor &&
revision == other.revision && build == other.build;
}

bool operator > (const VersionInfo& other) const
{
return !(*this < other || *this == other);
}
};

Updater* self;
QNetworkAccessManager* network;

Frequency checkFrequency;
Channel channel; ///< What kind of updates to check for.
QDateTime lastCheckTime;///< Time of last check (automatic or manual).
bool onlyCheckManually; ///< Should only check when manually requested.
bool deleteAfterUpdate; ///< Downloaded file is deleted afterwards.
QString downloadPath; ///< Path where the downloaded file is saved.
VersionInfo latestVersion;
QString latestPackageUri;
QString latestLogUri;

Instance(Updater* up) : self(up)
{
// Fetch the current settings.
QSettings st;
checkFrequency = Frequency(st.value(STK_FREQUENCY, Weekly).toInt());
channel = Channel(st.value(STK_CHANNEL, QString(DOOMSDAY_RELEASE_TYPE) == "Stable"? Stable : Unstable).toInt());
lastCheckTime = st.value(STK_LAST_CHECKED).toDateTime();
onlyCheckManually = st.value(STK_ONLY_MANUAL, false).toBool();
deleteAfterUpdate = st.value(STK_DELETE, true).toBool();
downloadPath = st.value(STK_DOWNLOAD_PATH,
QDesktopServices::storageLocation(QDesktopServices::TempLocation)).toString();

network = new QNetworkAccessManager(self);
}

~Instance()
{
// Save settings.
QSettings st;
st.setValue(STK_FREQUENCY, int(checkFrequency));
st.setValue(STK_CHANNEL, int(channel));
st.setValue(STK_LAST_CHECKED, lastCheckTime);
st.setValue(STK_ONLY_MANUAL, onlyCheckManually);
st.setValue(STK_DELETE, deleteAfterUpdate);
st.setValue(STK_DOWNLOAD_PATH, downloadPath);
}

QString composeCheckUri()
{
UpdaterSettings st;
QString uri = QString(DOOMSDAY_HOMEURL) + "/latestbuild?";
uri += QString("platform=") + PLATFORM_ID;
uri += (channel == Stable? "&stable" : "&unstable");
uri += (st.channel() == UpdaterSettings::Stable? "&stable" : "&unstable");
uri += "&graph";

LOG_DEBUG("Check URI: ") << uri;
Expand All @@ -210,7 +89,7 @@ struct Updater::Instance

void queryLatestVersion()
{
lastCheckTime = QDateTime::currentDateTime();
UpdaterSettings().setLastCheckTime(de::Time());
network->get(QNetworkRequest(composeCheckUri()));
}

Expand All @@ -236,7 +115,11 @@ struct Updater::Instance
<< latestPackageUri << latestLogUri;

// Is this newer than what we're running?
UpdateAvailableDialog* dlg = new UpdateAvailableDialog;

dlg->exec();

delete dlg;
}
};

Expand Down
58 changes: 58 additions & 0 deletions doomsday/engine/portable/src/updater/updateavailabledialog.cpp
@@ -0,0 +1,58 @@
#include "updateavailabledialog.h"
#include "versioninfo.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QDialogButtonBox>
#include <QCheckBox>
#include <QPushButton>
#include <QFont>
#include <QLabel>

struct UpdateAvailableDialog::Instance
{
UpdateAvailableDialog* self;

QLabel* info;

Instance(UpdateAvailableDialog* d) : self(d)
{
QVBoxLayout* mainLayout = new QVBoxLayout(self);
self->setLayout(mainLayout);
//mainLayout->setMargin(12);

info = new QLabel;
info->setTextFormat(Qt::RichText);
info->setText(QString("<span style=\"font-weight:bold; font-size:%1pt;\">You are up to date.</span>"
"<p>The installed version %2 is the latest available stable build.")
.arg(int(self->font().pointSize() * 1.2))
.arg(VersionInfo().asText()));

QCheckBox* neverCheck = new QCheckBox("Never check for updates automatically");

QDialogButtonBox* bbox = new QDialogButtonBox;

QPushButton* ok = bbox->addButton("Ok", QDialogButtonBox::AcceptRole);
ok->setDefault(true);

QPushButton* cfg = bbox->addButton("Settings...", QDialogButtonBox::ActionRole);
cfg->setAutoDefault(false);
cfg->setDefault(false);

//QPushButton* whatsNew = bbox->addButton("What's new?", QDialogButtonBox::HelpRole);

mainLayout->addWidget(info);
mainLayout->addWidget(neverCheck);
mainLayout->addWidget(bbox);
}
};

UpdateAvailableDialog::UpdateAvailableDialog(QWidget *parent)
: QDialog(parent)
{
d = new Instance(this);
}

UpdateAvailableDialog::~UpdateAvailableDialog()
{
delete d;
}
19 changes: 19 additions & 0 deletions doomsday/engine/portable/src/updater/updateavailabledialog.h
@@ -0,0 +1,19 @@
#ifndef LIBDENG_UPDATEAVAILABLEDIALOG_H
#define LIBDENG_UPDATEAVAILABLEDIALOG_H

#include <QDialog>

class UpdateAvailableDialog : public QDialog
{
Q_OBJECT

public:
explicit UpdateAvailableDialog(QWidget *parent = 0);
~UpdateAvailableDialog();

private:
struct Instance;
Instance* d;
};

#endif // LIBDENG_UPDATEAVAILABLEDIALOG_H
92 changes: 92 additions & 0 deletions doomsday/engine/portable/src/updater/updatersettings.cpp
@@ -0,0 +1,92 @@
#include "updatersettings.h"
#include "versioninfo.h"
#include <QDateTime>
#include <QSettings>
#include <QDesktopServices>

#define STK_FREQUENCY "updater/frequency"
#define STK_CHANNEL "updater/channel"
#define STK_LAST_CHECKED "updater/lastChecked"
#define STK_ONLY_MANUAL "updater/onlyManually"
#define STK_DELETE "updater/delete"
#define STK_DOWNLOAD_PATH "updater/downloadPath"

static de::String defaultDownloadPath()
{
return QDesktopServices::storageLocation(QDesktopServices::TempLocation);
}

UpdaterSettings::UpdaterSettings()
{}

UpdaterSettings::Frequency UpdaterSettings::frequency() const
{
return Frequency(QSettings().value(STK_FREQUENCY, Weekly).toInt());
}

UpdaterSettings::Channel UpdaterSettings::channel() const
{
return Channel(QSettings().value(STK_CHANNEL,
QString(DOOMSDAY_RELEASE_TYPE) == "Stable"? Stable : Unstable).toInt());
}

de::Time UpdaterSettings::lastCheckTime() const
{
return QSettings().value(STK_LAST_CHECKED).toDateTime();
}

bool UpdaterSettings::onlyCheckManually() const
{
return QSettings().value(STK_ONLY_MANUAL, false).toBool();
}

bool UpdaterSettings::deleteAfterUpdate() const
{
return QSettings().value(STK_DELETE, true).toBool();
}

bool UpdaterSettings::isDefaultDownloadPath() const
{
de::String path = downloadPath();
return path == defaultDownloadPath();
}

de::String UpdaterSettings::downloadPath() const
{
return QSettings().value(STK_DOWNLOAD_PATH, defaultDownloadPath()).toString();
}

void UpdaterSettings::setFrequency(UpdaterSettings::Frequency freq)
{
QSettings().setValue(STK_FREQUENCY, int(freq));
}

void UpdaterSettings::channel(UpdaterSettings::Channel channel)
{
QSettings().setValue(STK_CHANNEL, int(channel));
}

void UpdaterSettings::setLastCheckTime(const de::Time &time)
{
QSettings().setValue(STK_LAST_CHECKED, time.asDateTime());
}

void UpdaterSettings::setOnlyCheckManually(bool onlyManually)
{
QSettings().setValue(STK_ONLY_MANUAL, onlyManually);
}

void UpdaterSettings::setDeleteAfterUpdate(bool deleteAfter)
{
QSettings().setValue(STK_DELETE, deleteAfter);
}

void UpdaterSettings::setDownloadPath(de::String downloadPath)
{
QSettings().setValue(STK_DOWNLOAD_PATH, downloadPath);
}

void UpdaterSettings::useDefaultDownloadPath()
{
setDownloadPath(defaultDownloadPath());
}

0 comments on commit 6d193e2

Please sign in to comment.