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:
Eberhard Graether
2018-10-21 13:49:06 +02:00
parent 518f15d490
commit 6a6bd0fca8
17 changed files with 463 additions and 102 deletions
+21 -18
View File
@@ -29,19 +29,38 @@
border-radius: 10px; border-radius: 10px;
} }
#recentLabel { #titleLabel {
color: black; color: black;
font-size: 16px; font-size: 16px;
font-weight: bold; font-weight: bold;
margin-left: 6px; margin-left: 6px;
} }
#versionLabel { #textLabel {
color: black;
font-size: 12px;
}
#boldLabel {
color: black; color: black;
font-size: 12px; font-size: 12px;
font-weight: bold; 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 { #updateButton, #upgradeButton {
margin: 1px 0 3px; margin: 1px 0 3px;
text-align: left; text-align: left;
@@ -57,19 +76,3 @@
color: black; color: black;
text-decoration: none; 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> <skip_version><!-- VERSION: version to skip for update --></skip_version>
<update_url><!-- STRING: url to new version download --></update_url> <update_url><!-- STRING: url to new version download --></update_url>
<update_version><!-- VERSION: version of last check --></update_version> <update_version><!-- VERSION: version of last check --></update_version>
<news><!-- STRING: news in last update check --></news>
</update_check> </update_check>
<seen_error_help_message><!-- BOOL: whether user has been shown help message on errors after indexing --></seen_error_help_message> <seen_error_help_message><!-- BOOL: whether user has been shown help message on errors after indexing --></seen_error_help_message>
+24 -7
View File
@@ -24,7 +24,7 @@ std::shared_ptr<LicenseChecker> LicenseChecker::getInstance()
return s_instance; return s_instance;
} }
std::string LicenseChecker::getCurrentLicenseString() const std::string LicenseChecker::getCurrentLicenseString()
{ {
License license; License license;
bool isLoaded = license.loadFromEncodedString( bool isLoaded = license.loadFromEncodedString(
@@ -38,7 +38,7 @@ std::string LicenseChecker::getCurrentLicenseString() const
return ""; return "";
} }
void LicenseChecker::saveCurrentLicenseString(const std::string& licenseString) const void LicenseChecker::saveCurrentLicenseString(const std::string& licenseString)
{ {
License license; License license;
bool isLoaded = license.loadFromString(licenseString); bool isLoaded = license.loadFromString(licenseString);
@@ -55,7 +55,7 @@ bool LicenseChecker::isCurrentLicenseValid()
return checkCurrentLicense() == LICENSE_VALID; return checkCurrentLicense() == LICENSE_VALID;
} }
LicenseChecker::LicenseState LicenseChecker::checkCurrentLicense() const LicenseChecker::LicenseState LicenseChecker::checkCurrentLicense()
{ {
ApplicationSettings* appSettings = ApplicationSettings::getInstance().get(); ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
if (appSettings == nullptr) if (appSettings == nullptr)
@@ -96,7 +96,7 @@ LicenseChecker::LicenseState LicenseChecker::checkCurrentLicense() const
return checkLicense(license); return checkLicense(license);
} }
LicenseChecker::LicenseState LicenseChecker::checkLicenseString(const std::string& licenseString) const LicenseChecker::LicenseState LicenseChecker::checkLicenseString(const std::string& licenseString)
{ {
if (licenseString.size() == 0) if (licenseString.size() == 0)
{ {
@@ -115,7 +115,7 @@ LicenseChecker::LicenseState LicenseChecker::checkLicenseString(const std::strin
return checkLicense(license); return checkLicense(license);
} }
MessageEnteredLicense::LicenseType LicenseChecker::getCurrentLicenseType() const MessageEnteredLicense::LicenseType LicenseChecker::getCurrentLicenseType()
{ {
License license; License license;
bool isLoaded = license.loadFromEncodedString( bool isLoaded = license.loadFromEncodedString(
@@ -143,7 +143,7 @@ MessageEnteredLicense::LicenseType LicenseChecker::getCurrentLicenseType() const
return MessageEnteredLicense::LICENSE_COMMERCIAL; 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) if (licenseString.size() == 0)
{ {
@@ -174,11 +174,28 @@ MessageEnteredLicense::LicenseType LicenseChecker::getLicenseType(const std::str
return MessageEnteredLicense::LICENSE_COMMERCIAL; 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::LicenseChecker()
{ {
} }
LicenseChecker::LicenseState LicenseChecker::checkLicense(License& license) const LicenseChecker::LicenseState LicenseChecker::checkLicense(License& license)
{ {
if (license.isExpired()) if (license.isExpired())
{ {
+10 -8
View File
@@ -23,22 +23,24 @@ public:
~LicenseChecker() = default; ~LicenseChecker() = default;
std::string getCurrentLicenseString() const; static std::string getCurrentLicenseString();
void saveCurrentLicenseString(const std::string& licenseString) const; static void saveCurrentLicenseString(const std::string& licenseString);
bool isCurrentLicenseValid(); static bool isCurrentLicenseValid();
LicenseState checkCurrentLicense() const; static LicenseState checkCurrentLicense();
LicenseState checkLicenseString(const std::string& licenseString) const; static LicenseState checkLicenseString(const std::string& licenseString);
MessageEnteredLicense::LicenseType getCurrentLicenseType() const; static MessageEnteredLicense::LicenseType getCurrentLicenseType();
MessageEnteredLicense::LicenseType getLicenseType(const std::string& licenseString) const; static MessageEnteredLicense::LicenseType getLicenseType(const std::string& licenseString);
static std::string getCurrentLicenseTypeString();
private: private:
LicenseChecker(); LicenseChecker();
LicenseChecker(const LicenseChecker&) = delete; LicenseChecker(const LicenseChecker&) = delete;
void operator=(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; static std::shared_ptr<LicenseChecker> s_instance;
}; };
+10
View File
@@ -597,6 +597,16 @@ Version ApplicationSettings::getUpdateVersion() const
return Version::fromString(getValue<std::string>("user/update_check/update_version", "2017.1.0")); 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) void ApplicationSettings::setUpdateVersion(const Version& version)
{ {
if (version.isValid()) if (version.isValid())
+3
View File
@@ -167,6 +167,9 @@ public:
Version getUpdateVersion() const; Version getUpdateVersion() const;
void setUpdateVersion(const Version& version); void setUpdateVersion(const Version& version);
std::string getUpdateNews() const;
void setUpdateNews(const std::string& news);
bool getSeenErrorHelpMessage() const; bool getSeenErrorHelpMessage() const;
void setSeenErrorHelpMessage(bool seen); void setSeenErrorHelpMessage(bool seen);
+4
View File
@@ -45,6 +45,8 @@ add_files(
qt/element/QtListBoxItem.h qt/element/QtListBoxItem.h
qt/element/QtLocationPicker.cpp qt/element/QtLocationPicker.cpp
qt/element/QtLocationPicker.h qt/element/QtLocationPicker.h
qt/element/QtNewsWidget.cpp
qt/element/QtNewsWidget.h
qt/element/QtPathListBox.cpp qt/element/QtPathListBox.cpp
qt/element/QtPathListBox.h qt/element/QtPathListBox.h
qt/element/QtPathListBoxItem.cpp qt/element/QtPathListBoxItem.cpp
@@ -67,6 +69,8 @@ add_files(
qt/element/QtStatusBar.h qt/element/QtStatusBar.h
qt/element/QtTable.cpp qt/element/QtTable.cpp
qt/element/QtTable.h qt/element/QtTable.h
qt/element/QtTextEdit.cpp
qt/element/QtTextEdit.h
qt/element/QtTooltip.cpp qt/element/QtTooltip.cpp
qt/element/QtTooltip.h qt/element/QtTooltip.h
qt/element/QtUndoRedo.cpp qt/element/QtUndoRedo.cpp
+227
View File
@@ -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);
}
}
}
+33
View File
@@ -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
+18
View File
@@ -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);
}
+23
View File
@@ -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); setDownloadUrl(result.url);
} }
emit updateReceived();
} }
); );
} }
@@ -10,10 +10,15 @@ class QPushButton;
class QtUpdateCheckerWidget class QtUpdateCheckerWidget
: public QWidget : public QWidget
{ {
Q_OBJECT
public: public:
QtUpdateCheckerWidget(QWidget* parent = nullptr); QtUpdateCheckerWidget(QWidget* parent = nullptr);
virtual ~QtUpdateCheckerWidget(); virtual ~QtUpdateCheckerWidget();
signals:
void updateReceived();
private: private:
void checkUpdate(bool force); void checkUpdate(bool force);
void setDownloadUrl(QString url); void setDownloadUrl(QString url);
+24 -40
View File
@@ -36,27 +36,10 @@ void QtUpdateChecker::check(bool force, std::function<void(Result)> callback)
appSettings->setUpdateDownloadUrl(""); appSettings->setUpdateDownloadUrl("");
appSettings->save(); appSettings->save();
QString urlString = "https://www.sourcetrail.com/api/v1/versions/latest"; QString urlString = "https://www.sourcetrail.com/api/v2/versions/latest";
// OS // OS
std::string osString; std::string osString = utility::getOsTypeString();
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;
}
urlString += ("?os=" + osString).c_str(); urlString += ("?os=" + osString).c_str();
// architecture // architecture
@@ -68,21 +51,7 @@ void QtUpdateChecker::check(bool force, std::function<void(Result)> callback)
urlString += ("&version=" + Version::getApplicationVersion().toDisplayString()).c_str(); urlString += ("&version=" + Version::getApplicationVersion().toDisplayString()).c_str();
// license // license
std::string licenseString; std::string licenseString = LicenseChecker::getCurrentLicenseTypeString();
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;
}
urlString += ("&license=" + licenseString).c_str(); urlString += ("&license=" + licenseString).c_str();
// user token // user token
@@ -103,15 +72,27 @@ void QtUpdateChecker::check(bool force, std::function<void(Result)> callback)
{ {
Result result; Result result;
ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
bool saveAppSettings = false;
do do
{ {
QJsonDocument doc = QJsonDocument::fromJson(bytes); QJsonParseError error;
if (!doc.isObject()) 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; 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 version = doc.object().find("version")->toString();
QString url = doc.object().find("url")->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.version = updateVersion;
result.url = url; result.url = url;
ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
appSettings->setUpdateVersion(updateVersion); appSettings->setUpdateVersion(updateVersion);
appSettings->setUpdateDownloadUrl(url.toStdString()); appSettings->setUpdateDownloadUrl(url.toStdString());
appSettings->save(); saveAppSettings = true;
if (!force && appSettings->getSkipUpdateForVersion() == updateVersion) if (!force && appSettings->getSkipUpdateForVersion() == updateVersion)
{ {
@@ -153,7 +133,6 @@ void QtUpdateChecker::check(bool force, std::function<void(Result)> callback)
if (val == 1) if (val == 1)
{ {
appSettings->setSkipUpdateForVersion(updateVersion); appSettings->setSkipUpdateForVersion(updateVersion);
appSettings->save();
} }
else if (val == 2) else if (val == 2)
{ {
@@ -163,6 +142,11 @@ void QtUpdateChecker::check(bool force, std::function<void(Result)> callback)
} }
while (false); while (false);
if (saveAppSettings)
{
appSettings->save();
}
request->deleteLater(); request->deleteLater();
callback(result); callback(result);
+32 -20
View File
@@ -7,17 +7,17 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QMessageBox> #include <QMessageBox>
#include "ApplicationSettings.h"
#include "AppPath.h" #include "AppPath.h"
#include "MessageLoadProject.h"
#include "ResourcePaths.h"
#include "Version.h"
#include "License.h" #include "License.h"
#include "MessageLoadProject.h"
#include "ProjectSettings.h"
#include "PublicKey.h" #include "PublicKey.h"
#include "QtUpdateCheckerWidget.h" #include "QtUpdateCheckerWidget.h"
#include "QtNewsWidget.h"
#include "ResourcePaths.h"
#include "utilityQt.h" #include "utilityQt.h"
#include "ApplicationSettings.h" #include "Version.h"
#include "ProjectSettings.h"
QtRecentProjectButton::QtRecentProjectButton(QWidget* parent) QtRecentProjectButton::QtRecentProjectButton(QWidget* parent)
: QPushButton(parent) : QPushButton(parent)
@@ -93,7 +93,7 @@ QtStartScreen::QtStartScreen(QWidget *parent)
QSize QtStartScreen::sizeHint() const QSize QtStartScreen::sizeHint() const
{ {
return QSize(570, 600); return QSize(570, 630);
} }
void QtStartScreen::updateButtons() void QtStartScreen::updateButtons()
@@ -153,39 +153,39 @@ void QtStartScreen::setupStartScreen()
addLogo(); addLogo();
QHBoxLayout* layout = new QHBoxLayout(); QHBoxLayout* layout = new QHBoxLayout();
layout->setContentsMargins(15, 170, 15, 10); layout->setContentsMargins(15, 170, 15, 0);
layout->setSpacing(1); layout->setSpacing(1);
m_content->setLayout(layout); m_content->setLayout(layout);
{ {
QVBoxLayout* col = new QVBoxLayout(); QVBoxLayout* col = new QVBoxLayout();
layout->addLayout(col, 2); layout->addLayout(col, 3);
QLabel* versionLabel = new QLabel(("Version " + Version::getApplicationVersion().toDisplayString()).c_str(), this); QLabel* versionLabel = new QLabel(("Version " + Version::getApplicationVersion().toDisplayString()).c_str(), this);
versionLabel->setObjectName("versionLabel"); versionLabel->setObjectName("boldLabel");
col->addWidget(versionLabel); col->addWidget(versionLabel);
QtUpdateCheckerWidget* checker = new QtUpdateCheckerWidget(this); QtUpdateCheckerWidget* checker = new QtUpdateCheckerWidget(this);
col->addWidget(checker); col->addWidget(checker);
col->addSpacing(30); col->addSpacing(15);
if (license.isValid()) if (license.isValid())
{ {
std::string licenseString = license.getLicenseInfo(); std::string licenseString = license.getLicenseInfo();
QLabel* licenseHeader = new QLabel("Licensed to:"); QLabel* licenseHeader = new QLabel("Licensed to:");
licenseHeader->setObjectName("licenseHeaderLabel"); licenseHeader->setObjectName("boldLabel");
col->addWidget(licenseHeader); col->addWidget(licenseHeader);
col->addSpacing(2); col->addSpacing(2);
QLabel* licenseLabel = new QLabel(licenseString.c_str()); QLabel* licenseLabel = new QLabel(licenseString.c_str());
licenseLabel->setObjectName("licenseLabel"); licenseLabel->setObjectName("textLabel");
col->addWidget(licenseLabel); col->addWidget(licenseLabel);
} }
else else
{ {
QLabel* licenseHeader = new QLabel("Not licensed for<br />commercial use."); QLabel* licenseHeader = new QLabel("Not licensed for<br />commercial use.");
licenseHeader->setObjectName("licenseHeaderLabel"); licenseHeader->setObjectName("boldLabel");
col->addWidget(licenseHeader); col->addWidget(licenseHeader);
QPushButton* upgradeButton = new QPushButton("upgrade"); QPushButton* upgradeButton = new QPushButton("upgrade");
@@ -195,6 +195,20 @@ void QtStartScreen::setupStartScreen()
connect(upgradeButton, &QPushButton::clicked, [this](){ emit openEnterLicenseDialog(); }); 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(); col->addStretch();
QPushButton* newProjectButton = new QPushButton("New Project", this); QPushButton* newProjectButton = new QPushButton("New Project", this);
@@ -212,23 +226,21 @@ void QtStartScreen::setupStartScreen()
openProjectButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); openProjectButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
connect(openProjectButton, &QPushButton::clicked, this, &QtStartScreen::handleOpenProjectButton); connect(openProjectButton, &QPushButton::clicked, this, &QtStartScreen::handleOpenProjectButton);
col->addWidget(openProjectButton); col->addWidget(openProjectButton);
layout->addStretch(2);
} }
layout->addSpacing(50);
{ {
QVBoxLayout* col = new QVBoxLayout(); QVBoxLayout* col = new QVBoxLayout();
layout->addLayout(col, 1); layout->addLayout(col, 1);
QLabel* recentProjectsLabel = new QLabel("Recent Projects: ", this); QLabel* recentProjectsLabel = new QLabel("Recent Projects: ", this);
recentProjectsLabel->setObjectName("recentLabel"); recentProjectsLabel->setObjectName("titleLabel");
col->addWidget(recentProjectsLabel); col->addWidget(recentProjectsLabel);
col->addSpacing(20); col->addSpacing(20);
for (int i = 0 for (int i = 0; i < ApplicationSettings::getInstance()->getMaxRecentProjectsCount(); i++)
; i < ApplicationSettings::getInstance()->getMaxRecentProjectsCount()
; i++)
{ {
QtRecentProjectButton* button = new QtRecentProjectButton(this); QtRecentProjectButton* button = new QtRecentProjectButton(this);
button->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac button->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
+22 -5
View File
@@ -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() OsType utility::getOsType()
{ {
if (QSysInfo::windowsVersion() != QSysInfo::WV_None) if (QSysInfo::windowsVersion() != QSysInfo::WV_None)
@@ -154,14 +164,21 @@ OsType utility::getOsType()
return OS_UNKNOWN; return OS_UNKNOWN;
} }
int utility::getIdealThreadCount() std::string utility::getOsTypeString()
{ {
int threadCount = QThread::idealThreadCount(); // WARNING: Don't change these string. The server API relies on them.
if (getOsType() == OS_WINDOWS) 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) bool utility::saveLicense(const License* license)
+1 -1
View File
@@ -22,10 +22,10 @@ namespace utility
); );
void killRunningProcesses(); void killRunningProcesses();
int getIdealThreadCount(); int getIdealThreadCount();
OsType getOsType(); OsType getOsType();
std::string getOsTypeString();
bool saveLicense(const License* license); bool saveLicense(const License* license);
} }