ui: Show news sent with update check on start screen
* News are passed as JSON string, containing an array of news items. * Each news item has version and content (html). * Items can be filtered by min/max version, OS and license. The first item that fits is used. * Items can be important, which highlights the news box. * News are not shown if older than 5 days. fortune cookie message = You will be financially successful in case your actions are well planned.
This commit is contained in:
@@ -29,19 +29,38 @@
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
#recentLabel {
|
||||
#titleLabel {
|
||||
color: black;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
#versionLabel {
|
||||
#textLabel {
|
||||
color: black;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#boldLabel {
|
||||
color: black;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#textField {
|
||||
background: white;
|
||||
border: 1px solid lightgray;
|
||||
border-radius: 12px;
|
||||
color: black;
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
min-width: 180px;
|
||||
}
|
||||
|
||||
#textField[important=true] {
|
||||
border: 2px solid #007ac3;
|
||||
}
|
||||
|
||||
#updateButton, #upgradeButton {
|
||||
margin: 1px 0 3px;
|
||||
text-align: left;
|
||||
@@ -57,19 +76,3 @@
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#licenseHeaderLabel {
|
||||
color: black;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#licenseLabel {
|
||||
color: black;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#welcomeLabel {
|
||||
color: black;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
<skip_version><!-- VERSION: version to skip for update --></skip_version>
|
||||
<update_url><!-- STRING: url to new version download --></update_url>
|
||||
<update_version><!-- VERSION: version of last check --></update_version>
|
||||
<news><!-- STRING: news in last update check --></news>
|
||||
</update_check>
|
||||
|
||||
<seen_error_help_message><!-- BOOL: whether user has been shown help message on errors after indexing --></seen_error_help_message>
|
||||
|
||||
@@ -24,7 +24,7 @@ std::shared_ptr<LicenseChecker> LicenseChecker::getInstance()
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
std::string LicenseChecker::getCurrentLicenseString() const
|
||||
std::string LicenseChecker::getCurrentLicenseString()
|
||||
{
|
||||
License license;
|
||||
bool isLoaded = license.loadFromEncodedString(
|
||||
@@ -38,7 +38,7 @@ std::string LicenseChecker::getCurrentLicenseString() const
|
||||
return "";
|
||||
}
|
||||
|
||||
void LicenseChecker::saveCurrentLicenseString(const std::string& licenseString) const
|
||||
void LicenseChecker::saveCurrentLicenseString(const std::string& licenseString)
|
||||
{
|
||||
License license;
|
||||
bool isLoaded = license.loadFromString(licenseString);
|
||||
@@ -55,7 +55,7 @@ bool LicenseChecker::isCurrentLicenseValid()
|
||||
return checkCurrentLicense() == LICENSE_VALID;
|
||||
}
|
||||
|
||||
LicenseChecker::LicenseState LicenseChecker::checkCurrentLicense() const
|
||||
LicenseChecker::LicenseState LicenseChecker::checkCurrentLicense()
|
||||
{
|
||||
ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
|
||||
if (appSettings == nullptr)
|
||||
@@ -96,7 +96,7 @@ LicenseChecker::LicenseState LicenseChecker::checkCurrentLicense() const
|
||||
return checkLicense(license);
|
||||
}
|
||||
|
||||
LicenseChecker::LicenseState LicenseChecker::checkLicenseString(const std::string& licenseString) const
|
||||
LicenseChecker::LicenseState LicenseChecker::checkLicenseString(const std::string& licenseString)
|
||||
{
|
||||
if (licenseString.size() == 0)
|
||||
{
|
||||
@@ -115,7 +115,7 @@ LicenseChecker::LicenseState LicenseChecker::checkLicenseString(const std::strin
|
||||
return checkLicense(license);
|
||||
}
|
||||
|
||||
MessageEnteredLicense::LicenseType LicenseChecker::getCurrentLicenseType() const
|
||||
MessageEnteredLicense::LicenseType LicenseChecker::getCurrentLicenseType()
|
||||
{
|
||||
License license;
|
||||
bool isLoaded = license.loadFromEncodedString(
|
||||
@@ -143,7 +143,7 @@ MessageEnteredLicense::LicenseType LicenseChecker::getCurrentLicenseType() const
|
||||
return MessageEnteredLicense::LICENSE_COMMERCIAL;
|
||||
}
|
||||
|
||||
MessageEnteredLicense::LicenseType LicenseChecker::getLicenseType(const std::string& licenseString) const
|
||||
MessageEnteredLicense::LicenseType LicenseChecker::getLicenseType(const std::string& licenseString)
|
||||
{
|
||||
if (licenseString.size() == 0)
|
||||
{
|
||||
@@ -174,11 +174,28 @@ MessageEnteredLicense::LicenseType LicenseChecker::getLicenseType(const std::str
|
||||
return MessageEnteredLicense::LICENSE_COMMERCIAL;
|
||||
}
|
||||
|
||||
std::string LicenseChecker::getCurrentLicenseTypeString()
|
||||
{
|
||||
// WARNING: Don't change these string. The server API relies on them.
|
||||
switch (getCurrentLicenseType())
|
||||
{
|
||||
case MessageEnteredLicense::LICENSE_NONE:
|
||||
case MessageEnteredLicense::LICENSE_NON_COMMERCIAL:
|
||||
return "private";
|
||||
case MessageEnteredLicense::LICENSE_TEST:
|
||||
return "test";
|
||||
case MessageEnteredLicense::LICENSE_COMMERCIAL:
|
||||
return "commercial";
|
||||
}
|
||||
|
||||
return "private";
|
||||
}
|
||||
|
||||
LicenseChecker::LicenseChecker()
|
||||
{
|
||||
}
|
||||
|
||||
LicenseChecker::LicenseState LicenseChecker::checkLicense(License& license) const
|
||||
LicenseChecker::LicenseState LicenseChecker::checkLicense(License& license)
|
||||
{
|
||||
if (license.isExpired())
|
||||
{
|
||||
|
||||
@@ -23,22 +23,24 @@ public:
|
||||
|
||||
~LicenseChecker() = default;
|
||||
|
||||
std::string getCurrentLicenseString() const;
|
||||
void saveCurrentLicenseString(const std::string& licenseString) const;
|
||||
static std::string getCurrentLicenseString();
|
||||
static void saveCurrentLicenseString(const std::string& licenseString);
|
||||
|
||||
bool isCurrentLicenseValid();
|
||||
LicenseState checkCurrentLicense() const;
|
||||
LicenseState checkLicenseString(const std::string& licenseString) const;
|
||||
static bool isCurrentLicenseValid();
|
||||
static LicenseState checkCurrentLicense();
|
||||
static LicenseState checkLicenseString(const std::string& licenseString);
|
||||
|
||||
MessageEnteredLicense::LicenseType getCurrentLicenseType() const;
|
||||
MessageEnteredLicense::LicenseType getLicenseType(const std::string& licenseString) const;
|
||||
static MessageEnteredLicense::LicenseType getCurrentLicenseType();
|
||||
static MessageEnteredLicense::LicenseType getLicenseType(const std::string& licenseString);
|
||||
|
||||
static std::string getCurrentLicenseTypeString();
|
||||
|
||||
private:
|
||||
LicenseChecker();
|
||||
LicenseChecker(const LicenseChecker&) = delete;
|
||||
void operator=(const LicenseChecker&) = delete;
|
||||
|
||||
LicenseState checkLicense(License& license) const;
|
||||
static LicenseState checkLicense(License& license);
|
||||
|
||||
static std::shared_ptr<LicenseChecker> s_instance;
|
||||
};
|
||||
|
||||
@@ -597,6 +597,16 @@ Version ApplicationSettings::getUpdateVersion() const
|
||||
return Version::fromString(getValue<std::string>("user/update_check/update_version", "2017.1.0"));
|
||||
}
|
||||
|
||||
std::string ApplicationSettings::getUpdateNews() const
|
||||
{
|
||||
return getValue<std::string>("user/update_check/news", "");
|
||||
}
|
||||
|
||||
void ApplicationSettings::setUpdateNews(const std::string& news)
|
||||
{
|
||||
setValue<std::string>("user/update_check/news", news);
|
||||
}
|
||||
|
||||
void ApplicationSettings::setUpdateVersion(const Version& version)
|
||||
{
|
||||
if (version.isValid())
|
||||
|
||||
@@ -167,6 +167,9 @@ public:
|
||||
Version getUpdateVersion() const;
|
||||
void setUpdateVersion(const Version& version);
|
||||
|
||||
std::string getUpdateNews() const;
|
||||
void setUpdateNews(const std::string& news);
|
||||
|
||||
bool getSeenErrorHelpMessage() const;
|
||||
void setSeenErrorHelpMessage(bool seen);
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@ add_files(
|
||||
qt/element/QtListBoxItem.h
|
||||
qt/element/QtLocationPicker.cpp
|
||||
qt/element/QtLocationPicker.h
|
||||
qt/element/QtNewsWidget.cpp
|
||||
qt/element/QtNewsWidget.h
|
||||
qt/element/QtPathListBox.cpp
|
||||
qt/element/QtPathListBox.h
|
||||
qt/element/QtPathListBoxItem.cpp
|
||||
@@ -67,6 +69,8 @@ add_files(
|
||||
qt/element/QtStatusBar.h
|
||||
qt/element/QtTable.cpp
|
||||
qt/element/QtTable.h
|
||||
qt/element/QtTextEdit.cpp
|
||||
qt/element/QtTextEdit.h
|
||||
qt/element/QtTooltip.cpp
|
||||
qt/element/QtTooltip.h
|
||||
qt/element/QtUndoRedo.cpp
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
#include "QtNewsWidget.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QVBoxLayout>
|
||||
#include <QStyle>
|
||||
|
||||
#include "ApplicationSettings.h"
|
||||
#include "LicenseChecker.h"
|
||||
#include "logging.h"
|
||||
#include "QtTextEdit.h"
|
||||
#include "TimeStamp.h"
|
||||
#include "utilityApp.h"
|
||||
#include "Version.h"
|
||||
|
||||
QtNewsWidget::QtNewsWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(0);
|
||||
|
||||
m_text = new QtTextEdit();
|
||||
m_text->setObjectName("textField");
|
||||
m_text->setReadOnly(true);
|
||||
m_text->setTabStopWidth(8 * m_text->fontMetrics().width('9'));
|
||||
m_text->setViewportMargins(6, 4, 16, 4);
|
||||
m_text->setOpenExternalLinks(true);
|
||||
layout->addWidget(m_text);
|
||||
|
||||
QString placeholder = "No news available";
|
||||
if (!ApplicationSettings::getInstance()->getAutomaticUpdateCheck())
|
||||
{
|
||||
placeholder += "\n(Enable update check)";
|
||||
}
|
||||
m_text->setPlaceholderText(placeholder);
|
||||
|
||||
updateNews();
|
||||
}
|
||||
|
||||
/*
|
||||
syntax:
|
||||
[
|
||||
{
|
||||
// required
|
||||
"version": 1,
|
||||
"content": "<b>Hello World!</b>",
|
||||
|
||||
// optional
|
||||
"conditions":
|
||||
{
|
||||
"license": ["test", "private", "commercial"],
|
||||
"os": ["windows", "macOS", "linux"],
|
||||
"min_version": "2017.2.0",
|
||||
"max_version": "2018.4.2",
|
||||
}
|
||||
|
||||
// optional
|
||||
"flags":
|
||||
{
|
||||
"important": true
|
||||
}
|
||||
}
|
||||
]
|
||||
*/
|
||||
|
||||
void QtNewsWidget::updateNews()
|
||||
{
|
||||
const int supportedNewsItemVersion = 1;
|
||||
|
||||
resetFlags();
|
||||
|
||||
ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
|
||||
std::string newsRaw = appSettings->getUpdateNews();
|
||||
if (!newsRaw.size())
|
||||
{
|
||||
setNews("");
|
||||
return;
|
||||
}
|
||||
|
||||
if (TimeStamp::now().deltaHours(appSettings->getLastUpdateCheck()) >= 120)
|
||||
{
|
||||
LOG_INFO_STREAM(<< "Ignore news string, because older than 5 days.");
|
||||
setNews("");
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO_STREAM(<< "Process news string: " << newsRaw);
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(QString::fromStdString(newsRaw).toUtf8(), &error);
|
||||
if (doc.isNull() || !doc.isArray())
|
||||
{
|
||||
LOG_ERROR_STREAM(<< "News string couldn't be parsed as JSON: " << error.errorString().toStdString()
|
||||
<< "\nJSON: " << newsRaw);
|
||||
setNews("");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t itemNum = 0;
|
||||
for (QJsonValueRef value : doc.array())
|
||||
{
|
||||
itemNum++;
|
||||
QJsonObject newsItem = value.toObject();
|
||||
|
||||
int version = newsItem.value("version").toInt();
|
||||
if (version > supportedNewsItemVersion)
|
||||
{
|
||||
LOG_INFO_STREAM(<< "News item " << itemNum << " version " << version << " is not supported.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!checkConditions(newsItem.value("conditions").toObject()))
|
||||
{
|
||||
LOG_INFO_STREAM(<< "News item " << itemNum << " conditions failed.");
|
||||
continue;
|
||||
}
|
||||
|
||||
processFlags(newsItem.value("flags").toObject());
|
||||
setNews(newsItem.value("content").toString());
|
||||
return;
|
||||
}
|
||||
|
||||
setNews("");
|
||||
}
|
||||
|
||||
void QtNewsWidget::resetFlags()
|
||||
{
|
||||
setImportant(false);
|
||||
}
|
||||
|
||||
void QtNewsWidget::setNews(const QString& news)
|
||||
{
|
||||
m_text->setHtml(news);
|
||||
}
|
||||
|
||||
void QtNewsWidget::setImportant(bool important)
|
||||
{
|
||||
m_text->setProperty("important", important);
|
||||
m_text->style()->unpolish(m_text);
|
||||
m_text->style()->polish(m_text);
|
||||
}
|
||||
|
||||
bool QtNewsWidget::checkConditions(const QJsonObject& conditions) const
|
||||
{
|
||||
if (conditions.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// min_version
|
||||
{
|
||||
QString minVersionString = conditions.value("min_version").toString();
|
||||
if (!minVersionString.isEmpty())
|
||||
{
|
||||
Version minVersion = Version::fromString(minVersionString.toStdString());
|
||||
if (minVersion.isValid() && minVersion > Version::getApplicationVersion())
|
||||
{
|
||||
LOG_INFO_STREAM(<< "Failed condition min_version.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// max_version
|
||||
{
|
||||
QString maxVersionString = conditions.value("max_version").toString();
|
||||
if (!maxVersionString.isEmpty())
|
||||
{
|
||||
Version maxVersion = Version::fromString(maxVersionString.toStdString());
|
||||
if (maxVersion.isValid() && maxVersion < Version::getApplicationVersion())
|
||||
{
|
||||
LOG_INFO_STREAM(<< "Failed condition max_version.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// license
|
||||
{
|
||||
QJsonArray licenseStrings = conditions.value("license").toArray();
|
||||
if (!licenseStrings.isEmpty())
|
||||
{
|
||||
QString licenseString = QString::fromStdString(LicenseChecker::getCurrentLicenseTypeString());
|
||||
if (!licenseStrings.contains(QJsonValue(licenseString)))
|
||||
{
|
||||
LOG_INFO_STREAM(<< "Failed condition license.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OS
|
||||
{
|
||||
QJsonArray osStrings = conditions.value("os").toArray();
|
||||
if (!osStrings.isEmpty())
|
||||
{
|
||||
QString osString = QString::fromStdString(utility::getOsTypeString());
|
||||
if (!osStrings.contains(QJsonValue(osString)))
|
||||
{
|
||||
LOG_INFO_STREAM(<< "Failed condition os.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QtNewsWidget::processFlags(const QJsonObject& flags)
|
||||
{
|
||||
if (flags.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// important
|
||||
{
|
||||
bool important = flags.value("important").toBool();
|
||||
if (important)
|
||||
{
|
||||
LOG_INFO_STREAM(<< "Flag important enabled.");
|
||||
setImportant(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef QT_NEWS_WIDGET_H
|
||||
#define QT_NEWS_WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QtTextEdit;
|
||||
class QJsonObject;
|
||||
|
||||
class QtNewsWidget
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QtNewsWidget(QWidget* parent = nullptr);
|
||||
virtual ~QtNewsWidget() = default;
|
||||
|
||||
public slots:
|
||||
void updateNews();
|
||||
|
||||
private:
|
||||
void resetFlags();
|
||||
|
||||
void setNews(const QString& news);
|
||||
void setImportant(bool important);
|
||||
|
||||
bool checkConditions(const QJsonObject& conditions) const;
|
||||
void processFlags(const QJsonObject& flags);
|
||||
|
||||
QtTextEdit* m_text;
|
||||
};
|
||||
|
||||
#endif // QT_NEWS_WIDGET_H
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "QtTextEdit.h"
|
||||
|
||||
QtTextEdit::QtTextEdit(QWidget* parent)
|
||||
: QTextBrowser(parent)
|
||||
{
|
||||
document()->setDefaultStyleSheet("a { color: #007AC2; }");
|
||||
}
|
||||
|
||||
void QtTextEdit::setViewportMargins(int left, int top, int right, int bottom)
|
||||
{
|
||||
QAbstractScrollArea::setViewportMargins(left, top, right, bottom);
|
||||
}
|
||||
|
||||
void QtTextEdit::focusInEvent(QFocusEvent* event)
|
||||
{
|
||||
emit focus();
|
||||
QTextBrowser::focusInEvent(event);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef QT_TEXT_EDIT_H
|
||||
#define QT_TEXT_EDIT_H
|
||||
|
||||
#include <QTextBrowser>
|
||||
|
||||
class QtTextEdit
|
||||
: public QTextBrowser
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QtTextEdit(QWidget* parent = nullptr);
|
||||
|
||||
void setViewportMargins(int left, int top, int right, int bottom);
|
||||
|
||||
signals:
|
||||
void focus();
|
||||
|
||||
protected:
|
||||
void focusInEvent(QFocusEvent* event);
|
||||
};
|
||||
|
||||
#endif // QT_TEXT_EDIT_H
|
||||
@@ -99,6 +99,8 @@ void QtUpdateCheckerWidget::checkUpdate(bool force)
|
||||
{
|
||||
setDownloadUrl(result.url);
|
||||
}
|
||||
|
||||
emit updateReceived();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,10 +10,15 @@ class QPushButton;
|
||||
class QtUpdateCheckerWidget
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QtUpdateCheckerWidget(QWidget* parent = nullptr);
|
||||
virtual ~QtUpdateCheckerWidget();
|
||||
|
||||
signals:
|
||||
void updateReceived();
|
||||
|
||||
private:
|
||||
void checkUpdate(bool force);
|
||||
void setDownloadUrl(QString url);
|
||||
|
||||
@@ -36,27 +36,10 @@ void QtUpdateChecker::check(bool force, std::function<void(Result)> callback)
|
||||
appSettings->setUpdateDownloadUrl("");
|
||||
appSettings->save();
|
||||
|
||||
QString urlString = "https://www.sourcetrail.com/api/v1/versions/latest";
|
||||
QString urlString = "https://www.sourcetrail.com/api/v2/versions/latest";
|
||||
|
||||
// OS
|
||||
std::string osString;
|
||||
|
||||
switch (utility::getOsType())
|
||||
{
|
||||
case OS_WINDOWS:
|
||||
osString = "windows";
|
||||
break;
|
||||
case OS_MAC:
|
||||
osString = "macOS";
|
||||
break;
|
||||
case OS_LINUX:
|
||||
osString = "linux";
|
||||
break;
|
||||
default:
|
||||
callback(result);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string osString = utility::getOsTypeString();
|
||||
urlString += ("?os=" + osString).c_str();
|
||||
|
||||
// architecture
|
||||
@@ -68,21 +51,7 @@ void QtUpdateChecker::check(bool force, std::function<void(Result)> callback)
|
||||
urlString += ("&version=" + Version::getApplicationVersion().toDisplayString()).c_str();
|
||||
|
||||
// license
|
||||
std::string licenseString;
|
||||
switch (LicenseChecker::getInstance()->getCurrentLicenseType())
|
||||
{
|
||||
case MessageEnteredLicense::LICENSE_NONE:
|
||||
case MessageEnteredLicense::LICENSE_NON_COMMERCIAL:
|
||||
licenseString = "private";
|
||||
break;
|
||||
case MessageEnteredLicense::LICENSE_TEST:
|
||||
licenseString = "test";
|
||||
break;
|
||||
case MessageEnteredLicense::LICENSE_COMMERCIAL:
|
||||
licenseString = "commercial";
|
||||
break;
|
||||
}
|
||||
|
||||
std::string licenseString = LicenseChecker::getCurrentLicenseTypeString();
|
||||
urlString += ("&license=" + licenseString).c_str();
|
||||
|
||||
// user token
|
||||
@@ -103,15 +72,27 @@ void QtUpdateChecker::check(bool force, std::function<void(Result)> callback)
|
||||
{
|
||||
Result result;
|
||||
|
||||
ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
|
||||
bool saveAppSettings = false;
|
||||
|
||||
do
|
||||
{
|
||||
QJsonDocument doc = QJsonDocument::fromJson(bytes);
|
||||
if (!doc.isObject())
|
||||
QJsonParseError error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(bytes, &error);
|
||||
if (doc.isNull() || !doc.isObject())
|
||||
{
|
||||
LOG_ERROR_STREAM(<< "Update response couldn't be parsed as JSON");
|
||||
LOG_ERROR_STREAM(<< "Update response couldn't be parsed as JSON: " << error.errorString().toStdString());
|
||||
break;
|
||||
}
|
||||
|
||||
QString news = doc.object().find("news")->toString();
|
||||
if (news.toStdString() != appSettings->getUpdateNews())
|
||||
{
|
||||
appSettings->setUpdateNews(news.toStdString());
|
||||
saveAppSettings = true;
|
||||
}
|
||||
|
||||
|
||||
QString version = doc.object().find("version")->toString();
|
||||
QString url = doc.object().find("url")->toString();
|
||||
|
||||
@@ -129,10 +110,9 @@ void QtUpdateChecker::check(bool force, std::function<void(Result)> callback)
|
||||
result.version = updateVersion;
|
||||
result.url = url;
|
||||
|
||||
ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
|
||||
appSettings->setUpdateVersion(updateVersion);
|
||||
appSettings->setUpdateDownloadUrl(url.toStdString());
|
||||
appSettings->save();
|
||||
saveAppSettings = true;
|
||||
|
||||
if (!force && appSettings->getSkipUpdateForVersion() == updateVersion)
|
||||
{
|
||||
@@ -153,7 +133,6 @@ void QtUpdateChecker::check(bool force, std::function<void(Result)> callback)
|
||||
if (val == 1)
|
||||
{
|
||||
appSettings->setSkipUpdateForVersion(updateVersion);
|
||||
appSettings->save();
|
||||
}
|
||||
else if (val == 2)
|
||||
{
|
||||
@@ -163,6 +142,11 @@ void QtUpdateChecker::check(bool force, std::function<void(Result)> callback)
|
||||
}
|
||||
while (false);
|
||||
|
||||
if (saveAppSettings)
|
||||
{
|
||||
appSettings->save();
|
||||
}
|
||||
|
||||
request->deleteLater();
|
||||
|
||||
callback(result);
|
||||
|
||||
@@ -7,17 +7,17 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "ApplicationSettings.h"
|
||||
#include "AppPath.h"
|
||||
#include "MessageLoadProject.h"
|
||||
#include "ResourcePaths.h"
|
||||
#include "Version.h"
|
||||
|
||||
#include "License.h"
|
||||
#include "MessageLoadProject.h"
|
||||
#include "ProjectSettings.h"
|
||||
#include "PublicKey.h"
|
||||
#include "QtUpdateCheckerWidget.h"
|
||||
#include "QtNewsWidget.h"
|
||||
#include "ResourcePaths.h"
|
||||
#include "utilityQt.h"
|
||||
#include "ApplicationSettings.h"
|
||||
#include "ProjectSettings.h"
|
||||
#include "Version.h"
|
||||
|
||||
QtRecentProjectButton::QtRecentProjectButton(QWidget* parent)
|
||||
: QPushButton(parent)
|
||||
@@ -93,7 +93,7 @@ QtStartScreen::QtStartScreen(QWidget *parent)
|
||||
|
||||
QSize QtStartScreen::sizeHint() const
|
||||
{
|
||||
return QSize(570, 600);
|
||||
return QSize(570, 630);
|
||||
}
|
||||
|
||||
void QtStartScreen::updateButtons()
|
||||
@@ -153,39 +153,39 @@ void QtStartScreen::setupStartScreen()
|
||||
addLogo();
|
||||
|
||||
QHBoxLayout* layout = new QHBoxLayout();
|
||||
layout->setContentsMargins(15, 170, 15, 10);
|
||||
layout->setContentsMargins(15, 170, 15, 0);
|
||||
layout->setSpacing(1);
|
||||
m_content->setLayout(layout);
|
||||
|
||||
{
|
||||
QVBoxLayout* col = new QVBoxLayout();
|
||||
layout->addLayout(col, 2);
|
||||
layout->addLayout(col, 3);
|
||||
|
||||
QLabel* versionLabel = new QLabel(("Version " + Version::getApplicationVersion().toDisplayString()).c_str(), this);
|
||||
versionLabel->setObjectName("versionLabel");
|
||||
versionLabel->setObjectName("boldLabel");
|
||||
col->addWidget(versionLabel);
|
||||
|
||||
QtUpdateCheckerWidget* checker = new QtUpdateCheckerWidget(this);
|
||||
col->addWidget(checker);
|
||||
|
||||
col->addSpacing(30);
|
||||
col->addSpacing(15);
|
||||
|
||||
if (license.isValid())
|
||||
{
|
||||
std::string licenseString = license.getLicenseInfo();
|
||||
|
||||
QLabel* licenseHeader = new QLabel("Licensed to:");
|
||||
licenseHeader->setObjectName("licenseHeaderLabel");
|
||||
licenseHeader->setObjectName("boldLabel");
|
||||
col->addWidget(licenseHeader);
|
||||
col->addSpacing(2);
|
||||
QLabel* licenseLabel = new QLabel(licenseString.c_str());
|
||||
licenseLabel->setObjectName("licenseLabel");
|
||||
licenseLabel->setObjectName("textLabel");
|
||||
col->addWidget(licenseLabel);
|
||||
}
|
||||
else
|
||||
{
|
||||
QLabel* licenseHeader = new QLabel("Not licensed for<br />commercial use.");
|
||||
licenseHeader->setObjectName("licenseHeaderLabel");
|
||||
licenseHeader->setObjectName("boldLabel");
|
||||
col->addWidget(licenseHeader);
|
||||
|
||||
QPushButton* upgradeButton = new QPushButton("upgrade");
|
||||
@@ -195,6 +195,20 @@ void QtStartScreen::setupStartScreen()
|
||||
connect(upgradeButton, &QPushButton::clicked, [this](){ emit openEnterLicenseDialog(); });
|
||||
}
|
||||
|
||||
col->addSpacing(15);
|
||||
|
||||
{
|
||||
QLabel* newsHeader = new QLabel("News:");
|
||||
newsHeader->setObjectName("boldLabel");
|
||||
col->addWidget(newsHeader);
|
||||
|
||||
QtNewsWidget* newsWidget = new QtNewsWidget(this);
|
||||
col->addWidget(newsWidget);
|
||||
|
||||
connect(checker, &QtUpdateCheckerWidget::updateReceived, newsWidget, &QtNewsWidget::updateNews);
|
||||
}
|
||||
|
||||
col->addSpacing(15);
|
||||
col->addStretch();
|
||||
|
||||
QPushButton* newProjectButton = new QPushButton("New Project", this);
|
||||
@@ -212,23 +226,21 @@ void QtStartScreen::setupStartScreen()
|
||||
openProjectButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
connect(openProjectButton, &QPushButton::clicked, this, &QtStartScreen::handleOpenProjectButton);
|
||||
col->addWidget(openProjectButton);
|
||||
|
||||
layout->addStretch(2);
|
||||
}
|
||||
|
||||
layout->addSpacing(50);
|
||||
|
||||
{
|
||||
QVBoxLayout* col = new QVBoxLayout();
|
||||
layout->addLayout(col, 1);
|
||||
|
||||
QLabel* recentProjectsLabel = new QLabel("Recent Projects: ", this);
|
||||
recentProjectsLabel->setObjectName("recentLabel");
|
||||
recentProjectsLabel->setObjectName("titleLabel");
|
||||
col->addWidget(recentProjectsLabel);
|
||||
|
||||
col->addSpacing(20);
|
||||
|
||||
for (int i = 0
|
||||
; i < ApplicationSettings::getInstance()->getMaxRecentProjectsCount()
|
||||
; i++)
|
||||
for (int i = 0; i < ApplicationSettings::getInstance()->getMaxRecentProjectsCount(); i++)
|
||||
{
|
||||
QtRecentProjectButton* button = new QtRecentProjectButton(this);
|
||||
button->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
|
||||
|
||||
@@ -137,6 +137,16 @@ void utility::killRunningProcesses()
|
||||
}
|
||||
}
|
||||
|
||||
int utility::getIdealThreadCount()
|
||||
{
|
||||
int threadCount = QThread::idealThreadCount();
|
||||
if (getOsType() == OS_WINDOWS)
|
||||
{
|
||||
threadCount -= 1;
|
||||
}
|
||||
return std::max(1, threadCount);
|
||||
}
|
||||
|
||||
OsType utility::getOsType()
|
||||
{
|
||||
if (QSysInfo::windowsVersion() != QSysInfo::WV_None)
|
||||
@@ -154,14 +164,21 @@ OsType utility::getOsType()
|
||||
return OS_UNKNOWN;
|
||||
}
|
||||
|
||||
int utility::getIdealThreadCount()
|
||||
std::string utility::getOsTypeString()
|
||||
{
|
||||
int threadCount = QThread::idealThreadCount();
|
||||
if (getOsType() == OS_WINDOWS)
|
||||
// WARNING: Don't change these string. The server API relies on them.
|
||||
switch (utility::getOsType())
|
||||
{
|
||||
threadCount -= 1;
|
||||
case OS_WINDOWS:
|
||||
return "windows";
|
||||
case OS_MAC:
|
||||
return "macOS";
|
||||
case OS_LINUX:
|
||||
return "linux";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return std::max(1, threadCount);
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
bool utility::saveLicense(const License* license)
|
||||
|
||||
@@ -15,17 +15,17 @@ namespace utility
|
||||
std::string executeProcess(const std::string& command, const FilePath& workingDirectory = FilePath(), const int timeout = 30000);
|
||||
std::string executeProcessUntilNoOutput(const std::string& command, const FilePath& workingDirectory, int waitTime = 10000);
|
||||
int executeProcessAndGetExitCode(
|
||||
const std::wstring& commandPath,
|
||||
const std::vector<std::wstring>& commandArguments,
|
||||
const FilePath& workingDirectory = FilePath(),
|
||||
const std::wstring& commandPath,
|
||||
const std::vector<std::wstring>& commandArguments,
|
||||
const FilePath& workingDirectory = FilePath(),
|
||||
const int timeout = 30000
|
||||
);
|
||||
|
||||
void killRunningProcesses();
|
||||
|
||||
int getIdealThreadCount();
|
||||
|
||||
OsType getOsType();
|
||||
std::string getOsTypeString();
|
||||
|
||||
bool saveLicense(const License* license);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user