Release v1.14.5 (#7219)

* Update Version.cmake

* Add TLS to Synergy (Lite edition) (#7202)

* Add TLS to synergy light

* Requested changes

* License registration for Business edition (#7203)

* License registration for business

* Rename register to registry

* Add email into the request

* Add decoded serial key into the request

* Revert "Add decoded serial key into the request"

This reverts commit 0e18c8941664e86ae2264bbef072df68cab07751.

* Revert "Add email into the request"

This reverts commit 8dff01bc242769008897947d66187cb726fb34bf.

* Change field guid_generated to guid_type

* Update ChangeLog

* Update ChangeLog

* Fix build issue for ubuntu16 and ubuntu18 (#7204)

* Fix issue with settings

* Custom about screen for Elite Backers (#7211)

* Hide irrelevant information from the About screen for B2B

* Fix size for Windows and Linux

* Requested changes

* Fix Enterprise

* Revert "Fix Enterprise"

This reverts commit befd8d2ce36b6ca903250bada62293491f0b56a2.

* Revert "Requested changes"

This reverts commit 5f728e00aaeb4bed3e3c006539d380f74d3aff76.

* Change features based on edition (#7212)

* Change features based on edition

* Fix enterprise build

* Update window titles and about screen (#7214)

* Fix About screen for Business edition

* Change dialog title

* Refactored upgrade prompt for TLS and hotkeys (#7215)

* Prompt Basic users to upgrade to Pro to access TLS encryption

* Fixed Enterprise build

* Fix code smells

* Fix sonar bug
This commit is contained in:
Serhii Hadzhilov 2022-09-13 18:31:45 +03:00 committed by GitHub
parent a0560e5d87
commit 452c631d6e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 525 additions and 90 deletions

View file

@ -10,6 +10,7 @@ Enhancements:
- #7190 Maintenance license serial key support
- #7193 Support for maintenance licenses in China
- #7197 Special contributor mentions on the about screen
- #7203 License registration for Business edition
Github Actions:
- #7210 Update macos workflow to use macos-latest

View file

@ -8,7 +8,7 @@ set (SYNERGY_VERSION_MAJOR 1)
set (SYNERGY_VERSION_MINOR 14)
set (SYNERGY_VERSION_PATCH 5)
set (SYNERGY_VERSION_BUILD 1)
set (SYNERGY_VERSION_STAGE "snapshot")
set (SYNERGY_VERSION_STAGE "stable")
#
# Version from CI

View file

@ -16,80 +16,77 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AboutDialog.h"
#include "CreditsLoader.h"
#include <QtCore>
#include <QtGui>
#include "OSXHelpers.h"
#include "AboutDialog.h"
AboutDialog::AboutDialog(MainWindow* parent, const AppConfig& config) :
QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
Ui::AboutDialogBase(),
credits(*parent, config)
QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
Ui::AboutDialogBase()
{
setupUi(this);
setupCreditsLoader();
setupUi(this);
QString aboutText(R"(<p>
Keyboard and mouse sharing application. Cross platform and open source since 2001.<br /><br />
Copyright © %%YEAR%% Symless Ltd.<br /><br />
Synergy is released under the GNU General Public License (GPLv2).</p>
<p style="font-size: 14px">Key contributors<br>
<span style="font-size: 11px">Chris Schoeneman, Nick Bolton, Richard Lee, Adam Feder, Volker Lanz,
Ryan Breen, Guido Poschta, Bertrand Landry Hetu, Tom Chadwick, Brent Priddy, Kyle Bloom,
Daun Chung, Serhii Hadzhylov, Oleksandr Lysytsia, Olena Kutytska, Francisco Magalhães.</span>
</p>)");
m_versionChecker.setApp(parent->appPath(config.synergycName()));
QString version = m_versionChecker.getVersion();
m_versionChecker.setApp(parent->appPath(config.synergycName()));
QString version = m_versionChecker.getVersion();
#ifdef SYNERGY_REVISION
version += '-';
version += SYNERGY_REVISION;
#endif
m_pLabelSynergyVersion->setText(version);
m_pLabelSynergyVersion->setText(version);
QString buildDateString = QString::fromLocal8Bit(__DATE__).simplified();
QDate buildDate = QLocale("en_US").toDate(buildDateString, "MMM d yyyy");
m_pLabelBuildDate->setText(buildDate.toString(Qt::SystemLocaleLongDate));
QString buildDateString = QString::fromLocal8Bit(__DATE__).simplified();
QDate buildDate = QLocale("en_US").toDate(buildDateString, "MMM d yyyy");
m_pLabelBuildDate->setText(buildDate.toString(Qt::SystemLocaleLongDate));
//Sets the current build year into the copyright text
label_3->setText(aboutText.replace(QString("%%YEAR%%"), QString::number(buildDate.year())));
textEliteBackers->hide();
labelEliteBackers->hide();
labelEliteBackerLink->hide();
labelCreditsLink->hide();
}
// change default size based on os
int AboutDialog::exec()
{
//Sets the current build year into the copyright text
label_3->setText(getCopyrights() + getKeyContributors());
resizeWindow();
updateLogo();
return QDialog::exec();
}
void AboutDialog::resizeWindow()
{
QSize size(600, 310);
setMaximumSize(size);
setMinimumSize(size);
resize(size);
}
void AboutDialog::updateLogo() const
{
#if defined(Q_OS_MAC)
QSize size(600, 490);
setMaximumSize(size);
setMinimumSize(size);
resize(size);
if (isOSXInterfaceStyleDark()) {
QPixmap logo(":/res/image/about-dark.png");
if (!logo.isNull()) {
label_Logo->setPixmap(logo);
}
}
#elif defined(Q_OS_LINUX)
QSize size(600, 420);
setMaximumSize(size);
setMinimumSize(size);
resize(size);
#endif
}
void AboutDialog::setupCreditsLoader()
QString AboutDialog::getKeyContributors() const
{
this->textEliteBackers->setText("Loading...");
this->textEliteBackers->viewport()->setAutoFillBackground(false);
this->textEliteBackers->document()->setDocumentMargin(0);
connect(&credits, SIGNAL(loaded(const QString&)), this, SLOT(updateEliteBackers(const QString&)));
credits.loadEliteBackers();
return QString(R"(<p style="font-size: 14px">Key contributors<br>
<span style="font-size: 11px">Chris Schoeneman, Nick Bolton, Richard Lee, Adam Feder, Volker Lanz,
Ryan Breen, Guido Poschta, Bertrand Landry Hetu, Tom Chadwick, Brent Priddy, Kyle Bloom,
Daun Chung, Serhii Hadzhylov, Oleksandr Lysytsia, Olena Kutytska, Francisco Magalhães.</span>
</p>)");
}
void AboutDialog::updateEliteBackers(const QString& eliteBackers) const
QString AboutDialog::getCopyrights() const
{
this->textEliteBackers->setText(eliteBackers);
QString buildDateString = QString::fromLocal8Bit(__DATE__).simplified();
QDate buildDate = QLocale("en_US").toDate(buildDateString, "MMM d yyyy");
QString copyrights(R"(<p>Keyboard and mouse sharing application.<br /><br />Copyright © %%YEAR%% Symless Ltd.</p>)");
return copyrights.replace(QString("%%YEAR%%"), QString::number(buildDate.year()));
}

View file

@ -22,7 +22,6 @@
#include <QDialog>
#include "VersionChecker.h"
#include "CreditsLoader.h"
#include "MainWindow.h"
#include "ui_AboutDialogBase.h"
@ -30,20 +29,18 @@
class QWidget;
class QString;
class AboutDialog : public QDialog, public Ui::AboutDialogBase
{
class AboutDialog : public QDialog, public Ui::AboutDialogBase {
Q_OBJECT
public:
AboutDialog(MainWindow* parent, const AppConfig& config);
int exec() override;
private:
VersionChecker m_versionChecker;
void updateLogo() const;
public:
AboutDialog(MainWindow* parent, const AppConfig& config);
public slots:
void updateEliteBackers(const QString& eliteBackers) const;
private:
CreditsLoader credits;
VersionChecker m_versionChecker;
void setupCreditsLoader();
virtual void resizeWindow();
virtual QString getCopyrights() const;
virtual QString getKeyContributors() const;
};
#endif

View file

@ -0,0 +1,73 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2022 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CreditsLoader.h"
#include "AboutDialogEliteBackers.h"
AboutDialogEliteBackers::AboutDialogEliteBackers(MainWindow* parent, const AppConfig& config) :
AboutDialog(parent, config),
credits(*parent, config)
{
setupCreditsLoader();
textEliteBackers->show();
labelEliteBackers->show();
labelEliteBackerLink->show();
labelCreditsLink->show();
}
void AboutDialogEliteBackers::setupCreditsLoader()
{
this->textEliteBackers->setText("Loading...");
this->textEliteBackers->viewport()->setAutoFillBackground(false);
this->textEliteBackers->document()->setDocumentMargin(0);
connect(&credits, SIGNAL(loaded(const QString&)), this, SLOT(updateEliteBackers(const QString&)));
credits.loadEliteBackers();
}
void AboutDialogEliteBackers::updateEliteBackers(const QString& eliteBackers) const
{
this->textEliteBackers->setText(eliteBackers);
}
QString AboutDialogEliteBackers::getCopyrights() const
{
QString buildDateString = QString::fromLocal8Bit(__DATE__).simplified();
QDate buildDate = QLocale("en_US").toDate(buildDateString, "MMM d yyyy");
QString aboutText(R"(<p>Keyboard and mouse sharing application. Cross platform and open source since 2001.<br /><br />
Copyright © %%YEAR%% Symless Ltd.<br /><br />
Synergy is released under the GNU General Public License (GPLv2).</p>)");
return aboutText.replace(QString("%%YEAR%%"), QString::number(buildDate.year()));
}
void AboutDialogEliteBackers::resizeWindow()
{
// change default size based on os
#if defined(Q_OS_MAC)
QSize size(600, 490);
setMaximumSize(size);
setMinimumSize(size);
resize(size);
#elif defined(Q_OS_LINUX)
QSize size(600, 420);
setMaximumSize(size);
setMinimumSize(size);
resize(size);
#endif
}

View file

@ -0,0 +1,36 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2022 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "CreditsLoader.h"
#include "AboutDialog.h"
class AboutDialogEliteBackers : public AboutDialog {
Q_OBJECT
public:
AboutDialogEliteBackers(MainWindow* parent, const AppConfig& config);
public slots:
void updateEliteBackers(const QString& eliteBackers) const;
private:
CreditsLoader credits;
void setupCreditsLoader();
void resizeWindow() override;
QString getCopyrights() const override;
};

View file

@ -85,7 +85,7 @@ void ActivationDialog::accept()
arg ((daysLeft == 1) ? "" : "s").
arg ((daysLeft == 1) ? "s" : "");
if (edition == kPro || edition == kPro_China || edition == kBusiness) {
if (m_appConfig->isCryptoAvailable()) {
m_appConfig->generateCertificate();
thanksMessage = thanksMessage.arg("If you're using SSL, "
"remember to activate all of your devices.");

View file

@ -80,7 +80,10 @@ const char* AppConfig::m_SynergySettingsName[] = {
"preventSleep",
"languageSync",
"invertScrollDirection",
"eliteBackersUrl"
"eliteBackersUrl",
"guid",
"licenseRegistryUrl",
"licenseNextCheck"
};
static const char* logLevelNames[] =
@ -247,6 +250,9 @@ void AppConfig::loadSettings()
m_LanguageSync = loadSetting(kLanguageSync, false).toBool();
m_InvertScrollDirection = loadSetting(kInvertScrollDirection, false).toBool();
m_eliteBackersUrl = loadCommonSetting(kEliteBackersUrl, "https://api2.prod.symless.com/credits/elite-backers").toString();
m_guid = loadCommonSetting(kGuid, QUuid::createUuid()).toString();
m_licenseRegistryUrl = loadCommonSetting(kLicenseRegistryUrl, "https://api2.prod.symless.com/license/register").toString();
m_licenseNextCheck = loadCommonSetting(kLicenseNextCheck, 0).toULongLong();
//only change the serial key if the settings being loaded contains a key
bool updateSerial = ConfigWriter::make()
@ -280,6 +286,9 @@ void AppConfig::saveSettings()
setCommonSetting(kGroupClientCheck, m_ClientGroupChecked);
setCommonSetting(kGroupServerCheck, m_ServerGroupChecked);
setCommonSetting(kEliteBackersUrl, m_eliteBackersUrl);
setCommonSetting(kGuid, m_guid);
setCommonSetting(kLicenseRegistryUrl, m_licenseRegistryUrl);
setCommonSetting(kLicenseNextCheck, m_licenseNextCheck);
if (isWritable()) {
setSetting(kScreenName, m_ScreenName);
@ -408,7 +417,7 @@ void AppConfig::clearSerialKey()
m_Serialkey.clear();
}
QString AppConfig::serialKey() { return m_Serialkey; }
QString AppConfig::serialKey() const { return m_Serialkey; }
int AppConfig::lastExpiringWarningTime() const { return m_LastExpiringWarningTime; }
@ -439,8 +448,11 @@ void AppConfig::setCryptoEnabled(bool newValue) {
bool AppConfig::isCryptoAvailable() const {
bool result {true};
#ifndef SYNERGY_ENTERPRISE
result = (edition() == kPro || edition() == kPro_China || edition() == kBusiness);
#if !defined(SYNERGY_ENTERPRISE) && !defined(SYNERGY_BUSINESS)
result = (edition() == kPro ||
edition() == kPro_China ||
edition() == kBusiness ||
edition() == kUltimate);
#endif
return result;
@ -468,10 +480,26 @@ void AppConfig::setEliteBackersUrl(const QString& newValue) {
setSettingModified(m_eliteBackersUrl, newValue);
}
void AppConfig::setLicenseNextCheck(unsigned long long time) {
setSettingModified(m_licenseNextCheck, time);
}
const QString& AppConfig::getEliteBackersUrl() const {
return m_eliteBackersUrl;
}
const QString& AppConfig::getLicenseRegistryUrl() const {
return m_licenseRegistryUrl;
}
unsigned long long AppConfig::getLicenseNextCheck() const {
return m_licenseNextCheck;
}
const QString& AppConfig::getGuid() const {
return m_guid;
}
bool AppConfig::getLanguageSync() const { return m_LanguageSync; }
void AppConfig::setInvertScrollDirection(bool newValue) {

View file

@ -50,6 +50,7 @@ const int kWizardVersion = 8;
class QSettings;
class SettingsDialog;
class ServerConfig;
class LicenseRegister;
enum ProcessMode {
Service,
@ -93,7 +94,7 @@ class AppConfig: public QObject, public GUI::Config::ConfigBase
Edition edition() const;
void setSerialKey(const QString& serial);
void clearSerialKey();
QString serialKey();
QString serialKey() const;
int lastExpiringWarningTime() const;
void setLastExpiringWarningTime(int t);
#endif
@ -115,7 +116,11 @@ class AppConfig: public QObject, public GUI::Config::ConfigBase
void setInvertScrollDirection(bool b);
bool getInvertScrollDirection() const;
void setEliteBackersUrl(const QString&);
void setLicenseNextCheck(unsigned long long);
const QString& getEliteBackersUrl() const;
const QString& getLicenseRegistryUrl() const;
unsigned long long getLicenseNextCheck() const;
const QString& getGuid() const;
void setLanguageSync(bool b);
bool getLanguageSync() const;
void setPreventSleep(bool b);
@ -211,7 +216,10 @@ protected:
kPreventSleep,
kLanguageSync,
kInvertScrollDirection,
kEliteBackersUrl
kEliteBackersUrl,
kGuid,
kLicenseRegistryUrl,
kLicenseNextCheck
};
void setScreenName(const QString& s);
@ -252,6 +260,9 @@ protected:
QString m_Serialkey;
QString m_lastVersion;
QString m_eliteBackersUrl;
QString m_guid;
QString m_licenseRegistryUrl;
unsigned long long m_licenseNextCheck;
int m_LastExpiringWarningTime;
bool m_ActivationHasRun;
bool m_MinimizeToTray;

View file

@ -66,7 +66,8 @@ checkSerialKey(const SerialKey& serialKey, bool acceptExpired)
LicenseManager::LicenseManager(AppConfig* appConfig) :
m_AppConfig(appConfig),
m_serialKey(appConfig->edition()) {
m_serialKey(appConfig->edition()),
m_registry(*appConfig) {
}
void
@ -82,6 +83,7 @@ LicenseManager::setSerialKey(SerialKey serialKey, bool acceptExpired)
emit showLicenseNotice(getLicenseNotice());
validateSerialKey();
m_registry.scheduleRegistration();
if (m_serialKey.edition() != serialKey.edition()) {
m_AppConfig->setEdition(m_serialKey.edition());
@ -201,6 +203,12 @@ LicenseManager::getLicenseNotice() const
return Notice;
}
void
LicenseManager::registerLicense()
{
m_registry.registerLicense();
}
QString
LicenseManager::getTrialNotice() const
{

View file

@ -23,6 +23,8 @@
#include <ActivationNotifier.h>
#include <utility>
#include "LicenseRegistry.h"
class AppConfig;
class LicenseManager: public QObject
@ -45,9 +47,11 @@ public:
private:
AppConfig* m_AppConfig;
SerialKey m_serialKey;
LicenseRegistry m_registry;
public slots:
void validateSerialKey() const;
void registerLicense();
signals:
void editionChanged (Edition) const;

View file

@ -0,0 +1,105 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2022 Synergy Seamless Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QNetworkReply>
#include <QJsonObject>
#include <QJsonDocument>
#include <QTimer>
#include "LicenseRegistry.h"
#include "AppConfig.h"
#include <QSysInfo>
LicenseRegistry::LicenseRegistry(AppConfig& config) :
m_config(config)
{
connect(&m_timer, SIGNAL(timeout()), this, SLOT(registerLicense()));
}
void LicenseRegistry::registerLicense()
{
m_timer.stop();
if (m_config.edition() == Edition::kBusiness) {
const auto REGISTER_LICENSE_URL = m_config.getLicenseRegistryUrl();
const auto url = QUrl(REGISTER_LICENSE_URL);
auto request = QNetworkRequest(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
m_manager.post(request, getRequestData());
connect(&m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(handleResponse(QNetworkReply*)));
}
}
void LicenseRegistry::handleResponse(QNetworkReply *reply)
{
if (reply) {
const auto HOUR = (60*60); //seconds per hour
const auto DAY = (24*HOUR);//seconds per day
const auto WEEK = (7*DAY); //seconds per week
const auto currentTimestamp = time(nullptr);
if(reply->error() == QNetworkReply::NoError) {
m_config.setLicenseNextCheck(currentTimestamp + WEEK);
}
else{
m_config.setLicenseNextCheck(currentTimestamp + HOUR);
}
scheduleRegistration();
reply->deleteLater();
}
}
QByteArray LicenseRegistry::getRequestData() const
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
QString guid(QSysInfo::machineUniqueId());
#else
QString guid;
#endif
QJsonObject data;
if (!guid.isEmpty()) {
data["guid"] = guid;
data["guid_type"] = "system";
}
else {
data["guid"] = m_config.getGuid();
data["guid_type"] = "synergy";
}
data["key"] = m_config.serialKey();
data["is_server"] = m_config.getServerGroupChecked();
return QJsonDocument(data).toJson();
}
void LicenseRegistry::scheduleRegistration()
{
const auto nextCheck = m_config.getLicenseNextCheck();
const auto currentTimestamp = static_cast<unsigned long long>(time(nullptr));
if (currentTimestamp >= nextCheck) {
registerLicense();
}
else {
const auto interval = (nextCheck - currentTimestamp) * 1000; //interval in milliseconds
m_timer.setInterval(static_cast<int>(interval));
m_timer.setSingleShot(true);
m_timer.start();
}
}

View file

@ -0,0 +1,44 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2022 Synergy Seamless Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QObject>
#include <QTimer>
#include <QNetworkAccessManager>
class QNetworkReply;
class AppConfig;
class LicenseRegistry : public QObject
{
Q_OBJECT
public:
explicit LicenseRegistry(AppConfig& config);
void scheduleRegistration();
public slots:
void registerLicense();
void handleResponse(QNetworkReply *reply);
private:
AppConfig& m_config;
QNetworkAccessManager m_manager;
QTimer m_timer;
QByteArray getRequestData() const;
};

View file

@ -25,6 +25,7 @@
#include "Fingerprint.h"
#include "AboutDialog.h"
#include "AboutDialogEliteBackers.h"
#include "ServerConfigDialog.h"
#include "SettingsDialog.h"
#include "ActivationDialog.h"
@ -646,6 +647,7 @@ void MainWindow::startSynergy()
return;
}
}
m_LicenseManager->registerLicense();
#endif
bool desktopMode = appConfig().processMode() == Desktop;
bool serviceMode = appConfig().processMode() == Service;
@ -1265,8 +1267,19 @@ bool MainWindow::on_m_pActionSave_triggered()
void MainWindow::on_m_pActionAbout_triggered()
{
#if defined(SYNERGY_ENTERPRISE) || defined(SYNERGY_BUSINESS)
AboutDialog dlg(this, appConfig());
dlg.exec();
#else
if (appConfig().edition() == Edition::kBusiness) {
AboutDialog dlg(this, appConfig());
dlg.exec();
}
else {
AboutDialogEliteBackers dlg(this, appConfig());
dlg.exec();
}
#endif
}
void MainWindow::on_m_pActionHelp_triggered()

View file

@ -56,12 +56,16 @@ ServerConfig::ServerConfig(int numColumns, int numRows, AppConfig* appConfig, Ma
m_pMainWindow(mainWindow)
{
GUI::Config::ConfigWriter::make()->registerClass(this);
loadSettings();
ServerConfig::loadSettings();
}
ServerConfig::~ServerConfig()
{
saveSettings();
try {
ServerConfig::saveSettings();
} catch (const std::exception& e) {
m_pMainWindow->appendLogError(e.what());
}
}
bool ServerConfig::save(const QString& fileName) const
@ -555,3 +559,11 @@ QSettings &ServerConfig::settings() {
return ConfigWriter::make()->settings();
}
bool ServerConfig::isHotkeysAvailable() const {
#ifndef SYNERGY_ENTERPRISE
return (m_pAppConfig->edition() != Edition::kLite);
#else
return true;
#endif
}

View file

@ -88,6 +88,7 @@ class ServerConfig : public BaseConfig, public GUI::Config::ConfigBase
bool isFull() const;
bool isScreenExists(const QString& screenName) const;
void addClient(const QString& clientName);
bool isHotkeysAvailable() const;
protected:
QSettings& settings();

View file

@ -21,6 +21,7 @@
#include "ServerConfig.h"
#include "HotkeyDialog.h"
#include "ActionDialog.h"
#include "UpgradeDialog.h"
#include <QtCore>
#include <QtGui>
@ -186,12 +187,21 @@ void ServerConfigDialog::reject()
void ServerConfigDialog::on_m_pButtonNewHotkey_clicked()
{
Hotkey hotkey;
HotkeyDialog dlg(this, hotkey);
if (dlg.exec() == QDialog::Accepted) {
serverConfig().hotkeys().append(hotkey);
m_pListHotkeys->addItem(hotkey.text());
onChange();
if (serverConfig().isHotkeysAvailable()) {
Hotkey hotkey;
HotkeyDialog dlg(this, hotkey);
if (dlg.exec() == QDialog::Accepted) {
serverConfig().hotkeys().append(hotkey);
m_pListHotkeys->addItem(hotkey.text());
onChange();
}
}
else {
UpgradeDialog upgradeDialog(this);
upgradeDialog.showDialog(
"Configuring custom hotkeys is a Synergy Ultimate feature.",
"synergy/purchase/purchase-ultimate-upgrade?source=gui"
);
}
}

View file

@ -27,6 +27,7 @@
#include "MainWindow.h"
#include "BonjourWindows.h"
#include "Zeroconf.h"
#include "UpgradeDialog.h"
#include <QtCore>
#include <QtGui>
@ -264,16 +265,23 @@ void SettingsDialog::on_m_pCheckBoxEnableCrypto_clicked(bool checked)
else
{
m_pCheckBoxEnableCrypto->setChecked(false);
QMessageBox message(this);
message.addButton(QObject::tr("Close"), QMessageBox::RejectRole);
message.addButton(QObject::tr("Upgrade"), QMessageBox::AcceptRole);
message.setText(QObject::tr("TLS encryption is Synergy Pro feature.\nPlease upgrade if this is important to you"));
if (message.exec() == QMessageBox::Accepted)
#if !defined(SYNERGY_ENTERPRISE) && !defined(SYNERGY_BUSINESS)
UpgradeDialog upgradeDialog(this);
if (appConfig().edition() == Edition::kLite)
{
QDesktopServices::openUrl(QUrl(QCoreApplication::organizationDomain() + "synergy/purchase/upgrade"));
upgradeDialog.showDialog(
"TLS encryption is a Synergy Ultimate feature.",
"synergy/purchase/purchase-ultimate-upgrade?source=gui"
);
}
else
{
upgradeDialog.showDialog(
"TLS encryption is a Synergy Pro feature.",
"synergy/purchase/upgrade?source=gui"
);
}
#endif
}
}

View file

@ -0,0 +1,38 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2022 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "UpgradeDialog.h"
#include <QtCore>
#include <QtGui>
UpgradeDialog::UpgradeDialog(QWidget* parent) :
QMessageBox(parent)
{
setWindowTitle(QObject::tr("Upgrade to access this feature"));
addButton(QObject::tr("Close"), QMessageBox::RejectRole);
addButton(QObject::tr("Upgrade"), QMessageBox::AcceptRole);
}
void UpgradeDialog::showDialog(const QString& text, const QString& link)
{
setText(QObject::tr(text.toStdString().c_str()));
if (exec() == QMessageBox::Accepted)
{
QDesktopServices::openUrl(QUrl(QCoreApplication::organizationDomain() + link));
}
}

View file

@ -0,0 +1,25 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2022 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QMessageBox>
class UpgradeDialog : public QMessageBox
{
public:
explicit UpgradeDialog(QWidget *parent = nullptr);
void showDialog(const QString& text, const QString& link);
};

View file

@ -27,7 +27,9 @@ enum Edition {
kUnregistered,
kBusiness,
kBasic_China,
kPro_China
kPro_China,
kLite,
kUltimate
};
#endif // EDITIONTYPE_H

View file

@ -9,6 +9,8 @@ const std::string SerialKeyEdition::BASIC = "basic";
const std::string SerialKeyEdition::BASIC_CHINA = "basic_china";
const std::string SerialKeyEdition::BUSINESS = "business";
const std::string SerialKeyEdition::UNREGISTERED = "unregistered";
const std::string SerialKeyEdition::ULTIMATE = "ultimate";
const std::string SerialKeyEdition::LITE = "lite";
namespace {
@ -24,7 +26,9 @@ const std::map<std::string, Edition>& getSerialTypes()
{SerialKeyEdition::PRO, kPro},
{SerialKeyEdition::BASIC_CHINA, kBasic_China},
{SerialKeyEdition::PRO_CHINA, kPro_China},
{SerialKeyEdition::BUSINESS, kBusiness}
{SerialKeyEdition::BUSINESS, kBusiness},
{SerialKeyEdition::LITE, kLite},
{SerialKeyEdition::ULTIMATE, kUltimate}
};
#endif
return serialTypes;
@ -78,6 +82,12 @@ SerialKeyEdition::getName() const
case kPro_China:
Name = PRO_CHINA;
break;
case kLite:
Name = LITE;
break;
case kUltimate:
Name = ULTIMATE;
break;
default:
break;
}
@ -99,6 +109,9 @@ SerialKeyEdition::getDisplayName() const
case kPro_China:
DisplayName = "Synergy Pro 中文版";
break;
case kLite:
DisplayName = "Synergy 1";
break;
default:
std::string EditionName = getName();
if (!EditionName.empty()){
@ -120,6 +133,7 @@ void
SerialKeyEdition::setType(Edition type)
{
m_Type = type;
setType(getName());
}
void

View file

@ -43,6 +43,8 @@ public:
static const std::string BASIC_CHINA;
static const std::string BUSINESS;
static const std::string UNREGISTERED;
static const std::string ULTIMATE;
static const std::string LITE;
private:
Edition m_Type = kUnregistered;

View file

@ -33,6 +33,12 @@ void
SerialKeyParser::setEdition(const std::string& edition)
{
m_data.edition.setType(edition);
if (m_data.keyType.isMaintenance() && m_data.edition.getType() == Edition::kBasic) {
m_data.edition.setType(kLite);
}
else if (m_data.keyType.isMaintenance() && m_data.edition.getType() == Edition::kPro) {
m_data.edition.setType(kUltimate);
}
}
void