Client update implementation
This commit is contained in:
parent
36c3536e0c
commit
66fda086c3
10 changed files with 503 additions and 4 deletions
|
@ -2,8 +2,10 @@ set(VERSION_STRING_CPP "${PROJECT_BINARY_DIR}/version_string.cpp")
|
|||
set(VERSION_STRING_H "${PROJECT_BINARY_DIR}/version_string.h")
|
||||
INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR})
|
||||
|
||||
set( hstring "extern const char *VERSION_STRING\;\n" )
|
||||
set( cppstring "const char * VERSION_STRING = \"${PROJECT_VERSION_FRIENDLY}\"\;\n")
|
||||
set( hstring "extern const char *VERSION_STRING\;
|
||||
extern const char *VERSION_DATE\;\n" )
|
||||
set( cppstring "const char *VERSION_STRING = \"${PROJECT_VERSION_FRIENDLY}\"\;
|
||||
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.h.txt ${hstring} )
|
||||
|
|
|
@ -16,6 +16,7 @@ SET(cockatrice_SOURCES
|
|||
src/dlg_edit_tokens.cpp
|
||||
src/dlg_edit_user.cpp
|
||||
src/dlg_register.cpp
|
||||
src/dlg_update.cpp
|
||||
src/abstractclient.cpp
|
||||
src/remoteclient.cpp
|
||||
src/main.cpp
|
||||
|
@ -107,6 +108,8 @@ SET(cockatrice_SOURCES
|
|||
src/settings/messagesettings.cpp
|
||||
src/settings/gamefilterssettings.cpp
|
||||
src/settings/layoutssettings.cpp
|
||||
src/update_checker.cpp
|
||||
src/update_downloader.cpp
|
||||
${VERSION_STRING_CPP}
|
||||
)
|
||||
|
||||
|
|
179
cockatrice/src/dlg_update.cpp
Normal file
179
cockatrice/src/dlg_update.cpp
Normal file
|
@ -0,0 +1,179 @@
|
|||
#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 <QProgressDialog>
|
||||
#include <QDesktopServices>
|
||||
#include <QMessageBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
#include <QLabel>
|
||||
#include <QProgressBar>
|
||||
#include <QApplication>
|
||||
|
||||
#include "dlg_update.h"
|
||||
#include "window_main.h"
|
||||
|
||||
DlgUpdate::DlgUpdate(QWidget *parent) : QDialog(parent) {
|
||||
|
||||
//Handle layout
|
||||
text = new QLabel(this);
|
||||
progress = new QProgressBar(this);
|
||||
|
||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(this);
|
||||
ok = new QPushButton("Ok", this);
|
||||
manualDownload = new QPushButton("Update Anyway", this);
|
||||
enableUpdateButton(false); //Unless we know there's an update available, you can't install
|
||||
gotoDownload = new QPushButton("Open Download Page", this);
|
||||
buttonBox->addButton(manualDownload, QDialogButtonBox::ActionRole);
|
||||
buttonBox->addButton(gotoDownload, QDialogButtonBox::ActionRole);
|
||||
buttonBox->addButton(ok, QDialogButtonBox::AcceptRole);
|
||||
|
||||
connect(gotoDownload, SIGNAL(clicked()), this, SLOT(gotoDownloadPage()));
|
||||
connect(manualDownload, SIGNAL(clicked()), this, SLOT(downloadUpdate()));
|
||||
connect(ok, SIGNAL(clicked()), this, SLOT(closeDialog()));
|
||||
|
||||
QVBoxLayout *parentLayout = new QVBoxLayout(this);
|
||||
parentLayout->addWidget(text);
|
||||
parentLayout->addWidget(progress);
|
||||
parentLayout->addWidget(buttonBox);
|
||||
|
||||
setLayout(parentLayout);
|
||||
|
||||
//Check for SSL (this probably isn't necessary)
|
||||
if (!QSslSocket::supportsSsl()) {
|
||||
enableUpdateButton(false);
|
||||
QMessageBox::critical(
|
||||
this,
|
||||
tr("Error"),
|
||||
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
|
||||
uDownloader = new UpdateDownloader(this);
|
||||
connect(uDownloader, SIGNAL(downloadSuccessful(QUrl)), this, SLOT(downloadSuccessful(QUrl)));
|
||||
connect(uDownloader, SIGNAL(progressMade(qint64, qint64)),
|
||||
this, SLOT(downloadProgressMade(qint64, qint64)));
|
||||
connect(uDownloader, SIGNAL(error(QString)),
|
||||
this, SLOT(downloadError(QString)));
|
||||
|
||||
uChecker = new UpdateChecker(this);
|
||||
connect(uChecker, SIGNAL(finishedCheck(bool, bool, QVariantMap * )),
|
||||
this, SLOT(finishedUpdateCheck(bool, bool, QVariantMap * )));
|
||||
connect(uChecker, SIGNAL(error(QString)),
|
||||
this, SLOT(updateCheckError(QString)));
|
||||
|
||||
//Check for updates
|
||||
beginUpdateCheck();
|
||||
}
|
||||
|
||||
|
||||
void DlgUpdate::closeDialog() {
|
||||
accept();
|
||||
}
|
||||
|
||||
|
||||
void DlgUpdate::gotoDownloadPage() {
|
||||
QUrl openUrl(HUMAN_DOWNLOAD_URL);
|
||||
QDesktopServices::openUrl(openUrl);
|
||||
}
|
||||
|
||||
void DlgUpdate::downloadUpdate() {
|
||||
setLabel("Downloading update...");
|
||||
uDownloader->beginDownload(updateUrl);
|
||||
}
|
||||
|
||||
void DlgUpdate::beginUpdateCheck() {
|
||||
progress->setMinimum(0);
|
||||
progress->setMaximum(0);
|
||||
setLabel("Checking for updates...");
|
||||
uChecker->check();
|
||||
}
|
||||
|
||||
void DlgUpdate::finishedUpdateCheck(bool needToUpdate, bool isCompatible, QVariantMap *build) {
|
||||
|
||||
QString commitHash, commitDate;
|
||||
|
||||
//Update the UI to say we've finished
|
||||
progress->setMaximum(100);
|
||||
setLabel("Finished checking for updates.");
|
||||
|
||||
//If there are no available builds, then they can't auto update.
|
||||
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
|
||||
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, "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
|
||||
//downloader themselves if there's a compatible build
|
||||
QMessageBox::information(this, tr("Cockatrice Update"), tr("Your version of Cockatrice is up to date."));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DlgUpdate::enableUpdateButton(bool enable) {
|
||||
manualDownload->setEnabled(enable);
|
||||
}
|
||||
|
||||
void DlgUpdate::setLabel(QString newText) {
|
||||
text->setText(newText);
|
||||
}
|
||||
|
||||
void DlgUpdate::updateCheckError(QString errorString) {
|
||||
setLabel("Error");
|
||||
QMessageBox::critical(this, tr("Update Error"), "An error occurred while checking for updates: " + errorString);
|
||||
}
|
||||
|
||||
void DlgUpdate::downloadError(QString errorString) {
|
||||
setLabel("Error");
|
||||
QMessageBox::critical(this, tr("Update Error"), "An error occurred while downloading an update: " + errorString);
|
||||
}
|
||||
|
||||
void DlgUpdate::downloadSuccessful(QUrl filepath) {
|
||||
setLabel("Installing...");
|
||||
//Try to open the installer. If it opens, quit Cockatrice
|
||||
if (QDesktopServices::openUrl(filepath))
|
||||
{
|
||||
QMetaObject::invokeMethod((MainWindow*) parent(), "close", Qt::QueuedConnection);
|
||||
close();
|
||||
} else {
|
||||
setLabel("Error");
|
||||
QMessageBox::critical(this, tr("Update Error"), "Unable to open the installer. You might be able to manually update"
|
||||
" by closing Cockatrice and running the installer at " + filepath.toLocalFile() + ".");
|
||||
}
|
||||
}
|
||||
|
||||
void DlgUpdate::downloadProgressMade(qint64 bytesRead, qint64 totalBytes) {
|
||||
progress->setMaximum(totalBytes);
|
||||
progress->setValue(bytesRead);
|
||||
}
|
37
cockatrice/src/dlg_update.h
Normal file
37
cockatrice/src/dlg_update.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef DLG_UPDATE_H
|
||||
#define DLG_UPDATE_H
|
||||
|
||||
#include <QtNetwork>
|
||||
#include <QProgressDialog>
|
||||
|
||||
#include "update_checker.h"
|
||||
#include "update_downloader.h"
|
||||
|
||||
class DlgUpdate : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
DlgUpdate(QWidget *parent);
|
||||
|
||||
private slots:
|
||||
void finishedUpdateCheck(bool needToUpdate, bool isCompatible, QVariantMap *build);
|
||||
void gotoDownloadPage();
|
||||
void downloadUpdate();
|
||||
void updateCheckError(QString errorString);
|
||||
void downloadSuccessful(QUrl filepath);
|
||||
void downloadProgressMade(qint64 bytesRead, qint64 totalBytes);
|
||||
void downloadError(QString errorString);
|
||||
void closeDialog();
|
||||
private:
|
||||
QUrl updateUrl;
|
||||
void enableUpdateButton(bool enable);
|
||||
void beginUpdateCheck();
|
||||
void setLabel(QString text);
|
||||
QLabel *text;
|
||||
QProgressBar *progress;
|
||||
QPushButton *manualDownload, *gotoDownload, *ok;
|
||||
QPushButton *cancel;
|
||||
UpdateChecker *uChecker;
|
||||
UpdateDownloader *uDownloader;
|
||||
};
|
||||
|
||||
#endif
|
121
cockatrice/src/update_checker.cpp
Normal file
121
cockatrice/src/update_checker.cpp
Normal file
|
@ -0,0 +1,121 @@
|
|||
//
|
||||
// Created by miguel on 28/12/15.
|
||||
//
|
||||
|
||||
#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()
|
||||
.contains("osx");
|
||||
}
|
||||
#elif defined(Q_OS_WIN)
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
bool UpdateChecker::downloadMatchesCurrentOS(QVariant build)
|
||||
{
|
||||
return build
|
||||
.toMap()["name"]
|
||||
.toString()
|
||||
.contains("qt5.exe");
|
||||
}
|
||||
#else
|
||||
bool UpdateChecker::downloadMatchesCurrentOS(QVariant build)
|
||||
{
|
||||
return build
|
||||
.toMap()["name"]
|
||||
.toString()
|
||||
.contains("qt4.exe");
|
||||
}
|
||||
#endif
|
||||
#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()["date"].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());
|
||||
}
|
||||
}
|
38
cockatrice/src/update_checker.h
Normal file
38
cockatrice/src/update_checker.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// 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
|
66
cockatrice/src/update_downloader.cpp
Normal file
66
cockatrice/src/update_downloader.cpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include <QUrl>
|
||||
|
||||
#include "update_downloader.h"
|
||||
|
||||
UpdateDownloader::UpdateDownloader(QObject *parent) : QObject(parent) {
|
||||
netMan = new QNetworkAccessManager(this);
|
||||
}
|
||||
|
||||
void UpdateDownloader::beginDownload(QUrl downloadUrl) {
|
||||
|
||||
//Save the original URL because we need it for the filename
|
||||
if (originalUrl.isEmpty())
|
||||
originalUrl = downloadUrl;
|
||||
|
||||
response = netMan->get(QNetworkRequest(downloadUrl));
|
||||
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(error(QNetworkReply::NetworkError)),
|
||||
this, SLOT(downloadError(QNetworkReply::NetworkError)));
|
||||
}
|
||||
|
||||
void UpdateDownloader::downloadError(QNetworkReply::NetworkError) {
|
||||
emit error(response->errorString().toUtf8());
|
||||
}
|
||||
|
||||
void UpdateDownloader::fileFinished() {
|
||||
//If we finished but there's a redirect, follow it
|
||||
QVariant redirect = response->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
||||
if (!redirect.isNull())
|
||||
{
|
||||
beginDownload(redirect.toUrl());
|
||||
return;
|
||||
}
|
||||
|
||||
//Handle any errors we had
|
||||
if (response->error())
|
||||
{
|
||||
emit error(response->errorString());
|
||||
return;
|
||||
}
|
||||
|
||||
//Work out the file name of the download
|
||||
QString fileName = QDir::temp().path() + QDir::separator() + originalUrl.toString().section('/', -1);
|
||||
|
||||
//Save the build in a temporary directory
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
emit error("Could not open the file for reading.");
|
||||
return;
|
||||
}
|
||||
|
||||
file.write(response->readAll());
|
||||
file.close();
|
||||
|
||||
//Emit the success signal with a URL to the download file
|
||||
emit downloadSuccessful(QUrl::fromLocalFile(fileName));
|
||||
}
|
||||
|
||||
void UpdateDownloader::downloadProgress(qint64 bytesRead, qint64 totalBytes) {
|
||||
emit progressMade(bytesRead, totalBytes);
|
||||
}
|
||||
|
33
cockatrice/src/update_downloader.h
Normal file
33
cockatrice/src/update_downloader.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// Created by miguel on 28/12/15.
|
||||
//
|
||||
|
||||
#ifndef COCKATRICE_UPDATEDOWNLOADER_H
|
||||
#define COCKATRICE_UPDATEDOWNLOADER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
#include <QDate>
|
||||
#include <QtNetwork>
|
||||
|
||||
class UpdateDownloader : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
UpdateDownloader(QObject *parent);
|
||||
void beginDownload(QUrl url);
|
||||
signals:
|
||||
void downloadSuccessful(QUrl filepath);
|
||||
void progressMade(qint64 bytesRead, qint64 totalBytes);
|
||||
void error(QString errorString);
|
||||
private:
|
||||
QUrl originalUrl;
|
||||
QNetworkAccessManager *netMan;
|
||||
QNetworkReply *response;
|
||||
private slots:
|
||||
void fileFinished();
|
||||
void downloadProgress(qint64 bytesRead, qint64 totalBytes);
|
||||
void downloadError(QNetworkReply::NetworkError);
|
||||
};
|
||||
|
||||
|
||||
#endif //COCKATRICE_UPDATEDOWNLOADER_H
|
|
@ -30,6 +30,7 @@
|
|||
#include <QDateTime>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QApplication>
|
||||
#include <QtNetwork>
|
||||
|
||||
#if QT_VERSION < 0x050000
|
||||
#include <QtGui/qtextdocument.h> // for Qt::escape()
|
||||
|
@ -40,6 +41,7 @@
|
|||
#include "dlg_connect.h"
|
||||
#include "dlg_register.h"
|
||||
#include "dlg_settings.h"
|
||||
#include "dlg_update.h"
|
||||
#include "tab_supervisor.h"
|
||||
#include "remoteclient.h"
|
||||
#include "localserver.h"
|
||||
|
@ -48,6 +50,7 @@
|
|||
#include "settingscache.h"
|
||||
#include "tab_game.h"
|
||||
#include "version_string.h"
|
||||
#include "update_checker.h"
|
||||
|
||||
#include "pb/game_replay.pb.h"
|
||||
#include "pb/room_commands.pb.h"
|
||||
|
@ -62,6 +65,8 @@
|
|||
#define GITHUB_TROUBLESHOOTING_URL "https://github.com/Cockatrice/Cockatrice/wiki/Troubleshooting"
|
||||
#define GITHUB_FAQ_URL "https://github.com/Cockatrice/Cockatrice/wiki/Frequently-Asked-Questions"
|
||||
|
||||
#define DOWNLOAD_URL "https://dl.bintray.com/cockatrice/Cockatrice/"
|
||||
|
||||
const QString MainWindow::appName = "Cockatrice";
|
||||
|
||||
void MainWindow::updateTabMenu(const QList<QMenu *> &newMenuList)
|
||||
|
@ -288,6 +293,12 @@ void MainWindow::actAbout()
|
|||
));
|
||||
}
|
||||
|
||||
void MainWindow::actUpdate()
|
||||
{
|
||||
DlgUpdate dlg(this);
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
void MainWindow::serverTimeout()
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Server timeout"));
|
||||
|
@ -495,6 +506,7 @@ void MainWindow::retranslateUi()
|
|||
#endif
|
||||
|
||||
aAbout->setText(tr("&About Cockatrice"));
|
||||
aUpdate->setText(tr("&Update Cockatrice"));
|
||||
helpMenu->setTitle(tr("&Help"));
|
||||
aCheckCardUpdates->setText(tr("Check for card updates..."));
|
||||
tabSupervisor->retranslateUi();
|
||||
|
@ -525,6 +537,8 @@ void MainWindow::createActions()
|
|||
|
||||
aAbout = new QAction(this);
|
||||
connect(aAbout, SIGNAL(triggered()), this, SLOT(actAbout()));
|
||||
aUpdate = new QAction(this);
|
||||
connect(aUpdate, SIGNAL(triggered()), this, SLOT(actUpdate()));
|
||||
|
||||
aCheckCardUpdates = new QAction(this);
|
||||
connect(aCheckCardUpdates, SIGNAL(triggered()), this, SLOT(actCheckCardUpdates()));
|
||||
|
@ -566,6 +580,7 @@ void MainWindow::createMenus()
|
|||
|
||||
helpMenu = menuBar()->addMenu(QString());
|
||||
helpMenu->addAction(aAbout);
|
||||
helpMenu->addAction(aUpdate);
|
||||
}
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
|
|
|
@ -25,8 +25,11 @@
|
|||
#include <QSystemTrayIcon>
|
||||
#include <QProcess>
|
||||
#include <QMessageBox>
|
||||
#include <QtNetwork>
|
||||
|
||||
#include "abstractclient.h"
|
||||
#include "pb/response.pb.h"
|
||||
#include "update_checker.h"
|
||||
|
||||
class TabSupervisor;
|
||||
class RemoteClient;
|
||||
|
@ -66,6 +69,7 @@ private slots:
|
|||
void actExit();
|
||||
|
||||
void actAbout();
|
||||
void actUpdate();
|
||||
|
||||
void iconActivated(QSystemTrayIcon::ActivationReason reason);
|
||||
|
||||
|
@ -90,7 +94,7 @@ private:
|
|||
QList<QMenu *> tabMenus;
|
||||
QMenu *cockatriceMenu, *helpMenu;
|
||||
QAction *aConnect, *aDisconnect, *aSinglePlayer, *aWatchReplay, *aDeckEditor, *aFullScreen, *aSettings, *aExit,
|
||||
*aAbout, *aCheckCardUpdates, *aRegister;
|
||||
*aAbout, *aCheckCardUpdates, *aRegister, *aUpdate;
|
||||
TabSupervisor *tabSupervisor;
|
||||
|
||||
QMenu *trayIconMenu;
|
||||
|
@ -105,6 +109,7 @@ private:
|
|||
|
||||
QMessageBox serverShutdownMessageBox;
|
||||
QProcess * cardUpdateProcess;
|
||||
|
||||
public:
|
||||
MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
|
Loading…
Reference in a new issue