diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 30dab3644a..00f6d4c3b2 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -140,7 +140,7 @@ target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) # link required hifi libraries link_hifi_libraries(shared octree environment gpu model render fbx networking entities avatars audio audio-client animation script-engine physics - render-utils entities-renderer ui) + render-utils entities-renderer ui auto-updater) add_dependency_external_projects(sdl2) diff --git a/interface/resources/qml/UpdateDialog.qml b/interface/resources/qml/UpdateDialog.qml new file mode 100644 index 0000000000..e5216ff619 --- /dev/null +++ b/interface/resources/qml/UpdateDialog.qml @@ -0,0 +1,172 @@ +import Hifi 1.0 +import QtQuick 2.3 +import QtQuick.Controls.Styles 1.3 +import QtGraphicalEffects 1.0 +import "controls" +import "styles" + +DialogContainer { + HifiConstants { id: hifi } + id: root + objectName: "UpdateDialog" + implicitWidth: updateDialog.width + implicitHeight: updateDialog.height + x: parent ? parent.width / 2 - width / 2 : 0 + y: parent ? parent.height / 2 - height / 2 : 0 + + UpdateDialog { + id: updateDialog + + implicitWidth: backgroundRectangle.width + implicitHeight: backgroundRectangle.height + + readonly property int inputWidth: 500 + readonly property int inputHeight: 60 + readonly property int borderWidth: 30 + readonly property int closeMargin: 16 + readonly property int inputSpacing: 16 + readonly property int buttonWidth: 150 + readonly property int buttonHeight: 50 + readonly property int buttonRadius: 15 + + signal triggerBuildDownload + signal closeUpdateDialog + + Column { + id: mainContent + width: updateDialog.inputWidth + spacing: updateDialog.inputSpacing + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + + Rectangle { + id: backgroundRectangle + color: "#2c86b1" + opacity: 0.85 + radius: updateDialog.closeMargin * 2 + + width: updateDialog.inputWidth + updateDialog.borderWidth * 2 + height: updateDialog.inputHeight * 6 + updateDialog.closeMargin * 2 + + Rectangle { + id: dialogTitle + width: updateDialog.inputWidth + height: updateDialog.inputHeight + radius: height / 2 + color: "#ebebeb" + + anchors { + top: parent.top + topMargin: updateDialog.inputSpacing + horizontalCenter: parent.horizontalCenter + } + + Text { + id: updateAvailableText + text: "Update Available" + anchors { + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: updateDialog.inputSpacing + } + } + + Text { + text: updateDialog.updateAvailableDetails + font.pixelSize: 14 + color: hifi.colors.text + anchors { + verticalCenter: parent.verticalCenter + left: updateAvailableText.right + leftMargin: 13 + } + } + } + + Flickable { + id: scrollArea + anchors { + top: dialogTitle.bottom + } + contentWidth: updateDialog.inputWidth + contentHeight: backgroundRectangle.height - (dialogTitle.height * 2.5) + width: updateDialog.inputWidth + height: backgroundRectangle.height - (dialogTitle.height * 2.5) + flickableDirection: Flickable.VerticalFlick + clip: true + + TextEdit { + id: releaseNotes + wrapMode: TextEdit.Wrap + width: parent.width + readOnly: true + text: updateDialog.releaseNotes + font.pixelSize: 14 + color: hifi.colors.text + anchors { + left: parent.left + leftMargin: updateDialog.borderWidth + } + } + } + + Rectangle { + id: downloadButton + width: updateDialog.buttonWidth + height: updateDialog.buttonHeight + radius: updateDialog.buttonRadius + color: "green" + anchors { + top: scrollArea.bottom + topMargin: 10 + right: backgroundRectangle.right + rightMargin: 15 + } + Text { + text: "Upgrade" + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + } + MouseArea { + id: downloadButtonAction + anchors.fill: parent + onClicked: updateDialog.triggerUpgrade() + cursorShape: "PointingHandCursor" + } + } + + Rectangle { + id: cancelButton + width: updateDialog.buttonWidth + height: updateDialog.buttonHeight + radius: updateDialog.buttonRadius + color: "red" + anchors { + top: scrollArea.bottom + topMargin: 10 + right: downloadButton.left + rightMargin: 15 + } + + Text { + text: "Cancel" + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + } + MouseArea { + id: cancelButtonAction + anchors.fill: parent + onClicked: updateDialog.closeDialog() + cursorShape: "PointingHandCursor" + } + } + } + } + } +} \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 22cbad6775..662a8603d3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -147,6 +148,7 @@ #include "ui/StandAloneJSConsole.h" #include "ui/Stats.h" #include "ui/AddressBarDialog.h" +#include "ui/UpdateDialog.h" // ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU @@ -296,6 +298,7 @@ bool setupEssentials(int& argc, char** argv) { auto discoverabilityManager = DependencyManager::set(); auto sceneScriptingInterface = DependencyManager::set(); auto offscreenUi = DependencyManager::set(); + auto autoUpdater = DependencyManager::set(); auto pathUtils = DependencyManager::set(); auto actionFactory = DependencyManager::set(); @@ -563,8 +566,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // allow you to move an entity around in your hand _entityEditSender.setPacketsPerSecond(3000); // super high!! - checkVersion(); - _overlays.init(); // do this before scripts load _runningScriptsWidget->setRunningScripts(getRunningScripts()); @@ -636,9 +637,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : ddeTracker->init(); connect(ddeTracker.data(), &FaceTracker::muteToggled, this, &Application::faceTrackerMuteToggled); #endif + + auto applicationUpdater = DependencyManager::get(); + connect(applicationUpdater.data(), &AutoUpdater::newVersionIsAvailable, dialogsManager.data(), &DialogsManager::showUpdateDialog); + applicationUpdater->checkForUpdate(); } - void Application::aboutToQuit() { emit beforeAboutToQuit(); @@ -828,6 +832,7 @@ void Application::initializeUi() { LoginDialog::registerType(); MessageDialog::registerType(); VrMenu::registerType(); + UpdateDialog::registerType(); auto offscreenUi = DependencyManager::get(); offscreenUi->create(_glWidget->context()->contextHandle()); @@ -4523,72 +4528,6 @@ void Application::toggleLogDialog() { } } -void Application::checkVersion() { - QNetworkRequest latestVersionRequest((QUrl(CHECK_VERSION_URL))); - latestVersionRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); - latestVersionRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - QNetworkReply* reply = NetworkAccessManager::getInstance().get(latestVersionRequest); - connect(reply, SIGNAL(finished()), SLOT(parseVersionXml())); -} - -void Application::parseVersionXml() { - - #ifdef Q_OS_WIN32 - QString operatingSystem("win"); - #endif - - #ifdef Q_OS_MAC - QString operatingSystem("mac"); - #endif - - #ifdef Q_OS_LINUX - QString operatingSystem("ubuntu"); - #endif - - QString latestVersion; - QUrl downloadUrl; - QString releaseNotes("Unavailable"); - QNetworkReply* sender = qobject_cast(QObject::sender()); - - QXmlStreamReader xml(sender); - - while (!xml.atEnd() && !xml.hasError()) { - if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == operatingSystem) { - while (!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == operatingSystem)) { - if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name().toString() == "version") { - xml.readNext(); - latestVersion = xml.text().toString(); - } - if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name().toString() == "url") { - xml.readNext(); - downloadUrl = QUrl(xml.text().toString()); - } - xml.readNext(); - } - } - xml.readNext(); - } - - if (!shouldSkipVersion(latestVersion) && applicationVersion() != latestVersion) { - new UpdateDialog(_glWidget, releaseNotes, latestVersion, downloadUrl); - } - sender->deleteLater(); -} - -bool Application::shouldSkipVersion(QString latestVersion) { - QFile skipFile(SKIP_FILENAME); - skipFile.open(QIODevice::ReadWrite); - QString skipVersion(skipFile.readAll()); - return (skipVersion == latestVersion || applicationVersion() == "dev"); -} - -void Application::skipVersion(QString latestVersion) { - QFile skipFile(SKIP_FILENAME); - skipFile.open(QIODevice::WriteOnly | QIODevice::Truncate); - skipFile.seek(0); - skipFile.write(latestVersion.toStdString().c_str()); -} - void Application::takeSnapshot() { QMediaPlayer* player = new QMediaPlayer(); QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav"); diff --git a/interface/src/Application.h b/interface/src/Application.h index 68bf60781a..c9e5bea76e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -66,7 +66,6 @@ #include "ui/SnapshotShareDialog.h" #include "ui/LodToolsDialog.h" #include "ui/LogDialog.h" -#include "ui/UpdateDialog.h" #include "ui/overlays/Overlays.h" #include "ui/ApplicationOverlay.h" #include "ui/RunningScriptsWidget.h" @@ -312,8 +311,6 @@ public: NodeToJurisdictionMap& getEntityServerJurisdictions() { return _entityServerJurisdictions; } - void skipVersion(QString latestVersion); - QStringList getRunningScripts() { return _scriptEnginesHash.keys(); } ScriptEngine* getScriptEngine(QString scriptHash) { return _scriptEnginesHash.contains(scriptHash) ? _scriptEnginesHash[scriptHash] : NULL; } @@ -460,8 +457,6 @@ private slots: void restoreMirrorView(); void shrinkMirrorView(); - void parseVersionXml(); - void manageRunningScriptsWidgetVisibility(bool shown); void runTests(); @@ -627,9 +622,6 @@ private: FileLogger* _logger; - void checkVersion(); - void displayUpdateDialog(); - bool shouldSkipVersion(QString latestVersion); void takeSnapshot(); TouchEvent _lastTouchEvent; diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 1170e3c3a6..81c7cd2770 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -31,6 +31,7 @@ #include "OctreeStatsDialog.h" #include "PreferencesDialog.h" #include "ScriptEditorWindow.h" +#include "UpdateDialog.h" void DialogsManager::toggleAddressBar() { @@ -50,6 +51,10 @@ void DialogsManager::showLoginDialog() { LoginDialog::show(); } +void DialogsManager::showUpdateDialog() { + UpdateDialog::show(); +} + void DialogsManager::octreeStatsDetails() { if (!_octreeStatsDialog) { _octreeStatsDialog = new OctreeStatsDialog(qApp->getWindow(), qApp->getOcteeSceneStats()); diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index fc2dad072b..7eb716b73c 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -35,6 +35,7 @@ class ScriptEditorWindow; class QMessageBox; class AvatarAppearanceDialog; class DomainConnectionDialog; +class UpdateDialog; class DialogsManager : public QObject, public Dependency { Q_OBJECT @@ -64,6 +65,9 @@ public slots: void showIRCLink(); void changeAvatarAppearance(); void showDomainConnectionDialog(); + + // Application Update + void showUpdateDialog(); private slots: void toggleToolWindow(); @@ -101,6 +105,7 @@ private: QPointer _scriptEditor; QPointer _avatarAppearanceDialog; QPointer _domainConnectionDialog; + QPointer _updateDialog; }; #endif // hifi_DialogsManager_h diff --git a/interface/src/ui/UpdateDialog.cpp b/interface/src/ui/UpdateDialog.cpp index 40b32d66e3..69dfc343d9 100644 --- a/interface/src/ui/UpdateDialog.cpp +++ b/interface/src/ui/UpdateDialog.cpp @@ -2,54 +2,50 @@ // UpdateDialog.cpp // interface/src/ui // -// Copyright 2014 High Fidelity, Inc. +// Created by Leonardo Murillo on 6/3/15. +// Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - -#include "ui_updateDialog.h" - -#include "Application.h" #include "UpdateDialog.h" +#include -UpdateDialog::UpdateDialog(QWidget *parent, const QString& releaseNotes, const QString& latestVersion, const QUrl& downloadURL) : - QDialog(parent), - _latestVersion(latestVersion), - _downloadUrl(downloadURL) +#include "DependencyManager.h" + +HIFI_QML_DEF(UpdateDialog) + +UpdateDialog::UpdateDialog(QQuickItem* parent) : + OffscreenQmlDialog(parent) { - Ui::Dialog dialogUI; - dialogUI.setupUi(this); - - QString updateRequired = QString("You are currently running build %1, the latest build released is %2." - "\n\nPlease download and install the most recent release to access the latest features and bug fixes.") - .arg(Application::getInstance()->applicationVersion(), latestVersion); - - setAttribute(Qt::WA_DeleteOnClose); - - QPushButton* downloadButton = findChild("downloadButton"); - QPushButton* skipButton = findChild("skipButton"); - QPushButton* closeButton = findChild("closeButton"); - QLabel* updateContent = findChild("updateContent"); - - updateContent->setText(updateRequired); - - connect(downloadButton, SIGNAL(released()), this, SLOT(handleDownload())); - connect(skipButton, SIGNAL(released()), this, SLOT(handleSkip())); - connect(closeButton, SIGNAL(released()), this, SLOT(close())); - - QMetaObject::invokeMethod(this, "show", Qt::QueuedConnection); + auto applicationUpdater = DependencyManager::get(); + int currentVersion = QCoreApplication::applicationVersion().toInt(); + int latestVersion = applicationUpdater.data()->getBuildData().lastKey(); + int versionsBehind = latestVersion - currentVersion; + _updateAvailableDetails = "v" + QString::number(latestVersion) + " released on " + applicationUpdater.data()->getBuildData()[latestVersion]["releaseTime"]; + _updateAvailableDetails += "\nYou are " + QString::number(versionsBehind) + " versions behind"; + _releaseNotes = applicationUpdater.data()->getBuildData()[latestVersion]["releaseNotes"]; } -void UpdateDialog::handleDownload() { - QDesktopServices::openUrl(_downloadUrl); - Application::getInstance()->quit(); +const QString& UpdateDialog::updateAvailableDetails() const { + return _updateAvailableDetails; } -void UpdateDialog::handleSkip() { - Application::getInstance()->skipVersion(_latestVersion); - this->close(); +const QString& UpdateDialog::releaseNotes() const { + return _releaseNotes; } + +void UpdateDialog::closeDialog() { + hide(); +} + +void UpdateDialog::hide() { + ((QQuickItem*)parent())->setEnabled(false); +} + +void UpdateDialog::triggerUpgrade() { + auto applicationUpdater = DependencyManager::get(); + applicationUpdater.data()->performAutoUpdate(applicationUpdater.data()->getBuildData().lastKey()); +} \ No newline at end of file diff --git a/interface/src/ui/UpdateDialog.h b/interface/src/ui/UpdateDialog.h index 15a97bf024..84d390c942 100644 --- a/interface/src/ui/UpdateDialog.h +++ b/interface/src/ui/UpdateDialog.h @@ -2,30 +2,42 @@ // UpdateDialog.h // interface/src/ui // -// Copyright 2014 High Fidelity, Inc. +// Created by Leonardo Murillo on 6/3/15. +// Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#pragma once #ifndef hifi_UpdateDialog_h #define hifi_UpdateDialog_h -#include +#include -class UpdateDialog : public QDialog { +#include + +class UpdateDialog : public OffscreenQmlDialog { Q_OBJECT + HIFI_QML_DECL + + Q_PROPERTY(QString updateAvailableDetails READ updateAvailableDetails) + Q_PROPERTY(QString releaseNotes READ releaseNotes) public: - UpdateDialog(QWidget* parent, const QString& releaseNotes, const QString& latestVersion, const QUrl& downloadURL); + UpdateDialog(QQuickItem* parent = nullptr); + const QString& updateAvailableDetails() const; + const QString& releaseNotes() const; private: - QString _latestVersion; - QUrl _downloadUrl; - -private slots: - void handleDownload(); - void handleSkip(); + QString _updateAvailableDetails; + QString _releaseNotes; + +protected: + void hide(); + Q_INVOKABLE void triggerUpgrade(); + Q_INVOKABLE void closeDialog(); + }; #endif // hifi_UpdateDialog_h diff --git a/interface/ui/updateDialog.ui b/interface/ui/updateDialog.ui deleted file mode 100644 index fc375e17c2..0000000000 --- a/interface/ui/updateDialog.ui +++ /dev/null @@ -1,132 +0,0 @@ - - - Dialog - - - Qt::NonModal - - - - 0 - 0 - 750 - 213 - - - - PointingHandCursor - - - Update Required - - - background-color: rgb(255, 255, 255); - - - - - 50 - 20 - 641 - 111 - - - - - Arial - -1 - - - - font-family: Arial; -font-size: 20px; - - - - - - true - - - - - - 360 - 160 - 374 - 42 - - - - - - - PointingHandCursor - - - background-color: #333333; -border-width: 0; -border-radius: 9px; -border-radius: 9px; -font-family: Arial; -font-size: 18px; -font-weight: 100; -color: #b7b7b7; -width: 120px; -height: 40px; - - - Download - - - - - - - PointingHandCursor - - - background-color: #333333; -border-width: 0; -border-radius: 9px; -border-radius: 9px; -font-family: Arial; -font-size: 18px; -font-weight: 100; -color: #b7b7b7; -width: 120px; -height: 40px; - - - Skip Version - - - - - - - PointingHandCursor - - - background-color: #333333; -border-width: 0; -border-radius: 9px; -border-radius: 9px; -font-family: Arial; -font-size: 18px; -font-weight: 100; -color: #b7b7b7; -width: 120px; -height: 40px; - - - Close - - - - - - - - - diff --git a/libraries/auto-updater/CMakeLists.txt b/libraries/auto-updater/CMakeLists.txt new file mode 100644 index 0000000000..b3665af2cb --- /dev/null +++ b/libraries/auto-updater/CMakeLists.txt @@ -0,0 +1,3 @@ +set(TARGET_NAME auto-updater) +setup_hifi_library(Network) +link_hifi_libraries(shared networking) diff --git a/libraries/auto-updater/src/AutoUpdater.cpp b/libraries/auto-updater/src/AutoUpdater.cpp new file mode 100644 index 0000000000..445cdaec7b --- /dev/null +++ b/libraries/auto-updater/src/AutoUpdater.cpp @@ -0,0 +1,140 @@ +// +// AutoUpdater.cpp +// libraries/auto-update/src +// +// Created by Leonardo Murillo on 6/1/2015. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "AutoUpdater.h" + +#include +#include + +AutoUpdater::AutoUpdater() { +#if defined Q_OS_WIN32 + _operatingSystem = "windows"; +#elif defined Q_OS_MAC + _operatingSystem = "mac"; +#elif defined Q_OS_LINUX + _operatingSystem = "ubuntu"; +#endif + + connect(this, SIGNAL(latestVersionDataParsed()), this, SLOT(checkVersionAndNotify())); +} + +void AutoUpdater::checkForUpdate() { + this->getLatestVersionData(); +} + +void AutoUpdater::getLatestVersionData() { + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkRequest latestVersionRequest(BUILDS_XML_URL); + latestVersionRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); + QNetworkReply* reply = networkAccessManager.get(latestVersionRequest); + connect(reply, &QNetworkReply::finished, this, &AutoUpdater::parseLatestVersionData); +} + +void AutoUpdater::parseLatestVersionData() { + QNetworkReply* sender = qobject_cast(QObject::sender()); + + QXmlStreamReader xml(sender); + + int version; + QString downloadUrl; + QString releaseTime; + QString releaseNotes; + QString commitSha; + QString pullRequestNumber; + + while (!xml.atEnd() && !xml.hasError()) { + if (xml.name().toString() == "project" && + xml.attributes().hasAttribute("name") && + xml.attributes().value("name").toString() == "interface") { + xml.readNext(); + + while (!xml.atEnd() && !xml.hasError() && xml.name().toString() != "project") { + if (xml.name().toString() == "platform" && + xml.attributes().hasAttribute("name") && + xml.attributes().value("name").toString() == _operatingSystem) { + xml.readNext(); + while (!xml.atEnd() && !xml.hasError() && + xml.name().toString() != "platform") { + + if (xml.name().toString() == "build" && xml.tokenType() != QXmlStreamReader::EndElement) { + xml.readNext(); + version = xml.readElementText().toInt(); + xml.readNext(); + downloadUrl = xml.readElementText(); + xml.readNext(); + releaseTime = xml.readElementText(); + xml.readNext(); + if (xml.name().toString() == "notes" && xml.tokenType() != QXmlStreamReader::EndElement) { + xml.readNext(); + while (!xml.atEnd() && !xml.hasError() && xml.name().toString() != "notes") { + if (xml.name().toString() == "note" && xml.tokenType() != QXmlStreamReader::EndElement) { + releaseNotes = releaseNotes + "\n" + xml.readElementText(); + } + xml.readNext(); + } + } + xml.readNext(); + commitSha = xml.readElementText(); + xml.readNext(); + pullRequestNumber = xml.readElementText(); + appendBuildData(version, downloadUrl, releaseTime, releaseNotes, pullRequestNumber); + releaseNotes = ""; + } + + xml.readNext(); + } + } + xml.readNext(); + } + + } else { + xml.readNext(); + } + } + sender->deleteLater(); + emit latestVersionDataParsed(); +} + +void AutoUpdater::checkVersionAndNotify() { + int latestVersionAvailable = _builds.lastKey(); + if (QCoreApplication::applicationVersion() != "dev" && + QCoreApplication::applicationVersion().toInt() < latestVersionAvailable) { + emit newVersionIsAvailable(); + } +} + +void AutoUpdater::performAutoUpdate(int version) { + // NOTE: This is not yet auto updating - however this is a checkpoint towards that end + // Next PR will handle the automatic download, upgrading and application restart + const QMap& chosenVersion = _builds.value(version); + const QUrl& downloadUrl = chosenVersion.value("downloadUrl"); + QDesktopServices::openUrl(downloadUrl); + QCoreApplication::quit(); +} + +void AutoUpdater::downloadUpdateVersion(int version) { + emit newVersionIsDownloaded(); +} + +void AutoUpdater::appendBuildData(int versionNumber, + const QString& downloadURL, + const QString& releaseTime, + const QString& releaseNotes, + const QString& pullRequestNumber) { + + QMap thisBuildDetails; + thisBuildDetails.insert("downloadUrl", downloadURL); + thisBuildDetails.insert("releaseTime", releaseTime); + thisBuildDetails.insert("releaseNotes", releaseNotes); + thisBuildDetails.insert("pullRequestNumber", pullRequestNumber); + _builds.insert(versionNumber, thisBuildDetails); + +} \ No newline at end of file diff --git a/libraries/auto-updater/src/AutoUpdater.h b/libraries/auto-updater/src/AutoUpdater.h new file mode 100644 index 0000000000..70867e5a44 --- /dev/null +++ b/libraries/auto-updater/src/AutoUpdater.h @@ -0,0 +1,68 @@ +// +// AutoUpdater.h +// libraries/auto-update/src +// +// Created by Leonardo Murillo on 6/1/2015. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AutoUpdater_h +#define hifi_AutoUpdater_h + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +const QUrl BUILDS_XML_URL("https://highfidelity.com/builds.xml"); + +class AutoUpdater : public QObject, public Dependency { + Q_OBJECT + SINGLETON_DEPENDENCY + +public: + AutoUpdater(); + + void checkForUpdate(); + const QMap>& getBuildData() { return _builds; } + void performAutoUpdate(int version); + +signals: + void latestVersionDataParsed(); + void newVersionIsAvailable(); + void newVersionIsDownloaded(); + +private: + QMap> _builds; + QString _operatingSystem; + + void getLatestVersionData(); + void downloadUpdateVersion(int version); + void appendBuildData(int versionNumber, + const QString& downloadURL, + const QString& releaseTime, + const QString& releaseNotes, + const QString& pullRequestNumber); + +private slots: + void parseLatestVersionData(); + void checkVersionAndNotify(); +}; + +#endif // _hifi_AutoUpdater_h