Add release channels for autoupdater (#2362)
Fetch releases from github and find corresponding installers on bintray
This commit is contained in:
parent
b9cd942308
commit
7373819c32
16 changed files with 507 additions and 237 deletions
|
@ -3,8 +3,10 @@ set(VERSION_STRING_H "${PROJECT_BINARY_DIR}/version_string.h")
|
||||||
INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR})
|
INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
set( hstring "extern const char *VERSION_STRING\;
|
set( hstring "extern const char *VERSION_STRING\;
|
||||||
|
extern const char *VERSION_COMMIT\;
|
||||||
extern const char *VERSION_DATE\;\n" )
|
extern const char *VERSION_DATE\;\n" )
|
||||||
set( cppstring "const char *VERSION_STRING = \"${PROJECT_VERSION_FRIENDLY}\"\;
|
set( cppstring "const char *VERSION_STRING = \"${PROJECT_VERSION_FRIENDLY}\"\;
|
||||||
|
const char *VERSION_COMMIT = \"${GIT_COMMIT_ID}\"\;
|
||||||
const char *VERSION_DATE = \"${GIT_COMMIT_DATE_FRIENDLY}\"\;\n")
|
const char *VERSION_DATE = \"${GIT_COMMIT_DATE_FRIENDLY}\"\;\n")
|
||||||
|
|
||||||
file(WRITE ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${cppstring} )
|
file(WRITE ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${cppstring} )
|
||||||
|
|
|
@ -112,9 +112,9 @@ SET(cockatrice_SOURCES
|
||||||
src/settings/messagesettings.cpp
|
src/settings/messagesettings.cpp
|
||||||
src/settings/gamefilterssettings.cpp
|
src/settings/gamefilterssettings.cpp
|
||||||
src/settings/layoutssettings.cpp
|
src/settings/layoutssettings.cpp
|
||||||
src/update_checker.cpp
|
|
||||||
src/update_downloader.cpp
|
src/update_downloader.cpp
|
||||||
src/logger.cpp
|
src/logger.cpp
|
||||||
|
src/releasechannel.cpp
|
||||||
${VERSION_STRING_CPP}
|
${VERSION_STRING_CPP}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
#include "thememanager.h"
|
#include "thememanager.h"
|
||||||
#include "priceupdater.h"
|
#include "priceupdater.h"
|
||||||
|
#include "releasechannel.h"
|
||||||
#include "soundengine.h"
|
#include "soundengine.h"
|
||||||
#include "sequenceEdit/shortcutstab.h"
|
#include "sequenceEdit/shortcutstab.h"
|
||||||
|
|
||||||
|
@ -44,8 +45,18 @@ GeneralSettingsPage::GeneralSettingsPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
picDownloadCheckBox.setChecked(settingsCache->getPicDownload());
|
picDownloadCheckBox.setChecked(settingsCache->getPicDownload());
|
||||||
|
|
||||||
|
// updates
|
||||||
|
QList<ReleaseChannel*> channels = settingsCache->getUpdateReleaseChannels();
|
||||||
|
foreach(ReleaseChannel* chan, channels)
|
||||||
|
{
|
||||||
|
updateReleaseChannelBox.insertItem(chan->getIndex(), tr(chan->getName().toUtf8()));
|
||||||
|
}
|
||||||
|
updateReleaseChannelBox.setCurrentIndex(settingsCache->getUpdateReleaseChannel()->getIndex());
|
||||||
|
|
||||||
updateNotificationCheckBox.setChecked(settingsCache->getNotifyAboutUpdates());
|
updateNotificationCheckBox.setChecked(settingsCache->getNotifyAboutUpdates());
|
||||||
|
|
||||||
|
// pixmap cache
|
||||||
pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN);
|
pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN);
|
||||||
// 2047 is the max value to avoid overflowing of QPixmapCache::setCacheLimit(int size)
|
// 2047 is the max value to avoid overflowing of QPixmapCache::setCacheLimit(int size)
|
||||||
pixmapCacheEdit.setMaximum(PIXMAPCACHE_SIZE_MAX);
|
pixmapCacheEdit.setMaximum(PIXMAPCACHE_SIZE_MAX);
|
||||||
|
@ -60,6 +71,7 @@ GeneralSettingsPage::GeneralSettingsPage()
|
||||||
connect(&languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(languageBoxChanged(int)));
|
connect(&languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(languageBoxChanged(int)));
|
||||||
connect(&picDownloadCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownload(int)));
|
connect(&picDownloadCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownload(int)));
|
||||||
connect(&pixmapCacheEdit, SIGNAL(valueChanged(int)), settingsCache, SLOT(setPixmapCacheSize(int)));
|
connect(&pixmapCacheEdit, SIGNAL(valueChanged(int)), settingsCache, SLOT(setPixmapCacheSize(int)));
|
||||||
|
connect(&updateReleaseChannelBox, SIGNAL(currentIndexChanged(int)), settingsCache, SLOT(setUpdateReleaseChannel(int)));
|
||||||
connect(&updateNotificationCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setNotifyAboutUpdate(int)));
|
connect(&updateNotificationCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setNotifyAboutUpdate(int)));
|
||||||
connect(&picDownloadCheckBox, SIGNAL(clicked(bool)), this, SLOT(setEnabledStatus(bool)));
|
connect(&picDownloadCheckBox, SIGNAL(clicked(bool)), this, SLOT(setEnabledStatus(bool)));
|
||||||
connect(defaultUrlEdit, SIGNAL(textChanged(QString)), settingsCache, SLOT(setPicUrl(QString)));
|
connect(defaultUrlEdit, SIGNAL(textChanged(QString)), settingsCache, SLOT(setPicUrl(QString)));
|
||||||
|
@ -74,16 +86,18 @@ GeneralSettingsPage::GeneralSettingsPage()
|
||||||
personalGrid->addWidget(&languageBox, 0, 1);
|
personalGrid->addWidget(&languageBox, 0, 1);
|
||||||
personalGrid->addWidget(&pixmapCacheLabel, 1, 0);
|
personalGrid->addWidget(&pixmapCacheLabel, 1, 0);
|
||||||
personalGrid->addWidget(&pixmapCacheEdit, 1, 1);
|
personalGrid->addWidget(&pixmapCacheEdit, 1, 1);
|
||||||
personalGrid->addWidget(&updateNotificationCheckBox, 2, 0);
|
personalGrid->addWidget(&updateReleaseChannelLabel, 2, 0);
|
||||||
personalGrid->addWidget(&picDownloadCheckBox, 3, 0, 1, 3);
|
personalGrid->addWidget(&updateReleaseChannelBox, 2, 1);
|
||||||
personalGrid->addWidget(&defaultUrlLabel, 4, 0, 1, 1);
|
personalGrid->addWidget(&updateNotificationCheckBox, 3, 0);
|
||||||
personalGrid->addWidget(defaultUrlEdit, 4, 1, 1, 1);
|
personalGrid->addWidget(&picDownloadCheckBox, 4, 0, 1, 3);
|
||||||
personalGrid->addWidget(&defaultUrlRestoreButton, 4, 2, 1, 1);
|
personalGrid->addWidget(&defaultUrlLabel, 5, 0, 1, 1);
|
||||||
personalGrid->addWidget(&fallbackUrlLabel, 5, 0, 1, 1);
|
personalGrid->addWidget(defaultUrlEdit, 5, 1, 1, 1);
|
||||||
personalGrid->addWidget(fallbackUrlEdit, 5, 1, 1, 1);
|
personalGrid->addWidget(&defaultUrlRestoreButton, 5, 2, 1, 1);
|
||||||
personalGrid->addWidget(&fallbackUrlRestoreButton, 5, 2, 1, 1);
|
personalGrid->addWidget(&fallbackUrlLabel, 6, 0, 1, 1);
|
||||||
personalGrid->addWidget(&urlLinkLabel, 6, 1, 1, 1);
|
personalGrid->addWidget(fallbackUrlEdit, 6, 1, 1, 1);
|
||||||
personalGrid->addWidget(&clearDownloadedPicsButton, 7, 0, 1, 3);
|
personalGrid->addWidget(&fallbackUrlRestoreButton, 6, 2, 1, 1);
|
||||||
|
personalGrid->addWidget(&urlLinkLabel, 7, 1, 1, 1);
|
||||||
|
personalGrid->addWidget(&clearDownloadedPicsButton, 8, 0, 1, 3);
|
||||||
|
|
||||||
urlLinkLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse);
|
urlLinkLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse);
|
||||||
urlLinkLabel.setOpenExternalLinks(true);
|
urlLinkLabel.setOpenExternalLinks(true);
|
||||||
|
@ -269,8 +283,9 @@ void GeneralSettingsPage::retranslateUi()
|
||||||
defaultUrlLabel.setText(tr("Primary download URL:"));
|
defaultUrlLabel.setText(tr("Primary download URL:"));
|
||||||
fallbackUrlLabel.setText(tr("Fallback download URL:"));
|
fallbackUrlLabel.setText(tr("Fallback download URL:"));
|
||||||
urlLinkLabel.setText(QString("<a href='%1'>%2</a>").arg(WIKI_CUSTOM_PIC_URL).arg(tr("How to set a custom picture url")));
|
urlLinkLabel.setText(QString("<a href='%1'>%2</a>").arg(WIKI_CUSTOM_PIC_URL).arg(tr("How to set a custom picture url")));
|
||||||
clearDownloadedPicsButton.setText(tr("Reset/Clear Downloaded Pictures"));
|
clearDownloadedPicsButton.setText(tr("Reset/clear downloaded pictures"));
|
||||||
updateNotificationCheckBox.setText(tr("Notify when new client features are available"));
|
updateReleaseChannelLabel.setText(tr("Update channel"));
|
||||||
|
updateNotificationCheckBox.setText(tr("Notify when a new version is available"));
|
||||||
defaultUrlRestoreButton.setText(tr("Reset"));
|
defaultUrlRestoreButton.setText(tr("Reset"));
|
||||||
fallbackUrlRestoreButton.setText(tr("Reset"));
|
fallbackUrlRestoreButton.setText(tr("Reset"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@ private:
|
||||||
QComboBox languageBox;
|
QComboBox languageBox;
|
||||||
QCheckBox picDownloadCheckBox;
|
QCheckBox picDownloadCheckBox;
|
||||||
QCheckBox updateNotificationCheckBox;
|
QCheckBox updateNotificationCheckBox;
|
||||||
|
QComboBox updateReleaseChannelBox;
|
||||||
QLabel languageLabel;
|
QLabel languageLabel;
|
||||||
QLabel pixmapCacheLabel;
|
QLabel pixmapCacheLabel;
|
||||||
QLabel deckPathLabel;
|
QLabel deckPathLabel;
|
||||||
|
@ -73,6 +74,7 @@ private:
|
||||||
QLabel defaultUrlLabel;
|
QLabel defaultUrlLabel;
|
||||||
QLabel fallbackUrlLabel;
|
QLabel fallbackUrlLabel;
|
||||||
QLabel urlLinkLabel;
|
QLabel urlLinkLabel;
|
||||||
|
QLabel updateReleaseChannelLabel;
|
||||||
QPushButton clearDownloadedPicsButton;
|
QPushButton clearDownloadedPicsButton;
|
||||||
QPushButton defaultUrlRestoreButton;
|
QPushButton defaultUrlRestoreButton;
|
||||||
QPushButton fallbackUrlRestoreButton;
|
QPushButton fallbackUrlRestoreButton;
|
||||||
|
|
|
@ -1,9 +1,3 @@
|
||||||
#define HUMAN_DOWNLOAD_URL "https://bintray.com/cockatrice/Cockatrice/Cockatrice/_latestVersion"
|
|
||||||
#define API_DOWNLOAD_BASE_URL "https://dl.bintray.com/cockatrice/Cockatrice/"
|
|
||||||
#define DATE_LENGTH 10
|
|
||||||
#define MAX_DATE_LENGTH 100
|
|
||||||
#define SHORT_SHA1_HASH_LENGTH 7
|
|
||||||
|
|
||||||
#include <QtNetwork>
|
#include <QtNetwork>
|
||||||
#include <QProgressDialog>
|
#include <QProgressDialog>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
|
@ -16,12 +10,15 @@
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
#include "dlg_update.h"
|
#include "dlg_update.h"
|
||||||
|
#include "releasechannel.h"
|
||||||
|
#include "settingscache.h"
|
||||||
#include "window_main.h"
|
#include "window_main.h"
|
||||||
|
|
||||||
DlgUpdate::DlgUpdate(QWidget *parent) : QDialog(parent) {
|
DlgUpdate::DlgUpdate(QWidget *parent) : QDialog(parent) {
|
||||||
|
|
||||||
//Handle layout
|
//Handle layout
|
||||||
text = new QLabel(this);
|
statusLabel = new QLabel(this);
|
||||||
|
descriptionLabel = new QLabel(tr("Current release channel:") + " " + tr(settingsCache->getUpdateReleaseChannel()->getName().toUtf8()), this);
|
||||||
progress = new QProgressBar(this);
|
progress = new QProgressBar(this);
|
||||||
|
|
||||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(this);
|
QDialogButtonBox *buttonBox = new QDialogButtonBox(this);
|
||||||
|
@ -38,7 +35,8 @@ DlgUpdate::DlgUpdate(QWidget *parent) : QDialog(parent) {
|
||||||
connect(ok, SIGNAL(clicked()), this, SLOT(closeDialog()));
|
connect(ok, SIGNAL(clicked()), this, SLOT(closeDialog()));
|
||||||
|
|
||||||
QVBoxLayout *parentLayout = new QVBoxLayout(this);
|
QVBoxLayout *parentLayout = new QVBoxLayout(this);
|
||||||
parentLayout->addWidget(text);
|
parentLayout->addWidget(descriptionLabel);
|
||||||
|
parentLayout->addWidget(statusLabel);
|
||||||
parentLayout->addWidget(progress);
|
parentLayout->addWidget(progress);
|
||||||
parentLayout->addWidget(buttonBox);
|
parentLayout->addWidget(buttonBox);
|
||||||
|
|
||||||
|
@ -47,11 +45,9 @@ DlgUpdate::DlgUpdate(QWidget *parent) : QDialog(parent) {
|
||||||
//Check for SSL (this probably isn't necessary)
|
//Check for SSL (this probably isn't necessary)
|
||||||
if (!QSslSocket::supportsSsl()) {
|
if (!QSslSocket::supportsSsl()) {
|
||||||
enableUpdateButton(false);
|
enableUpdateButton(false);
|
||||||
QMessageBox::critical(
|
QMessageBox::critical(this, tr("Error"),
|
||||||
this,
|
tr("Cockatrice was not built with SSL support, so you cannot download updates automatically! "
|
||||||
tr("Error"),
|
"Please visit the download page to update manually."));
|
||||||
tr("Cockatrice was not built with SSL support, so cannot download updates! "
|
|
||||||
"Please visit the download page and update manually."));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Initialize the checker and downloader class
|
//Initialize the checker and downloader class
|
||||||
|
@ -62,10 +58,10 @@ DlgUpdate::DlgUpdate(QWidget *parent) : QDialog(parent) {
|
||||||
connect(uDownloader, SIGNAL(error(QString)),
|
connect(uDownloader, SIGNAL(error(QString)),
|
||||||
this, SLOT(downloadError(QString)));
|
this, SLOT(downloadError(QString)));
|
||||||
|
|
||||||
uChecker = new UpdateChecker(this);
|
ReleaseChannel * channel = settingsCache->getUpdateReleaseChannel();
|
||||||
connect(uChecker, SIGNAL(finishedCheck(bool, bool, QVariantMap * )),
|
connect(channel, SIGNAL(finishedCheck(bool, bool, Release * )),
|
||||||
this, SLOT(finishedUpdateCheck(bool, bool, QVariantMap * )));
|
this, SLOT(finishedUpdateCheck(bool, bool, Release * )));
|
||||||
connect(uChecker, SIGNAL(error(QString)),
|
connect(channel, SIGNAL(error(QString)),
|
||||||
this, SLOT(updateCheckError(QString)));
|
this, SLOT(updateCheckError(QString)));
|
||||||
|
|
||||||
//Check for updates
|
//Check for updates
|
||||||
|
@ -79,8 +75,7 @@ void DlgUpdate::closeDialog() {
|
||||||
|
|
||||||
|
|
||||||
void DlgUpdate::gotoDownloadPage() {
|
void DlgUpdate::gotoDownloadPage() {
|
||||||
QUrl openUrl(HUMAN_DOWNLOAD_URL);
|
QDesktopServices::openUrl(settingsCache->getUpdateReleaseChannel()->getManualDownloadUrl());
|
||||||
QDesktopServices::openUrl(openUrl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DlgUpdate::downloadUpdate() {
|
void DlgUpdate::downloadUpdate() {
|
||||||
|
@ -94,12 +89,12 @@ void DlgUpdate::beginUpdateCheck() {
|
||||||
progress->setMinimum(0);
|
progress->setMinimum(0);
|
||||||
progress->setMaximum(0);
|
progress->setMaximum(0);
|
||||||
setLabel(tr("Checking for updates..."));
|
setLabel(tr("Checking for updates..."));
|
||||||
uChecker->check();
|
settingsCache->getUpdateReleaseChannel()->checkForUpdates();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DlgUpdate::finishedUpdateCheck(bool needToUpdate, bool isCompatible, QVariantMap *build) {
|
void DlgUpdate::finishedUpdateCheck(bool needToUpdate, bool isCompatible, Release *release) {
|
||||||
|
|
||||||
QString commitHash, commitDate;
|
QString publishDate, versionName;
|
||||||
|
|
||||||
//Update the UI to say we've finished
|
//Update the UI to say we've finished
|
||||||
progress->setMaximum(100);
|
progress->setMaximum(100);
|
||||||
|
@ -108,40 +103,34 @@ void DlgUpdate::finishedUpdateCheck(bool needToUpdate, bool isCompatible, QVaria
|
||||||
//If there are no available builds, then they can't auto update.
|
//If there are no available builds, then they can't auto update.
|
||||||
enableUpdateButton(isCompatible);
|
enableUpdateButton(isCompatible);
|
||||||
|
|
||||||
//If there is an update, save its URL and work out its name
|
|
||||||
if (isCompatible) {
|
|
||||||
QString endUrl = (*build)["path"].toString();
|
|
||||||
updateUrl = API_DOWNLOAD_BASE_URL + endUrl;
|
|
||||||
commitHash = (*build)["sha1"].toString().left(SHORT_SHA1_HASH_LENGTH);
|
|
||||||
commitDate = (*build)["created"].toString().remove(DATE_LENGTH, MAX_DATE_LENGTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Give the user the appropriate message
|
//Give the user the appropriate message
|
||||||
if (needToUpdate) {
|
if (!needToUpdate) {
|
||||||
if (isCompatible) {
|
|
||||||
|
|
||||||
QMessageBox::StandardButton reply;
|
|
||||||
reply = QMessageBox::question(this, "Update Available",
|
|
||||||
"A new build (commit " + commitHash + ") from " + commitDate +
|
|
||||||
" is available. Download?",
|
|
||||||
QMessageBox::Yes | QMessageBox::No);
|
|
||||||
if (reply == QMessageBox::Yes)
|
|
||||||
downloadUpdate();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QMessageBox::information(this, tr("Cockatrice Update"),
|
|
||||||
tr("Your version of Cockatrice is out of date, but there are no packages"
|
|
||||||
" available for your operating system. You may have to use a developer build or build from source"
|
|
||||||
" yourself. Please visit the download page."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//If there's no need to update, tell them that. However we still allow them to run the
|
//If there's no need to update, tell them that. However we still allow them to run the
|
||||||
//downloader themselves if there's a compatible build
|
//downloader themselves if there's a compatible build
|
||||||
QMessageBox::information(this, tr("Cockatrice Update"), tr("Your version of Cockatrice is up to date."));
|
QMessageBox::information(this, tr("Cockatrice Update"), tr("Your version of Cockatrice is up to date."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isCompatible) {
|
||||||
|
//If there is an update, save its URL and work out its name
|
||||||
|
updateUrl = release->getDownloadUrl();
|
||||||
|
publishDate = release->getPublishDate().toString(Qt::DefaultLocaleLongDate);
|
||||||
|
|
||||||
|
QMessageBox::StandardButton reply;
|
||||||
|
reply = QMessageBox::question(this, "Update Available",
|
||||||
|
tr("A new version is available:<br/>%1<br/>published on %2 ."
|
||||||
|
"<br/>More informations are available on the <a href=\"%3\">release changelog</a>"
|
||||||
|
"<br/>Do you want to update now?").arg(release->getName(), publishDate, release->getDescriptionUrl()),
|
||||||
|
QMessageBox::Yes | QMessageBox::No);
|
||||||
|
|
||||||
|
if (reply == QMessageBox::Yes)
|
||||||
|
downloadUpdate();
|
||||||
|
} else {
|
||||||
|
QMessageBox::information(this, tr("Cockatrice Update"),
|
||||||
|
tr("A new version is available:<br/>%1<br/>published on %2 ."
|
||||||
|
"<br/>More informations are available on the <a href=\"%3\">release changelog</a>"
|
||||||
|
"<br/>Unfortunately there are no packages available for your operating system. "
|
||||||
|
"You may have to use a developer build or build from source yourself. Please visit the download page.").arg(release->getName(), publishDate, release->getDescriptionUrl()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DlgUpdate::enableUpdateButton(bool enable) {
|
void DlgUpdate::enableUpdateButton(bool enable) {
|
||||||
|
@ -153,7 +142,7 @@ void DlgUpdate::enableOkButton(bool enable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DlgUpdate::setLabel(QString newText) {
|
void DlgUpdate::setLabel(QString newText) {
|
||||||
text->setText(newText);
|
statusLabel->setText(newText);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DlgUpdate::updateCheckError(QString errorString) {
|
void DlgUpdate::updateCheckError(QString errorString) {
|
||||||
|
@ -176,8 +165,8 @@ void DlgUpdate::downloadSuccessful(QUrl filepath) {
|
||||||
close();
|
close();
|
||||||
} else {
|
} else {
|
||||||
setLabel(tr("Error"));
|
setLabel(tr("Error"));
|
||||||
QMessageBox::critical(this, tr("Update Error"), "Unable to open the installer. You might be able to manually update"
|
QMessageBox::critical(this, tr("Update Error"),
|
||||||
" by closing Cockatrice and running the installer at " + filepath.toLocalFile() + ".");
|
tr("Unable to open the installer. You might be able to manually update by closing Cockatrice and running the installer at %1.").arg(filepath.toLocalFile()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
#include <QtNetwork>
|
#include <QtNetwork>
|
||||||
#include <QProgressDialog>
|
#include <QProgressDialog>
|
||||||
|
|
||||||
#include "update_checker.h"
|
|
||||||
#include "update_downloader.h"
|
#include "update_downloader.h"
|
||||||
|
class Release;
|
||||||
|
|
||||||
class DlgUpdate : public QDialog {
|
class DlgUpdate : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -13,7 +13,7 @@ public:
|
||||||
DlgUpdate(QWidget *parent);
|
DlgUpdate(QWidget *parent);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void finishedUpdateCheck(bool needToUpdate, bool isCompatible, QVariantMap *build);
|
void finishedUpdateCheck(bool needToUpdate, bool isCompatible, Release *release);
|
||||||
void gotoDownloadPage();
|
void gotoDownloadPage();
|
||||||
void downloadUpdate();
|
void downloadUpdate();
|
||||||
void updateCheckError(QString errorString);
|
void updateCheckError(QString errorString);
|
||||||
|
@ -27,11 +27,10 @@ private:
|
||||||
void enableOkButton(bool enable);
|
void enableOkButton(bool enable);
|
||||||
void beginUpdateCheck();
|
void beginUpdateCheck();
|
||||||
void setLabel(QString text);
|
void setLabel(QString text);
|
||||||
QLabel *text;
|
QLabel *statusLabel, *descriptionLabel;
|
||||||
QProgressBar *progress;
|
QProgressBar *progress;
|
||||||
QPushButton *manualDownload, *gotoDownload, *ok;
|
QPushButton *manualDownload, *gotoDownload, *ok;
|
||||||
QPushButton *cancel;
|
QPushButton *cancel;
|
||||||
UpdateChecker *uChecker;
|
|
||||||
UpdateDownloader *uDownloader;
|
UpdateDownloader *uDownloader;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
312
cockatrice/src/releasechannel.cpp
Normal file
312
cockatrice/src/releasechannel.cpp
Normal file
|
@ -0,0 +1,312 @@
|
||||||
|
#include "releasechannel.h"
|
||||||
|
#include "qt-json/json.h"
|
||||||
|
#include "version_string.h"
|
||||||
|
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#define STABLERELEASE_URL "https://api.github.com/repos/Cockatrice/Cockatrice/releases/latest"
|
||||||
|
#define STABLETAG_URL "https://api.github.com/repos/Cockatrice/Cockatrice/git/refs/tags/"
|
||||||
|
#define STABLEFILES_URL "https://api.bintray.com/packages/cockatrice/Cockatrice/Cockatrice/files"
|
||||||
|
#define STABLEDOWNLOAD_URL "https://dl.bintray.com/cockatrice/Cockatrice/"
|
||||||
|
#define STABLEMANUALDOWNLOAD_URL "https://bintray.com/cockatrice/Cockatrice/Cockatrice/_latestVersion#files"
|
||||||
|
|
||||||
|
#define DEVRELEASE_URL "https://api.github.com/repos/Cockatrice/Cockatrice/commits/master"
|
||||||
|
#define DEVFILES_URL "https://api.bintray.com/packages/cockatrice/Cockatrice/Cockatrice-git/files"
|
||||||
|
#define DEVDOWNLOAD_URL "https://dl.bintray.com/cockatrice/Cockatrice/"
|
||||||
|
#define DEVMANUALDOWNLOAD_URL "https://bintray.com/cockatrice/Cockatrice/Cockatrice-git/_latestVersion#files"
|
||||||
|
#define GIT_SHORT_HASH_LEN 7
|
||||||
|
|
||||||
|
int ReleaseChannel::sharedIndex = 0;
|
||||||
|
|
||||||
|
ReleaseChannel::ReleaseChannel()
|
||||||
|
: response(nullptr), lastRelease(nullptr)
|
||||||
|
{
|
||||||
|
index = sharedIndex++;
|
||||||
|
netMan = new QNetworkAccessManager(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseChannel::~ReleaseChannel()
|
||||||
|
{
|
||||||
|
netMan->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReleaseChannel::checkForUpdates()
|
||||||
|
{
|
||||||
|
QString releaseChannelUrl = getReleaseChannelUrl();
|
||||||
|
qDebug() << "Searching for updates on the channel: " << releaseChannelUrl;
|
||||||
|
response = netMan->get(QNetworkRequest(releaseChannelUrl));
|
||||||
|
connect(response, SIGNAL(finished()), this, SLOT(releaseListFinished()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(Q_OS_OSX)
|
||||||
|
bool ReleaseChannel::downloadMatchesCurrentOS(QVariantMap build)
|
||||||
|
{
|
||||||
|
return build["name"].toString().endsWith(".dmg");
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(Q_OS_WIN)
|
||||||
|
|
||||||
|
#include <QSysInfo>
|
||||||
|
|
||||||
|
bool ReleaseChannel::downloadMatchesCurrentOS(QVariantMap build)
|
||||||
|
{
|
||||||
|
QString wordSize = QSysInfo::buildAbi().split('-')[2];
|
||||||
|
QString arch;
|
||||||
|
if (wordSize == "llp64") {
|
||||||
|
arch = "win64";
|
||||||
|
} else if (wordSize == "ilp32") {
|
||||||
|
arch = "win32";
|
||||||
|
} else {
|
||||||
|
qWarning() << "Error checking for upgrade version: wordSize is" << wordSize;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fileName = build["name"].toString();
|
||||||
|
// Checking for .zip is a workaround for the May 6th 2016 release
|
||||||
|
auto zipName = arch + ".zip";
|
||||||
|
auto exeName = arch + ".exe";
|
||||||
|
return fileName.endsWith(exeName) || fileName.endsWith(zipName);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
bool ReleaseChannel::downloadMatchesCurrentOS(QVariantMap)
|
||||||
|
{
|
||||||
|
//If the OS doesn't fit one of the above #defines, then it will never match
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QString StableReleaseChannel::getManualDownloadUrl() const
|
||||||
|
{
|
||||||
|
return QString(STABLEMANUALDOWNLOAD_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString StableReleaseChannel::getName() const
|
||||||
|
{
|
||||||
|
return tr("Stable releases");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString StableReleaseChannel::getReleaseChannelUrl() const
|
||||||
|
{
|
||||||
|
return QString(STABLERELEASE_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StableReleaseChannel::releaseListFinished()
|
||||||
|
{
|
||||||
|
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
||||||
|
bool ok;
|
||||||
|
QString tmp = QString(reply->readAll());
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
QVariantMap resultMap = QtJson::Json::parse(tmp, ok).toMap();
|
||||||
|
if (!ok) {
|
||||||
|
qWarning() << "No reply received from the release update server:" << tmp;
|
||||||
|
emit error(tr("No reply received from the release update server."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(resultMap.contains("name") &&
|
||||||
|
resultMap.contains("html_url") &&
|
||||||
|
resultMap.contains("tag_name") &&
|
||||||
|
resultMap.contains("published_at"))) {
|
||||||
|
qWarning() << "Invalid received from the release update server:" << tmp;
|
||||||
|
emit error(tr("Invalid reply received from the release update server."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!lastRelease)
|
||||||
|
lastRelease = new Release;
|
||||||
|
|
||||||
|
lastRelease->setName(resultMap["name"].toString());
|
||||||
|
lastRelease->setDescriptionUrl(resultMap["html_url"].toString());
|
||||||
|
lastRelease->setPublishDate(resultMap["published_at"].toDate());
|
||||||
|
|
||||||
|
qDebug() << "Got reply from release server, size=" << tmp.size()
|
||||||
|
<< "name=" << lastRelease->getName()
|
||||||
|
<< "desc=" << lastRelease->getDescriptionUrl()
|
||||||
|
<< "date=" << lastRelease->getPublishDate();
|
||||||
|
|
||||||
|
QString url = QString(STABLETAG_URL) + resultMap["tag_name"].toString();
|
||||||
|
qDebug() << "Searching for a corresponding tag on the stable channel: " << url;
|
||||||
|
response = netMan->get(QNetworkRequest(url));
|
||||||
|
connect(response, SIGNAL(finished()), this, SLOT(tagListFinished()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void StableReleaseChannel::tagListFinished()
|
||||||
|
{
|
||||||
|
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
||||||
|
bool ok;
|
||||||
|
QString tmp = QString(reply->readAll());
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
QVariantMap resultMap = QtJson::Json::parse(tmp, ok).toMap();
|
||||||
|
if (!ok) {
|
||||||
|
qWarning() << "No reply received from the tag update server:" << tmp;
|
||||||
|
emit error(tr("No reply received from the tag update server."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(resultMap.contains("object") &&
|
||||||
|
resultMap["object"].toMap().contains("sha"))) {
|
||||||
|
qWarning() << "Invalid received from the tag update server:" << tmp;
|
||||||
|
emit error(tr("Invalid reply received from the tag update server."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastRelease->setCommitHash(resultMap["object"].toMap()["sha"].toString());
|
||||||
|
qDebug() << "Got reply from tag server, size=" << tmp.size()
|
||||||
|
<< "commit=" << lastRelease->getCommitHash();
|
||||||
|
|
||||||
|
qDebug() << "Searching for a corresponding file on the stable channel: " << QString(STABLEFILES_URL);
|
||||||
|
response = netMan->get(QNetworkRequest(QString(STABLEFILES_URL)));
|
||||||
|
connect(response, SIGNAL(finished()), this, SLOT(fileListFinished()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void StableReleaseChannel::fileListFinished()
|
||||||
|
{
|
||||||
|
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
||||||
|
bool ok;
|
||||||
|
QString tmp = QString(reply->readAll());
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
QVariantList resultList = QtJson::Json::parse(tmp, ok).toList();
|
||||||
|
if (!ok) {
|
||||||
|
qWarning() << "No reply received from the file update server:" << tmp;
|
||||||
|
emit error(tr("No reply received from the file update server."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
|
||||||
|
QString myHash = QString(VERSION_COMMIT);
|
||||||
|
qDebug() << "Current hash=" << myHash << "update hash=" << shortHash;
|
||||||
|
|
||||||
|
bool needToUpdate = (QString::compare(shortHash, myHash, Qt::CaseInsensitive) != 0);
|
||||||
|
bool compatibleVersion = false;
|
||||||
|
|
||||||
|
foreach(QVariant file, resultList)
|
||||||
|
{
|
||||||
|
QVariantMap map = file.toMap();
|
||||||
|
// TODO: map github version to bintray version
|
||||||
|
/*
|
||||||
|
if(!map.contains("version"))
|
||||||
|
continue;
|
||||||
|
if(!map["version"].toString().endsWith(shortHash))
|
||||||
|
continue;
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(!downloadMatchesCurrentOS(map))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
compatibleVersion = true;
|
||||||
|
|
||||||
|
QString url = QString(STABLEDOWNLOAD_URL) + map["path"].toString();
|
||||||
|
lastRelease->setDownloadUrl(url);
|
||||||
|
qDebug() << "Found compatible version url=" << url;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit finishedCheck(needToUpdate, compatibleVersion, lastRelease);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DevReleaseChannel::getManualDownloadUrl() const
|
||||||
|
{
|
||||||
|
return QString(DEVMANUALDOWNLOAD_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DevReleaseChannel::getName() const
|
||||||
|
{
|
||||||
|
return tr("Development snapshots");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DevReleaseChannel::getReleaseChannelUrl() const
|
||||||
|
{
|
||||||
|
return QString(DEVRELEASE_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevReleaseChannel::releaseListFinished()
|
||||||
|
{
|
||||||
|
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
||||||
|
bool ok;
|
||||||
|
QString tmp = QString(reply->readAll());
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
QVariantMap resultMap = QtJson::Json::parse(tmp, ok).toMap();
|
||||||
|
if (!ok) {
|
||||||
|
qWarning() << "No reply received from the release update server:" << tmp;
|
||||||
|
emit error(tr("No reply received from the release update server."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(resultMap.contains("commit") &&
|
||||||
|
resultMap.contains("html_url") &&
|
||||||
|
resultMap.contains("sha") &&
|
||||||
|
resultMap["commit"].toMap().contains("author") &&
|
||||||
|
resultMap["commit"].toMap()["author"].toMap().contains("date"))) {
|
||||||
|
qWarning() << "Invalid received from the release update server:" << tmp;
|
||||||
|
emit error(tr("Invalid reply received from the release update server."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!lastRelease)
|
||||||
|
lastRelease = new Release;
|
||||||
|
|
||||||
|
lastRelease->setName("Commit " + resultMap["sha"].toString());
|
||||||
|
lastRelease->setDescriptionUrl(resultMap["html_url"].toString());
|
||||||
|
lastRelease->setCommitHash(resultMap["sha"].toString());
|
||||||
|
lastRelease->setPublishDate(resultMap["commit"].toMap()["author"].toMap()["date"].toDate());
|
||||||
|
|
||||||
|
qDebug() << "Got reply from release server, size=" << tmp.size()
|
||||||
|
<< "name=" << lastRelease->getName()
|
||||||
|
<< "desc=" << lastRelease->getDescriptionUrl()
|
||||||
|
<< "commit=" << lastRelease->getCommitHash()
|
||||||
|
<< "date=" << lastRelease->getPublishDate();
|
||||||
|
|
||||||
|
qDebug() << "Searching for a corresponding file on the dev channel: " << QString(DEVFILES_URL);
|
||||||
|
response = netMan->get(QNetworkRequest(QString(DEVFILES_URL)));
|
||||||
|
connect(response, SIGNAL(finished()), this, SLOT(fileListFinished()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevReleaseChannel::fileListFinished()
|
||||||
|
{
|
||||||
|
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
||||||
|
bool ok;
|
||||||
|
QString tmp = QString(reply->readAll());
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
QVariantList resultList = QtJson::Json::parse(tmp, ok).toList();
|
||||||
|
if (!ok) {
|
||||||
|
qWarning() << "No reply received from the file update server:" << tmp;
|
||||||
|
emit error(tr("No reply received from the file update server."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
|
||||||
|
QString myHash = QString(VERSION_COMMIT);
|
||||||
|
qDebug() << "Current hash=" << myHash << "update hash=" << shortHash;
|
||||||
|
|
||||||
|
bool needToUpdate = (QString::compare(shortHash, myHash, Qt::CaseInsensitive) != 0);
|
||||||
|
bool compatibleVersion = false;
|
||||||
|
|
||||||
|
foreach(QVariant file, resultList)
|
||||||
|
{
|
||||||
|
QVariantMap map = file.toMap();
|
||||||
|
if(!map.contains("version"))
|
||||||
|
continue;
|
||||||
|
if(!map["version"].toString().endsWith(shortHash))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!downloadMatchesCurrentOS(map))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
compatibleVersion = true;
|
||||||
|
QString url = QString(DEVDOWNLOAD_URL) + map["path"].toString();
|
||||||
|
lastRelease->setDownloadUrl(url);
|
||||||
|
qDebug() << "Found compatible version url=" << url;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit finishedCheck(needToUpdate, compatibleVersion, lastRelease);
|
||||||
|
}
|
93
cockatrice/src/releasechannel.h
Normal file
93
cockatrice/src/releasechannel.h
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
#ifndef RELEASECHANNEL_H
|
||||||
|
#define RELEASECHANNEL_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QDate>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QVariantMap>
|
||||||
|
|
||||||
|
class QNetworkReply;
|
||||||
|
class QNetworkAccessManager;
|
||||||
|
|
||||||
|
class Release {
|
||||||
|
friend class StableReleaseChannel;
|
||||||
|
friend class DevReleaseChannel;
|
||||||
|
public:
|
||||||
|
Release() {};
|
||||||
|
~Release() {};
|
||||||
|
private:
|
||||||
|
QString name, descriptionUrl, downloadUrl, commitHash;
|
||||||
|
QDate publishDate;
|
||||||
|
protected:
|
||||||
|
void setName(QString _name) { name = _name; }
|
||||||
|
void setDescriptionUrl(QString _descriptionUrl) { descriptionUrl = _descriptionUrl; }
|
||||||
|
void setDownloadUrl(QString _downloadUrl) { downloadUrl = _downloadUrl; }
|
||||||
|
void setCommitHash(QString _commitHash) { commitHash = _commitHash; }
|
||||||
|
void setPublishDate(QDate _publishDate) { publishDate = _publishDate; }
|
||||||
|
public:
|
||||||
|
QString getName() const { return name; }
|
||||||
|
QString getDescriptionUrl() const { return descriptionUrl; }
|
||||||
|
QString getDownloadUrl() const { return downloadUrl; }
|
||||||
|
QString getCommitHash() const { return commitHash; }
|
||||||
|
QDate getPublishDate() const { return publishDate; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ReleaseChannel: public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
ReleaseChannel();
|
||||||
|
~ReleaseChannel();
|
||||||
|
protected:
|
||||||
|
// shared by all instances
|
||||||
|
static int sharedIndex;
|
||||||
|
int index;
|
||||||
|
QNetworkAccessManager *netMan;
|
||||||
|
QNetworkReply *response;
|
||||||
|
Release * lastRelease;
|
||||||
|
protected:
|
||||||
|
static bool downloadMatchesCurrentOS(QVariantMap build);
|
||||||
|
virtual QString getReleaseChannelUrl() const = 0;
|
||||||
|
public:
|
||||||
|
int getIndex() const { return index; }
|
||||||
|
Release * getLastRelease() { return lastRelease; }
|
||||||
|
virtual QString getManualDownloadUrl() const = 0;
|
||||||
|
virtual QString getName() const = 0;
|
||||||
|
void checkForUpdates();
|
||||||
|
signals:
|
||||||
|
void finishedCheck(bool needToUpdate, bool isCompatible, Release *release);
|
||||||
|
void error(QString errorString);
|
||||||
|
protected slots:
|
||||||
|
virtual void releaseListFinished() = 0;
|
||||||
|
virtual void fileListFinished() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class StableReleaseChannel: public ReleaseChannel {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
StableReleaseChannel() {};
|
||||||
|
~StableReleaseChannel() {};
|
||||||
|
virtual QString getManualDownloadUrl() const;
|
||||||
|
virtual QString getName() const;
|
||||||
|
protected:
|
||||||
|
virtual QString getReleaseChannelUrl() const;
|
||||||
|
protected slots:
|
||||||
|
virtual void releaseListFinished();
|
||||||
|
void tagListFinished();
|
||||||
|
virtual void fileListFinished();
|
||||||
|
};
|
||||||
|
|
||||||
|
class DevReleaseChannel: public ReleaseChannel {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
DevReleaseChannel() {};
|
||||||
|
~DevReleaseChannel() {};
|
||||||
|
virtual QString getManualDownloadUrl() const;
|
||||||
|
virtual QString getName() const;
|
||||||
|
protected:
|
||||||
|
virtual QString getReleaseChannelUrl() const;
|
||||||
|
protected slots:
|
||||||
|
virtual void releaseListFinished();
|
||||||
|
virtual void fileListFinished();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,4 +1,6 @@
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
|
#include "releasechannel.h"
|
||||||
|
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
@ -162,7 +164,13 @@ SettingsCache::SettingsCache()
|
||||||
if(!QFile(settingsPath+"global.ini").exists())
|
if(!QFile(settingsPath+"global.ini").exists())
|
||||||
translateLegacySettings();
|
translateLegacySettings();
|
||||||
|
|
||||||
|
// updates - don't reorder them or their index in the settings won't match
|
||||||
|
releaseChannels << new StableReleaseChannel()
|
||||||
|
<< new DevReleaseChannel();
|
||||||
|
|
||||||
notifyAboutUpdates = settings->value("personal/updatenotification", true).toBool();
|
notifyAboutUpdates = settings->value("personal/updatenotification", true).toBool();
|
||||||
|
updateReleaseChannel = settings->value("personal/updatereleasechannel", 0).toInt();
|
||||||
|
|
||||||
lang = settings->value("personal/lang").toString();
|
lang = settings->value("personal/lang").toString();
|
||||||
keepalive = settings->value("personal/keepalive", 5).toInt();
|
keepalive = settings->value("personal/keepalive", 5).toInt();
|
||||||
|
|
||||||
|
@ -642,4 +650,10 @@ void SettingsCache::setNotifyAboutUpdate(int _notifyaboutupdate)
|
||||||
{
|
{
|
||||||
notifyAboutUpdates = _notifyaboutupdate;
|
notifyAboutUpdates = _notifyaboutupdate;
|
||||||
settings->setValue("personal/updatenotification", notifyAboutUpdates);
|
settings->setValue("personal/updatenotification", notifyAboutUpdates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsCache::setUpdateReleaseChannel(int _updateReleaseChannel)
|
||||||
|
{
|
||||||
|
updateReleaseChannel = _updateReleaseChannel;
|
||||||
|
settings->setValue("personal/updatereleasechannel", updateReleaseChannel);
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#include "settings/gamefilterssettings.h"
|
#include "settings/gamefilterssettings.h"
|
||||||
#include "settings/layoutssettings.h"
|
#include "settings/layoutssettings.h"
|
||||||
|
|
||||||
|
class ReleaseChannel;
|
||||||
|
|
||||||
// the falbacks are used for cards without a muid
|
// the falbacks are used for cards without a muid
|
||||||
#define PIC_URL_DEFAULT "http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card"
|
#define PIC_URL_DEFAULT "http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card"
|
||||||
#define PIC_URL_FALLBACK "http://gatherer.wizards.com/Handlers/Image.ashx?name=!name!&type=card"
|
#define PIC_URL_FALLBACK "http://gatherer.wizards.com/Handlers/Image.ashx?name=!name!&type=card"
|
||||||
|
@ -58,6 +60,7 @@ private:
|
||||||
QString lang;
|
QString lang;
|
||||||
QString deckPath, replaysPath, picsPath, customPicsPath, cardDatabasePath, customCardDatabasePath, tokenDatabasePath, themeName;
|
QString deckPath, replaysPath, picsPath, customPicsPath, cardDatabasePath, customCardDatabasePath, tokenDatabasePath, themeName;
|
||||||
bool notifyAboutUpdates;
|
bool notifyAboutUpdates;
|
||||||
|
int updateReleaseChannel;
|
||||||
bool picDownload;
|
bool picDownload;
|
||||||
bool notificationsEnabled;
|
bool notificationsEnabled;
|
||||||
bool spectatorNotificationsEnabled;
|
bool spectatorNotificationsEnabled;
|
||||||
|
@ -110,6 +113,7 @@ private:
|
||||||
QString getSafeConfigPath(QString configEntry, QString defaultPath) const;
|
QString getSafeConfigPath(QString configEntry, QString defaultPath) const;
|
||||||
QString getSafeConfigFilePath(QString configEntry, QString defaultPath) const;
|
QString getSafeConfigFilePath(QString configEntry, QString defaultPath) const;
|
||||||
bool rememberGameSettings;
|
bool rememberGameSettings;
|
||||||
|
QList<ReleaseChannel*> releaseChannels;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SettingsCache();
|
SettingsCache();
|
||||||
|
@ -131,6 +135,8 @@ public:
|
||||||
bool getNotificationsEnabled() const { return notificationsEnabled; }
|
bool getNotificationsEnabled() const { return notificationsEnabled; }
|
||||||
bool getSpectatorNotificationsEnabled() const { return spectatorNotificationsEnabled; }
|
bool getSpectatorNotificationsEnabled() const { return spectatorNotificationsEnabled; }
|
||||||
bool getNotifyAboutUpdates() const { return notifyAboutUpdates; }
|
bool getNotifyAboutUpdates() const { return notifyAboutUpdates; }
|
||||||
|
ReleaseChannel * getUpdateReleaseChannel() const { return releaseChannels.at(updateReleaseChannel); }
|
||||||
|
QList<ReleaseChannel*> getUpdateReleaseChannels() const { return releaseChannels; }
|
||||||
|
|
||||||
bool getDoubleClickToPlay() const { return doubleClickToPlay; }
|
bool getDoubleClickToPlay() const { return doubleClickToPlay; }
|
||||||
bool getPlayToStack() const { return playToStack; }
|
bool getPlayToStack() const { return playToStack; }
|
||||||
|
@ -249,6 +255,7 @@ public slots:
|
||||||
void setSpectatorsCanSeeEverything(const bool _spectatorsCanSeeEverything);
|
void setSpectatorsCanSeeEverything(const bool _spectatorsCanSeeEverything);
|
||||||
void setRememberGameSettings(const bool _rememberGameSettings);
|
void setRememberGameSettings(const bool _rememberGameSettings);
|
||||||
void setNotifyAboutUpdate(int _notifyaboutupdate);
|
void setNotifyAboutUpdate(int _notifyaboutupdate);
|
||||||
|
void setUpdateReleaseChannel(int _updateReleaseChannel);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SettingsCache *settingsCache;
|
extern SettingsCache *settingsCache;
|
||||||
|
|
|
@ -1,124 +0,0 @@
|
||||||
#include <algorithm>
|
|
||||||
#include <QMessageBox>
|
|
||||||
|
|
||||||
#include "update_checker.h"
|
|
||||||
#include "version_string.h"
|
|
||||||
#include "qt-json/json.h"
|
|
||||||
|
|
||||||
#define LATEST_FILES_URL "https://api.bintray.com/packages/cockatrice/Cockatrice/Cockatrice/files"
|
|
||||||
|
|
||||||
UpdateChecker::UpdateChecker(QObject *parent) : QObject(parent)
|
|
||||||
{
|
|
||||||
//Parse the commit date. We'll use this to check for new versions
|
|
||||||
//We know the format because it's based on `git log` which is documented here:
|
|
||||||
// https://git-scm.com/docs/git-log#_commit_formatting
|
|
||||||
buildDate = QDate::fromString(VERSION_DATE, "yyyy-MM-dd");
|
|
||||||
latestFilesUrl = QUrl(LATEST_FILES_URL);
|
|
||||||
response = NULL;
|
|
||||||
netMan = new QNetworkAccessManager(this);
|
|
||||||
build = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateChecker::~UpdateChecker()
|
|
||||||
{
|
|
||||||
delete build;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateChecker::check()
|
|
||||||
{
|
|
||||||
response = netMan->get(QNetworkRequest(latestFilesUrl));
|
|
||||||
connect(response, SIGNAL(finished()),
|
|
||||||
this, SLOT(fileListFinished()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(Q_OS_OSX)
|
|
||||||
bool UpdateChecker::downloadMatchesCurrentOS(QVariant build)
|
|
||||||
{
|
|
||||||
return build
|
|
||||||
.toMap()["name"]
|
|
||||||
.toString()
|
|
||||||
.endsWith(".dmg");
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(Q_OS_WIN)
|
|
||||||
bool UpdateChecker::downloadMatchesCurrentOS(QVariant build)
|
|
||||||
{
|
|
||||||
QString wordSize = QSysInfo::buildAbi().split('-')[2];
|
|
||||||
QString arch;
|
|
||||||
if (wordSize == "llp64") {
|
|
||||||
arch = "win64";
|
|
||||||
} else if (wordSize == "ilp32") {
|
|
||||||
arch = "win32";
|
|
||||||
} else {
|
|
||||||
qWarning() << "Error checking for upgrade version: wordSize is" << wordSize;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto fileName = build
|
|
||||||
.toMap()["name"]
|
|
||||||
.toString();
|
|
||||||
// Checking for .zip is a workaround for the May 6th 2016 release
|
|
||||||
auto zipName = arch + ".zip";
|
|
||||||
auto exeName = arch + ".exe";
|
|
||||||
return fileName.endsWith(exeName) || fileName.endsWith(zipName);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
|
|
||||||
bool UpdateChecker::downloadMatchesCurrentOS(QVariant)
|
|
||||||
{
|
|
||||||
//If the OS doesn't fit one of the above #defines, then it will never match
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QDate UpdateChecker::dateFromBuild(QVariant build)
|
|
||||||
{
|
|
||||||
QString formatString = "yyyy-MM-dd";
|
|
||||||
QString dateString = build.toMap()["created"].toString();
|
|
||||||
dateString = dateString.remove(formatString.length(), dateString.length());
|
|
||||||
|
|
||||||
return QDate::fromString(dateString, formatString);
|
|
||||||
}
|
|
||||||
|
|
||||||
QDate UpdateChecker::findOldestBuild(QVariantList allBuilds)
|
|
||||||
{
|
|
||||||
//Map the build array into an array of dates
|
|
||||||
std::vector<QDate> dateArray(allBuilds.size());
|
|
||||||
std::transform(allBuilds.begin(), allBuilds.end(), dateArray.begin(), dateFromBuild);
|
|
||||||
|
|
||||||
//Return the first date
|
|
||||||
return *std::min_element(dateArray.begin(), dateArray.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantMap *UpdateChecker::findCompatibleBuild(QVariantList allBuilds)
|
|
||||||
{
|
|
||||||
|
|
||||||
QVariantList::iterator result = std::find_if(allBuilds.begin(), allBuilds.end(), downloadMatchesCurrentOS);
|
|
||||||
|
|
||||||
//If there is no compatible version, return NULL
|
|
||||||
if (result == allBuilds.end())
|
|
||||||
return NULL;
|
|
||||||
else {
|
|
||||||
QVariantMap *ret = new QVariantMap;
|
|
||||||
*ret = (*result).toMap();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateChecker::fileListFinished()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
QVariantList builds = QtJson::Json::parse(response->readAll()).toList();
|
|
||||||
build = findCompatibleBuild(builds);
|
|
||||||
QDate bintrayBuildDate = findOldestBuild(builds);
|
|
||||||
|
|
||||||
bool needToUpdate = bintrayBuildDate > buildDate;
|
|
||||||
bool compatibleVersion = build != NULL;
|
|
||||||
|
|
||||||
emit finishedCheck(needToUpdate, compatibleVersion, build);
|
|
||||||
}
|
|
||||||
catch (const std::exception &exc) {
|
|
||||||
emit error(exc.what());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
//
|
|
||||||
// Created by miguel on 28/12/15.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef COCKATRICE_UPDATECHECKER_H
|
|
||||||
#define COCKATRICE_UPDATECHECKER_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QUrl>
|
|
||||||
#include <QDate>
|
|
||||||
#include <QtNetwork>
|
|
||||||
|
|
||||||
class UpdateChecker : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
UpdateChecker(QObject *parent);
|
|
||||||
~UpdateChecker();
|
|
||||||
void check();
|
|
||||||
signals:
|
|
||||||
void finishedCheck(bool needToUpdate, bool isCompatible, QVariantMap *build);
|
|
||||||
void error(QString errorString);
|
|
||||||
private:
|
|
||||||
static QVariantMap *findCompatibleBuild();
|
|
||||||
static QDate findOldestBuild(QVariantList allBuilds);
|
|
||||||
static QDate dateFromBuild(QVariant build);
|
|
||||||
static QVariantMap *findCompatibleBuild(QVariantList allBuilds);
|
|
||||||
static bool downloadMatchesCurrentOS(QVariant build);
|
|
||||||
QVariantMap *build;
|
|
||||||
QUrl latestFilesUrl;
|
|
||||||
QDate buildDate;
|
|
||||||
QNetworkAccessManager *netMan;
|
|
||||||
QNetworkReply *response;
|
|
||||||
private slots:
|
|
||||||
void fileListFinished();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //COCKATRICE_UPDATECHECKER_H
|
|
|
@ -13,7 +13,6 @@ void UpdateDownloader::beginDownload(QUrl downloadUrl) {
|
||||||
|
|
||||||
response = netMan->get(QNetworkRequest(downloadUrl));
|
response = netMan->get(QNetworkRequest(downloadUrl));
|
||||||
connect(response, SIGNAL(finished()), this, SLOT(fileFinished()));
|
connect(response, SIGNAL(finished()), this, SLOT(fileFinished()));
|
||||||
connect(response, SIGNAL(readyRead()), this, SLOT(fileReadyRead()));
|
|
||||||
connect(response, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgress(qint64, qint64)));
|
connect(response, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgress(qint64, qint64)));
|
||||||
connect(response, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError)));
|
connect(response, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,6 @@
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
#include "tab_game.h"
|
#include "tab_game.h"
|
||||||
#include "version_string.h"
|
#include "version_string.h"
|
||||||
#include "update_checker.h"
|
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
#include "window_sets.h"
|
#include "window_sets.h"
|
||||||
#include "dlg_edit_tokens.h"
|
#include "dlg_edit_tokens.h"
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
|
|
||||||
#include "abstractclient.h"
|
#include "abstractclient.h"
|
||||||
#include "pb/response.pb.h"
|
#include "pb/response.pb.h"
|
||||||
#include "update_checker.h"
|
|
||||||
|
|
||||||
class TabSupervisor;
|
class TabSupervisor;
|
||||||
class RemoteClient;
|
class RemoteClient;
|
||||||
|
|
|
@ -23,7 +23,9 @@ SET(oracle_SOURCES
|
||||||
../cockatrice/src/settings/layoutssettings.cpp
|
../cockatrice/src/settings/layoutssettings.cpp
|
||||||
../cockatrice/src/thememanager.cpp
|
../cockatrice/src/thememanager.cpp
|
||||||
../cockatrice/src/qt-json/json.cpp
|
../cockatrice/src/qt-json/json.cpp
|
||||||
)
|
../cockatrice/src/releasechannel.cpp
|
||||||
|
${VERSION_STRING_CPP}
|
||||||
|
)
|
||||||
|
|
||||||
set(oracle_RESOURCES oracle.qrc)
|
set(oracle_RESOURCES oracle.qrc)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue