mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
feat(ui): add update notification enabled with -DUPDATE_CHECK
Fix #5335
This commit is contained in:
parent
52853485eb
commit
6c9d7b59c1
|
@ -180,7 +180,7 @@ build_qtox() {
|
||||||
rm -rf "$BUILDDIR"
|
rm -rf "$BUILDDIR"
|
||||||
|
|
||||||
echo '*** BUILDING "FULL" VERSION ***'
|
echo '*** BUILDING "FULL" VERSION ***'
|
||||||
cmake -H. -B"$BUILDDIR"
|
cmake -H. -B"$BUILDDIR" -DUPDATE_CHECK=ON
|
||||||
bdir
|
bdir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ option(PLATFORM_EXTENSIONS "Enable platform specific extensions, requires extra
|
||||||
option(USE_FILTERAUDIO "Enable the echo canceling backend" ON)
|
option(USE_FILTERAUDIO "Enable the echo canceling backend" ON)
|
||||||
# AUTOUPDATE is currently broken and thus disabled
|
# AUTOUPDATE is currently broken and thus disabled
|
||||||
option(AUTOUPDATE "Enable the auto updater" OFF)
|
option(AUTOUPDATE "Enable the auto updater" OFF)
|
||||||
|
option(UPDATE_CHECK "Enable automatic update check" ON)
|
||||||
option(USE_CCACHE "Use ccache when available" ON)
|
option(USE_CCACHE "Use ccache when available" ON)
|
||||||
option(SPELL_CHECK "Enable spell cheching support" ON)
|
option(SPELL_CHECK "Enable spell cheching support" ON)
|
||||||
option(ASAN "Compile with AddressSanitizer" OFF)
|
option(ASAN "Compile with AddressSanitizer" OFF)
|
||||||
|
@ -632,6 +633,16 @@ if(${AUTOUPDATE} AND (WIN32 OR APPLE))
|
||||||
message(STATUS "using autoupdater")
|
message(STATUS "using autoupdater")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(${UPDATE_CHECK})
|
||||||
|
add_definitions(-DUPDATE_CHECK_ENABLED=1)
|
||||||
|
set(${PROJECT_NAME}_SOURCES ${${PROJECT_NAME}_SOURCES}
|
||||||
|
src/net/updatecheck.cpp
|
||||||
|
src/net/updatecheck.h)
|
||||||
|
message(STATUS "using update check")
|
||||||
|
else()
|
||||||
|
message(STATUS "NOT using update check")
|
||||||
|
endif()
|
||||||
|
|
||||||
if (MINGW)
|
if (MINGW)
|
||||||
STRING(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
|
STRING(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
|
||||||
if (CMAKE_BUILD_TYPE_LOWER MATCHES debug)
|
if (CMAKE_BUILD_TYPE_LOWER MATCHES debug)
|
||||||
|
|
|
@ -117,7 +117,7 @@ cd build
|
||||||
export PKG_CONFIG_PATH=/deps/lib/pkgconfig/
|
export PKG_CONFIG_PATH=/deps/lib/pkgconfig/
|
||||||
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=ON \
|
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=ON \
|
||||||
-DAPPIMAGEKIT_PACKAGE_DEBS=ON
|
-DAPPIMAGEKIT_PACKAGE_DEBS=ON -DUPDATE_CHECK=ON
|
||||||
|
|
||||||
make
|
make
|
||||||
make install
|
make install
|
||||||
|
|
|
@ -234,7 +234,7 @@ build() {
|
||||||
fcho "Now working in ${PWD}"
|
fcho "Now working in ${PWD}"
|
||||||
fcho "Starting cmake ..."
|
fcho "Starting cmake ..."
|
||||||
export CMAKE_PREFIX_PATH=$(brew --prefix qt5)
|
export CMAKE_PREFIX_PATH=$(brew --prefix qt5)
|
||||||
cmake -H$QTOX_DIR -B.
|
cmake -H$QTOX_DIR -B. -DUPDATE_CHECK=ON
|
||||||
make -j$(sysctl -n hw.ncpu)
|
make -j$(sysctl -n hw.ncpu)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,9 @@ void logMessageHandler(QtMsgType type, const QMessageLogContext& ctxt, const QSt
|
||||||
case QtDebugMsg:
|
case QtDebugMsg:
|
||||||
LogMsg += "Debug";
|
LogMsg += "Debug";
|
||||||
break;
|
break;
|
||||||
|
case QtInfoMsg:
|
||||||
|
LogMsg += "Info";
|
||||||
|
break;
|
||||||
case QtWarningMsg:
|
case QtWarningMsg:
|
||||||
LogMsg += "Warning";
|
LogMsg += "Warning";
|
||||||
break;
|
break;
|
||||||
|
|
94
src/net/updatecheck.cpp
Normal file
94
src/net/updatecheck.cpp
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
Copyright © 2014-2018 by The qTox Project Contributors
|
||||||
|
|
||||||
|
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||||
|
|
||||||
|
qTox is libre software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
qTox is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include "src/net/updatecheck.h"
|
||||||
|
#include "src/persistence/settings.h"
|
||||||
|
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const QString versionUrl{QStringLiteral("https://api.github.com/repos/qTox/qTox/releases/latest")};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
UpdateCheck::UpdateCheck(const Settings& settings)
|
||||||
|
: settings(settings)
|
||||||
|
{
|
||||||
|
updateTimer.start(1000 * 60 * 60 * 24 /* 1 day */);
|
||||||
|
connect(&updateTimer, &QTimer::timeout, this, &UpdateCheck::checkForUpdate);
|
||||||
|
connect(&manager, &QNetworkAccessManager::finished, this, &UpdateCheck::handleResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateCheck::checkForUpdate()
|
||||||
|
{
|
||||||
|
if (!settings.getCheckUpdates()) {
|
||||||
|
// still run the timer to check periodically incase setting changes
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
manager.setProxy(settings.getProxy());
|
||||||
|
QNetworkRequest request{versionUrl};
|
||||||
|
manager.get(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateCheck::handleResponse(QNetworkReply *reply)
|
||||||
|
{
|
||||||
|
assert(reply != nullptr);
|
||||||
|
if (reply == nullptr) {
|
||||||
|
qWarning() << "Update check returned null reply, ignoring";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
|
qWarning() << "Failed to check for update:" << reply->error();
|
||||||
|
emit updateCheckFailed();
|
||||||
|
reply->deleteLater();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QByteArray result = reply->readAll();
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(result);
|
||||||
|
QJsonObject jObject = doc.object();
|
||||||
|
QVariantMap mainMap = jObject.toVariantMap();
|
||||||
|
QString latestVersion = mainMap["tag_name"].toString();
|
||||||
|
if (latestVersion.isEmpty()) {
|
||||||
|
qWarning() << "No tag name found in response:";
|
||||||
|
emit updateCheckFailed();
|
||||||
|
reply->deleteLater();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// capture tag name to avoid showing update available on dev builds which include hash as part of describe
|
||||||
|
QRegularExpression versionFormat{QStringLiteral("v[0-9]+.[0-9]+.[0-9]+")};
|
||||||
|
QString curVer = versionFormat.match(GIT_DESCRIBE).captured(0);
|
||||||
|
if (latestVersion != curVer) {
|
||||||
|
qInfo() << "Update available to version" << latestVersion;
|
||||||
|
QUrl link{mainMap["html_url"].toString()};
|
||||||
|
emit updateAvailable(latestVersion, link);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qInfo() << "qTox is up to date";
|
||||||
|
emit upToDate();
|
||||||
|
}
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
49
src/net/updatecheck.h
Normal file
49
src/net/updatecheck.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
Copyright © 2014-2018 by The qTox Project Contributors
|
||||||
|
|
||||||
|
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||||
|
|
||||||
|
qTox is libre software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
qTox is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <QObject>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class Settings;
|
||||||
|
class QString;
|
||||||
|
class QUrl;
|
||||||
|
class QNetworkReply;
|
||||||
|
class UpdateCheck : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
UpdateCheck(const Settings& settings);
|
||||||
|
void checkForUpdate();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void updateAvailable(QString latestVersion, QUrl link);
|
||||||
|
void upToDate();
|
||||||
|
void updateCheckFailed();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleResponse(QNetworkReply *reply);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QNetworkAccessManager manager;
|
||||||
|
QTimer updateTimer;
|
||||||
|
const Settings& settings;
|
||||||
|
};
|
|
@ -69,53 +69,55 @@ static constexpr int TYPING_NOTIFICATION_DURATION = 3000;
|
||||||
|
|
||||||
const QString ChatForm::ACTION_PREFIX = QStringLiteral("/me ");
|
const QString ChatForm::ACTION_PREFIX = QStringLiteral("/me ");
|
||||||
|
|
||||||
QString statusToString(const Status status)
|
namespace
|
||||||
{
|
{
|
||||||
QString result;
|
QString statusToString(const Status status)
|
||||||
switch (status) {
|
{
|
||||||
case Status::Online:
|
QString result;
|
||||||
result = ChatForm::tr("online", "contact status");
|
switch (status) {
|
||||||
break;
|
case Status::Online:
|
||||||
case Status::Away:
|
result = ChatForm::tr("online", "contact status");
|
||||||
result = ChatForm::tr("away", "contact status");
|
break;
|
||||||
break;
|
case Status::Away:
|
||||||
case Status::Busy:
|
result = ChatForm::tr("away", "contact status");
|
||||||
result = ChatForm::tr("busy", "contact status");
|
break;
|
||||||
break;
|
case Status::Busy:
|
||||||
case Status::Offline:
|
result = ChatForm::tr("busy", "contact status");
|
||||||
result = ChatForm::tr("offline", "contact status");
|
break;
|
||||||
break;
|
case Status::Offline:
|
||||||
}
|
result = ChatForm::tr("offline", "contact status");
|
||||||
return result;
|
break;
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
QString secondsToDHMS(quint32 duration)
|
|
||||||
{
|
|
||||||
QString res;
|
|
||||||
QString cD = ChatForm::tr("Call duration: ");
|
|
||||||
quint32 seconds = duration % 60;
|
|
||||||
duration /= 60;
|
|
||||||
quint32 minutes = duration % 60;
|
|
||||||
duration /= 60;
|
|
||||||
quint32 hours = duration % 24;
|
|
||||||
quint32 days = duration / 24;
|
|
||||||
|
|
||||||
// I assume no one will ever have call longer than a month
|
|
||||||
if (days) {
|
|
||||||
return cD + res.sprintf("%dd%02dh %02dm %02ds", days, hours, minutes, seconds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hours) {
|
QString secondsToDHMS(quint32 duration)
|
||||||
return cD + res.sprintf("%02dh %02dm %02ds", hours, minutes, seconds);
|
{
|
||||||
|
QString res;
|
||||||
|
QString cD = ChatForm::tr("Call duration: ");
|
||||||
|
quint32 seconds = duration % 60;
|
||||||
|
duration /= 60;
|
||||||
|
quint32 minutes = duration % 60;
|
||||||
|
duration /= 60;
|
||||||
|
quint32 hours = duration % 24;
|
||||||
|
quint32 days = duration / 24;
|
||||||
|
|
||||||
|
// I assume no one will ever have call longer than a month
|
||||||
|
if (days) {
|
||||||
|
return cD + res.sprintf("%dd%02dh %02dm %02ds", days, hours, minutes, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hours) {
|
||||||
|
return cD + res.sprintf("%02dh %02dm %02ds", hours, minutes, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minutes) {
|
||||||
|
return cD + res.sprintf("%02dm %02ds", minutes, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cD + res.sprintf("%02ds", seconds);
|
||||||
}
|
}
|
||||||
|
} // namespace
|
||||||
if (minutes) {
|
|
||||||
return cD + res.sprintf("%02dm %02ds", minutes, seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cD + res.sprintf("%02ds", seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ChatForm::ChatForm(Friend* chatFriend, History* history)
|
ChatForm::ChatForm(Friend* chatFriend, History* history)
|
||||||
: GenericChatForm(chatFriend)
|
: GenericChatForm(chatFriend)
|
||||||
|
|
|
@ -20,13 +20,29 @@
|
||||||
#include "aboutform.h"
|
#include "aboutform.h"
|
||||||
#include "ui_aboutsettings.h"
|
#include "ui_aboutsettings.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include "src/widget/tool/recursivesignalblocker.h"
|
||||||
#include <QTimer>
|
#include "src/net/autoupdate.h"
|
||||||
|
#include "src/net/updatecheck.h"
|
||||||
|
#include "src/widget/translator.h"
|
||||||
|
#include "src/persistence/profile.h"
|
||||||
|
#include "src/persistence/settings.h"
|
||||||
|
|
||||||
#include <tox/tox.h>
|
#include <tox/tox.h>
|
||||||
|
|
||||||
#include "src/net/autoupdate.h"
|
#include <QDebug>
|
||||||
#include "src/widget/tool/recursivesignalblocker.h"
|
#include <QDesktopServices>
|
||||||
#include "src/widget/translator.h"
|
#include <QPushButton>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
// index of UI in the QStackedWidget
|
||||||
|
enum class updateIndex
|
||||||
|
{
|
||||||
|
available = 0,
|
||||||
|
upToDate = 1,
|
||||||
|
failed = 2
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class AboutForm
|
* @class AboutForm
|
||||||
|
@ -38,10 +54,11 @@
|
||||||
/**
|
/**
|
||||||
* @brief Constructor of AboutForm.
|
* @brief Constructor of AboutForm.
|
||||||
*/
|
*/
|
||||||
AboutForm::AboutForm()
|
AboutForm::AboutForm(UpdateCheck* updateCheck)
|
||||||
: GenericForm(QPixmap(":/img/settings/general.png"))
|
: GenericForm(QPixmap(":/img/settings/general.png"))
|
||||||
, bodyUI(new Ui::AboutSettings)
|
, bodyUI(new Ui::AboutSettings)
|
||||||
, progressTimer(new QTimer(this))
|
, progressTimer(new QTimer(this))
|
||||||
|
, updateCheck(updateCheck)
|
||||||
{
|
{
|
||||||
bodyUI->setupUi(this);
|
bodyUI->setupUi(this);
|
||||||
|
|
||||||
|
@ -84,6 +101,18 @@ void AboutForm::replaceVersions()
|
||||||
|
|
||||||
bodyUI->youAreUsing->setText(tr("You are using qTox version %1.").arg(QString(GIT_DESCRIBE)));
|
bodyUI->youAreUsing->setText(tr("You are using qTox version %1.").arg(QString(GIT_DESCRIBE)));
|
||||||
|
|
||||||
|
#if UPDATE_CHECK_ENABLED && !AUTOUPDATE_ENABLED
|
||||||
|
if (updateCheck != nullptr) {
|
||||||
|
connect(updateCheck, &UpdateCheck::updateAvailable, this, &AboutForm::onUpdateAvailable);
|
||||||
|
connect(updateCheck, &UpdateCheck::upToDate, this, &AboutForm::onUpToDate);
|
||||||
|
connect(updateCheck, &UpdateCheck::updateCheckFailed, this, &AboutForm::onUpdateCheckFailed);
|
||||||
|
} else {
|
||||||
|
qWarning() << "AboutForm passed null UpdateCheck!";
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
qDebug() << "AboutForm not showing updates, qTox built without UPDATE_CHECK";
|
||||||
|
#endif
|
||||||
|
|
||||||
QString commitLink = "https://github.com/qTox/qTox/commit/" + QString(GIT_VERSION);
|
QString commitLink = "https://github.com/qTox/qTox/commit/" + QString(GIT_VERSION);
|
||||||
bodyUI->gitVersion->setText(
|
bodyUI->gitVersion->setText(
|
||||||
tr("Commit hash: %1").arg(createLink(commitLink, QString(GIT_VERSION))));
|
tr("Commit hash: %1").arg(createLink(commitLink, QString(GIT_VERSION))));
|
||||||
|
@ -146,6 +175,25 @@ void AboutForm::replaceVersions()
|
||||||
bodyUI->authorInfo->setText(authorInfo);
|
bodyUI->authorInfo->setText(authorInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AboutForm::onUpdateAvailable(QString latestVersion, QUrl link)
|
||||||
|
{
|
||||||
|
QObject::disconnect(linkConnection);
|
||||||
|
linkConnection = connect(bodyUI->updateAvailableButton, &QPushButton::clicked, [link](){
|
||||||
|
QDesktopServices::openUrl(link);
|
||||||
|
});
|
||||||
|
bodyUI->updateStack->setCurrentIndex(static_cast<int>(updateIndex::available));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AboutForm::onUpToDate()
|
||||||
|
{
|
||||||
|
bodyUI->updateStack->setCurrentIndex(static_cast<int>(updateIndex::upToDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AboutForm::onUpdateCheckFailed()
|
||||||
|
{
|
||||||
|
bodyUI->updateStack->setCurrentIndex(static_cast<int>(updateIndex::failed));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates hyperlink with specific style.
|
* @brief Creates hyperlink with specific style.
|
||||||
* @param path The URL of the page the link goes to.
|
* @param path The URL of the page the link goes to.
|
||||||
|
|
|
@ -22,9 +22,12 @@
|
||||||
|
|
||||||
#include "genericsettings.h"
|
#include "genericsettings.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
class Core;
|
class Core;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
class QString;
|
class QString;
|
||||||
|
class UpdateCheck;
|
||||||
|
class QLayoutItem;
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class AboutSettings;
|
class AboutSettings;
|
||||||
|
@ -34,13 +37,18 @@ class AboutForm : public GenericForm
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
AboutForm();
|
AboutForm(UpdateCheck* updateCheck);
|
||||||
~AboutForm();
|
~AboutForm();
|
||||||
virtual QString getFormName() final override
|
virtual QString getFormName() final override
|
||||||
{
|
{
|
||||||
return tr("About");
|
return tr("About");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void onUpdateAvailable(QString latestVersion, QUrl link);
|
||||||
|
void onUpToDate();
|
||||||
|
void onUpdateCheckFailed();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
private slots:
|
private slots:
|
||||||
void showUpdateProgress();
|
void showUpdateProgress();
|
||||||
|
@ -55,6 +63,8 @@ private:
|
||||||
private:
|
private:
|
||||||
Ui::AboutSettings* bodyUI;
|
Ui::AboutSettings* bodyUI;
|
||||||
QTimer* progressTimer;
|
QTimer* progressTimer;
|
||||||
|
UpdateCheck* updateCheck;
|
||||||
|
QMetaObject::Connection linkConnection;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ABOUTFORM_H
|
#endif // ABOUTFORM_H
|
||||||
|
|
|
@ -175,6 +175,89 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QStackedWidget" name="updateStack">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="updateAvailablePage">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="updateAvailableLayout">
|
||||||
|
<item>
|
||||||
|
<spacer name="updateAvailableSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="updateAvailableButton">
|
||||||
|
<property name="accessibleDescription">
|
||||||
|
<string>Open update download link</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Update available</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="upToDatePage">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="upToDateLayout">
|
||||||
|
<item>
|
||||||
|
<spacer name="upToDateSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="upToDateLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>qTox is up to date ✓</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="blankPage">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<spacer name="blankPageFiller">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -100,9 +100,7 @@ GeneralForm::GeneralForm(SettingsWidget* myParent)
|
||||||
|
|
||||||
Settings& s = Settings::getInstance();
|
Settings& s = Settings::getInstance();
|
||||||
|
|
||||||
#ifdef AUTOUPDATE_ENABLED
|
#if !defined(AUTOUPDATE_ENABLED) && !defined(UPDATE_CHECK_ENABLED)
|
||||||
bodyUI->checkUpdates->setVisible(AUTOUPDATE_ENABLED);
|
|
||||||
#else
|
|
||||||
bodyUI->checkUpdates->setVisible(false);
|
bodyUI->checkUpdates->setVisible(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="checkUpdates">
|
<widget class="QCheckBox" name="checkUpdates">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Check for updates on startup</string>
|
<string>Check for updates</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "src/audio/audio.h"
|
#include "src/audio/audio.h"
|
||||||
#include "src/core/coreav.h"
|
#include "src/core/coreav.h"
|
||||||
#include "src/core/core.h"
|
#include "src/core/core.h"
|
||||||
|
#include "src/net/updatecheck.h"
|
||||||
#include "src/persistence/settings.h"
|
#include "src/persistence/settings.h"
|
||||||
#include "src/video/camerasource.h"
|
#include "src/video/camerasource.h"
|
||||||
#include "src/widget/contentlayout.h"
|
#include "src/widget/contentlayout.h"
|
||||||
|
@ -40,7 +41,7 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
SettingsWidget::SettingsWidget(QWidget* parent)
|
SettingsWidget::SettingsWidget(UpdateCheck* updateCheck, QWidget* parent)
|
||||||
: QWidget(parent, Qt::Window)
|
: QWidget(parent, Qt::Window)
|
||||||
{
|
{
|
||||||
Audio* audio = &Audio::getInstance();
|
Audio* audio = &Audio::getInstance();
|
||||||
|
@ -63,7 +64,15 @@ SettingsWidget::SettingsWidget(QWidget* parent)
|
||||||
AVForm* rawAvfrm = new AVForm(audio, coreAV, camera, audioSettings, videoSettings);
|
AVForm* rawAvfrm = new AVForm(audio, coreAV, camera, audioSettings, videoSettings);
|
||||||
std::unique_ptr<AVForm> avfrm(rawAvfrm);
|
std::unique_ptr<AVForm> avfrm(rawAvfrm);
|
||||||
std::unique_ptr<AdvancedForm> expfrm(new AdvancedForm());
|
std::unique_ptr<AdvancedForm> expfrm(new AdvancedForm());
|
||||||
std::unique_ptr<AboutForm> abtfrm(new AboutForm());
|
std::unique_ptr<AboutForm> abtfrm(new AboutForm(updateCheck));
|
||||||
|
|
||||||
|
#if UPDATE_CHECK_ENABLED && !AUTOUPDATE_ENABLED
|
||||||
|
if (updateCheck != nullptr) {
|
||||||
|
connect(updateCheck, &UpdateCheck::updateAvailable, this, &SettingsWidget::onUpdateAvailable);
|
||||||
|
} else {
|
||||||
|
qWarning() << "SettingsWidget passed null UpdateCheck!";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
cfgForms = {{std::move(gfrm), std::move(uifrm), std::move(pfrm), std::move(avfrm), std::move(expfrm), std::move(abtfrm)}};
|
cfgForms = {{std::move(gfrm), std::move(uifrm), std::move(pfrm), std::move(avfrm), std::move(expfrm), std::move(abtfrm)}};
|
||||||
for (auto& cfgForm : cfgForms)
|
for (auto& cfgForm : cfgForms)
|
||||||
|
@ -111,6 +120,13 @@ void SettingsWidget::onTabChanged(int index)
|
||||||
settingsWidgets->setCurrentIndex(index);
|
settingsWidgets->setCurrentIndex(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsWidget::onUpdateAvailable(void)
|
||||||
|
{
|
||||||
|
settingsWidgets->tabBar()->setProperty("update-available", true);
|
||||||
|
settingsWidgets->tabBar()->style()->unpolish(settingsWidgets->tabBar());
|
||||||
|
settingsWidgets->tabBar()->style()->polish(settingsWidgets->tabBar());
|
||||||
|
}
|
||||||
|
|
||||||
void SettingsWidget::retranslateUi()
|
void SettingsWidget::retranslateUi()
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < cfgForms.size(); ++i)
|
for (size_t i = 0; i < cfgForms.size(); ++i)
|
||||||
|
|
|
@ -35,12 +35,13 @@ class AVForm;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QTabWidget;
|
class QTabWidget;
|
||||||
class ContentLayout;
|
class ContentLayout;
|
||||||
|
class UpdateCheck;
|
||||||
|
|
||||||
class SettingsWidget : public QWidget
|
class SettingsWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit SettingsWidget(QWidget* parent = nullptr);
|
SettingsWidget(UpdateCheck* updateCheck, QWidget* parent = nullptr);
|
||||||
~SettingsWidget();
|
~SettingsWidget();
|
||||||
|
|
||||||
bool isShown() const;
|
bool isShown() const;
|
||||||
|
@ -49,6 +50,9 @@ public:
|
||||||
|
|
||||||
void showAbout();
|
void showAbout();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void onUpdateAvailable(void);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onTabChanged(int);
|
void onTabChanged(int);
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
#include "src/model/groupinvite.h"
|
#include "src/model/groupinvite.h"
|
||||||
#include "src/model/profile/profileinfo.h"
|
#include "src/model/profile/profileinfo.h"
|
||||||
#include "src/net/autoupdate.h"
|
#include "src/net/autoupdate.h"
|
||||||
|
#include "src/net/updatecheck.h"
|
||||||
#include "src/nexus.h"
|
#include "src/nexus.h"
|
||||||
#include "src/persistence/offlinemsgengine.h"
|
#include "src/persistence/offlinemsgengine.h"
|
||||||
#include "src/persistence/profile.h"
|
#include "src/persistence/profile.h"
|
||||||
|
@ -232,6 +233,14 @@ void Widget::init()
|
||||||
filesForm = new FilesForm();
|
filesForm = new FilesForm();
|
||||||
addFriendForm = new AddFriendForm;
|
addFriendForm = new AddFriendForm;
|
||||||
groupInviteForm = new GroupInviteForm;
|
groupInviteForm = new GroupInviteForm;
|
||||||
|
#if UPDATE_CHECK_ENABLED
|
||||||
|
updateCheck = std::unique_ptr<UpdateCheck>(new UpdateCheck(Settings::getInstance()));
|
||||||
|
connect(updateCheck.get(), &UpdateCheck::updateAvailable, this, &Widget::onUpdateAvailable);
|
||||||
|
#endif
|
||||||
|
settingsWidget = new SettingsWidget(updateCheck.get(), this);
|
||||||
|
#if UPDATE_CHECK_ENABLED
|
||||||
|
updateCheck->checkForUpdate();
|
||||||
|
#endif
|
||||||
|
|
||||||
Core* core = Nexus::getCore();
|
Core* core = Nexus::getCore();
|
||||||
Profile* profile = Nexus::getProfile();
|
Profile* profile = Nexus::getProfile();
|
||||||
|
@ -848,10 +857,6 @@ void Widget::onIconClick(QSystemTrayIcon::ActivationReason reason)
|
||||||
|
|
||||||
void Widget::onShowSettings()
|
void Widget::onShowSettings()
|
||||||
{
|
{
|
||||||
if (!settingsWidget) {
|
|
||||||
settingsWidget = new SettingsWidget(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Settings::getInstance().getSeparateWindow()) {
|
if (Settings::getInstance().getSeparateWindow()) {
|
||||||
if (!settingsWidget->isShown()) {
|
if (!settingsWidget->isShown()) {
|
||||||
settingsWidget->show(createContentDialog(DialogType::SettingDialog));
|
settingsWidget->show(createContentDialog(DialogType::SettingDialog));
|
||||||
|
@ -1589,6 +1594,13 @@ void Widget::toggleFullscreen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::onUpdateAvailable(QString /*latestVersion*/, QUrl /*link*/)
|
||||||
|
{
|
||||||
|
ui->settingsButton->setProperty("update-available", true);
|
||||||
|
ui->settingsButton->style()->unpolish(ui->settingsButton);
|
||||||
|
ui->settingsButton->style()->polish(ui->settingsButton);
|
||||||
|
}
|
||||||
|
|
||||||
ContentDialog* Widget::createContentDialog() const
|
ContentDialog* Widget::createContentDialog() const
|
||||||
{
|
{
|
||||||
ContentDialog* contentDialog = new ContentDialog();
|
ContentDialog* contentDialog = new ContentDialog();
|
||||||
|
|
|
@ -69,6 +69,7 @@ class QTimer;
|
||||||
class SettingsWidget;
|
class SettingsWidget;
|
||||||
class SystemTrayIcon;
|
class SystemTrayIcon;
|
||||||
class VideoSurface;
|
class VideoSurface;
|
||||||
|
class UpdateCheck;
|
||||||
|
|
||||||
class Widget final : public QMainWindow
|
class Widget final : public QMainWindow
|
||||||
{
|
{
|
||||||
|
@ -183,6 +184,7 @@ public slots:
|
||||||
void onGroupDialogShown(Group* g);
|
void onGroupDialogShown(Group* g);
|
||||||
void toggleFullscreen();
|
void toggleFullscreen();
|
||||||
void refreshPeerListsLocal(const QString &username);
|
void refreshPeerListsLocal(const QString &username);
|
||||||
|
void onUpdateAvailable(QString latestVersion, QUrl link);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void friendRequestAccepted(const ToxPk& friendPk);
|
void friendRequestAccepted(const ToxPk& friendPk);
|
||||||
|
@ -288,6 +290,7 @@ private:
|
||||||
ProfileForm* profileForm;
|
ProfileForm* profileForm;
|
||||||
|
|
||||||
QPointer<SettingsWidget> settingsWidget;
|
QPointer<SettingsWidget> settingsWidget;
|
||||||
|
std::unique_ptr<UpdateCheck> updateCheck; // ownership should be moved outside Widget once non-singleton
|
||||||
FilesForm* filesForm;
|
FilesForm* filesForm;
|
||||||
static Widget* instance;
|
static Widget* instance;
|
||||||
GenericChatroomWidget* activeChatroomWidget;
|
GenericChatroomWidget* activeChatroomWidget;
|
||||||
|
|
|
@ -105,6 +105,17 @@ QScrollBar:vertical
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* using last is a bit of a hack, but QTabBar otherwise doesn't allow selecting single tabs */
|
||||||
|
QTabBar::tab:last:!selected[update-available=true]
|
||||||
|
{
|
||||||
|
background-color: #80c580;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton#updateAvailableButton
|
||||||
|
{
|
||||||
|
background-color: #21da21;
|
||||||
|
}
|
||||||
|
|
||||||
QScrollBar::handle:vertical
|
QScrollBar::handle:vertical
|
||||||
{
|
{
|
||||||
background-color: #d1d1d1;
|
background-color: #d1d1d1;
|
||||||
|
|
|
@ -1,3 +1,15 @@
|
||||||
|
QPushButton[update-available=true]
|
||||||
|
{
|
||||||
|
background-color: #115508;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton:hover[update-available=true]
|
||||||
|
{
|
||||||
|
background-color: #2b9e1c;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
QPushButton
|
QPushButton
|
||||||
{
|
{
|
||||||
background-color: @themeDark;
|
background-color: @themeDark;
|
||||||
|
|
|
@ -1130,12 +1130,14 @@ then
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=./toolchain.cmake \
|
cmake -DCMAKE_TOOLCHAIN_FILE=./toolchain.cmake \
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
-DSPELL_CHECK=OFF \
|
-DSPELL_CHECK=OFF \
|
||||||
|
-DUPDATE_CHECK=ON \
|
||||||
..
|
..
|
||||||
elif [[ "$BUILD_TYPE" == "debug" ]]
|
elif [[ "$BUILD_TYPE" == "debug" ]]
|
||||||
then
|
then
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=./toolchain.cmake \
|
cmake -DCMAKE_TOOLCHAIN_FILE=./toolchain.cmake \
|
||||||
-DCMAKE_BUILD_TYPE=Debug \
|
-DCMAKE_BUILD_TYPE=Debug \
|
||||||
-DSPELL_CHECK=OFF \
|
-DSPELL_CHECK=OFF \
|
||||||
|
-DUPDATE_CHECK=ON \
|
||||||
..
|
..
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user