diff --git a/bin/app/data/gui/startscreen/startscreen.css b/bin/app/data/gui/startscreen/startscreen.css
index 6b3cff93..35d47fdc 100644
--- a/bin/app/data/gui/startscreen/startscreen.css
+++ b/bin/app/data/gui/startscreen/startscreen.css
@@ -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;
-}
diff --git a/bin/app/user/ApplicationSettings_template.xml b/bin/app/user/ApplicationSettings_template.xml
index cede33f6..7ad86d6a 100644
--- a/bin/app/user/ApplicationSettings_template.xml
+++ b/bin/app/user/ApplicationSettings_template.xml
@@ -97,6 +97,7 @@
+
diff --git a/src/lib/LicenseChecker.cpp b/src/lib/LicenseChecker.cpp
index 976ce5d1..322bd963 100644
--- a/src/lib/LicenseChecker.cpp
+++ b/src/lib/LicenseChecker.cpp
@@ -24,7 +24,7 @@ std::shared_ptr 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())
{
diff --git a/src/lib/LicenseChecker.h b/src/lib/LicenseChecker.h
index d16a2f88..e97cf21f 100644
--- a/src/lib/LicenseChecker.h
+++ b/src/lib/LicenseChecker.h
@@ -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 s_instance;
};
diff --git a/src/lib/settings/ApplicationSettings.cpp b/src/lib/settings/ApplicationSettings.cpp
index e343eb7b..26fb7191 100644
--- a/src/lib/settings/ApplicationSettings.cpp
+++ b/src/lib/settings/ApplicationSettings.cpp
@@ -597,6 +597,16 @@ Version ApplicationSettings::getUpdateVersion() const
return Version::fromString(getValue("user/update_check/update_version", "2017.1.0"));
}
+std::string ApplicationSettings::getUpdateNews() const
+{
+ return getValue("user/update_check/news", "");
+}
+
+void ApplicationSettings::setUpdateNews(const std::string& news)
+{
+ setValue("user/update_check/news", news);
+}
+
void ApplicationSettings::setUpdateVersion(const Version& version)
{
if (version.isValid())
diff --git a/src/lib/settings/ApplicationSettings.h b/src/lib/settings/ApplicationSettings.h
index 7ae192a8..b7283f3c 100644
--- a/src/lib/settings/ApplicationSettings.h
+++ b/src/lib/settings/ApplicationSettings.h
@@ -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);
diff --git a/src/lib_gui/CMakeLists.txt b/src/lib_gui/CMakeLists.txt
index d5ee7d39..eab2dc79 100644
--- a/src/lib_gui/CMakeLists.txt
+++ b/src/lib_gui/CMakeLists.txt
@@ -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
diff --git a/src/lib_gui/qt/element/QtNewsWidget.cpp b/src/lib_gui/qt/element/QtNewsWidget.cpp
new file mode 100644
index 00000000..dbd3f0e6
--- /dev/null
+++ b/src/lib_gui/qt/element/QtNewsWidget.cpp
@@ -0,0 +1,227 @@
+#include "QtNewsWidget.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#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": "Hello World!",
+
+ // 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);
+ }
+ }
+}
diff --git a/src/lib_gui/qt/element/QtNewsWidget.h b/src/lib_gui/qt/element/QtNewsWidget.h
new file mode 100644
index 00000000..a92d657a
--- /dev/null
+++ b/src/lib_gui/qt/element/QtNewsWidget.h
@@ -0,0 +1,33 @@
+#ifndef QT_NEWS_WIDGET_H
+#define QT_NEWS_WIDGET_H
+
+#include
+
+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
diff --git a/src/lib_gui/qt/element/QtTextEdit.cpp b/src/lib_gui/qt/element/QtTextEdit.cpp
new file mode 100644
index 00000000..1be11982
--- /dev/null
+++ b/src/lib_gui/qt/element/QtTextEdit.cpp
@@ -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);
+}
diff --git a/src/lib_gui/qt/element/QtTextEdit.h b/src/lib_gui/qt/element/QtTextEdit.h
new file mode 100644
index 00000000..a9ae8bae
--- /dev/null
+++ b/src/lib_gui/qt/element/QtTextEdit.h
@@ -0,0 +1,23 @@
+#ifndef QT_TEXT_EDIT_H
+#define QT_TEXT_EDIT_H
+
+#include
+
+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
diff --git a/src/lib_gui/qt/element/QtUpdateCheckerWidget.cpp b/src/lib_gui/qt/element/QtUpdateCheckerWidget.cpp
index 306b6220..2425e7fd 100644
--- a/src/lib_gui/qt/element/QtUpdateCheckerWidget.cpp
+++ b/src/lib_gui/qt/element/QtUpdateCheckerWidget.cpp
@@ -99,6 +99,8 @@ void QtUpdateCheckerWidget::checkUpdate(bool force)
{
setDownloadUrl(result.url);
}
+
+ emit updateReceived();
}
);
}
diff --git a/src/lib_gui/qt/element/QtUpdateCheckerWidget.h b/src/lib_gui/qt/element/QtUpdateCheckerWidget.h
index ff9db513..6c3ffdb2 100644
--- a/src/lib_gui/qt/element/QtUpdateCheckerWidget.h
+++ b/src/lib_gui/qt/element/QtUpdateCheckerWidget.h
@@ -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);
diff --git a/src/lib_gui/qt/network/QtUpdateChecker.cpp b/src/lib_gui/qt/network/QtUpdateChecker.cpp
index ed3d8a74..844522a8 100644
--- a/src/lib_gui/qt/network/QtUpdateChecker.cpp
+++ b/src/lib_gui/qt/network/QtUpdateChecker.cpp
@@ -36,27 +36,10 @@ void QtUpdateChecker::check(bool force, std::function 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 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 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 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 callback)
if (val == 1)
{
appSettings->setSkipUpdateForVersion(updateVersion);
- appSettings->save();
}
else if (val == 2)
{
@@ -163,6 +142,11 @@ void QtUpdateChecker::check(bool force, std::function callback)
}
while (false);
+ if (saveAppSettings)
+ {
+ appSettings->save();
+ }
+
request->deleteLater();
callback(result);
diff --git a/src/lib_gui/qt/window/QtStartScreen.cpp b/src/lib_gui/qt/window/QtStartScreen.cpp
index 1bcb56a2..b56f609e 100644
--- a/src/lib_gui/qt/window/QtStartScreen.cpp
+++ b/src/lib_gui/qt/window/QtStartScreen.cpp
@@ -7,17 +7,17 @@
#include
#include
+#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
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
diff --git a/src/lib_gui/utility/utilityApp.cpp b/src/lib_gui/utility/utilityApp.cpp
index ff09d610..f2c477c3 100644
--- a/src/lib_gui/utility/utilityApp.cpp
+++ b/src/lib_gui/utility/utilityApp.cpp
@@ -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)
diff --git a/src/lib_gui/utility/utilityApp.h b/src/lib_gui/utility/utilityApp.h
index 9ab8376a..9a33c03c 100644
--- a/src/lib_gui/utility/utilityApp.h
+++ b/src/lib_gui/utility/utilityApp.h
@@ -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& commandArguments,
- const FilePath& workingDirectory = FilePath(),
+ const std::wstring& commandPath,
+ const std::vector& commandArguments,
+ const FilePath& workingDirectory = FilePath(),
const int timeout = 30000
);
void killRunningProcesses();
-
int getIdealThreadCount();
OsType getOsType();
+ std::string getOsTypeString();
bool saveLicense(const License* license);
}