Merge pull request #6389 from symless/v1-issue-6338-auto-config

#6384 Redesigned Auto Config UX so it's either manual or auto
This commit is contained in:
Nick Bolton 2018-08-08 17:27:29 +01:00 committed by GitHub
commit e0e8651490
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 784 additions and 427 deletions

12
dist/wix/Product.wxs vendored
View File

@ -42,7 +42,6 @@
</Component> </Component>
</DirectoryRef> </DirectoryRef>
<Icon Id="synergy.ico" SourceFile="$(var.ResPath)/synergy.ico"/> <Icon Id="synergy.ico" SourceFile="$(var.ResPath)/synergy.ico"/>
<WixVariable Id="WixUILicenseRtf" Value="$(var.ResPath)\License.rtf"/>
<WixVariable Id="WixUIBannerBmp" Value="$(var.ResPath)\banner.bmp"/> <WixVariable Id="WixUIBannerBmp" Value="$(var.ResPath)\banner.bmp"/>
<WixVariable Id="WixUIDialogBmp" Value="$(var.ResPath)\dialog.bmp"/> <WixVariable Id="WixUIDialogBmp" Value="$(var.ResPath)\dialog.bmp"/>
<Property Id="ARPPRODUCTICON" Value="synergy.ico"/> <Property Id="ARPPRODUCTICON" Value="synergy.ico"/>
@ -56,6 +55,17 @@
</Condition> </Condition>
<CustomAction ExeCommand="" FileKey="GuiProgram" Id="StartGui" Return="asyncNoWait"/> <CustomAction ExeCommand="" FileKey="GuiProgram" Id="StartGui" Return="asyncNoWait"/>
<UI> <UI>
<UIRef Id="WixUI_InstallDir" />
<Publish Dialog="WelcomeDlg"
Control="Next"
Event="NewDialog"
Value="InstallDirDlg"
Order="2">1</Publish>
<Publish Dialog="InstallDirDlg"
Control="Back"
Event="NewDialog"
Value="WelcomeDlg"
Order="2">1</Publish>
<Publish Control="Finish" Dialog="ExitDialog" Event="DoAction" Value="StartGui">NOT Installed</Publish> <Publish Control="Finish" Dialog="ExitDialog" Event="DoAction" Value="StartGui">NOT Installed</Publish>
</UI> </UI>
</Product> </Product>

View File

@ -54,5 +54,6 @@
<file>image/spinning-wheel.gif</file> <file>image/spinning-wheel.gif</file>
<file>icons/16x16/padlock.png</file> <file>icons/16x16/padlock.png</file>
<file>icons/16x16/synergy-transfering.png</file> <file>icons/16x16/synergy-transfering.png</file>
<file>icons/16x16/auto-config.png</file>
</qresource> </qresource>
</RCC> </RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

View File

@ -54,7 +54,6 @@ AppConfig::AppConfig(QSettings* settings) :
m_ProcessMode(DEFAULT_PROCESS_MODE), m_ProcessMode(DEFAULT_PROCESS_MODE),
m_AutoConfig(true), m_AutoConfig(true),
m_ElevateMode(defaultElevateMode), m_ElevateMode(defaultElevateMode),
m_AutoConfigPrompted(false),
m_CryptoEnabled(false), m_CryptoEnabled(false),
m_AutoHide(false), m_AutoHide(false),
m_LastExpiringWarningTime(0) m_LastExpiringWarningTime(0)
@ -147,7 +146,6 @@ void AppConfig::loadSettings()
QVariant(static_cast<int>(defaultElevateMode))); QVariant(static_cast<int>(defaultElevateMode)));
} }
m_ElevateMode = static_cast<ElevateMode>(elevateMode.toInt()); m_ElevateMode = static_cast<ElevateMode>(elevateMode.toInt());
m_AutoConfigPrompted = settings().value("autoConfigPrompted", false).toBool();
m_Edition = static_cast<Edition>(settings().value("edition", kUnregistered).toInt()); m_Edition = static_cast<Edition>(settings().value("edition", kUnregistered).toInt());
m_ActivateEmail = settings().value("activateEmail", "").toString(); m_ActivateEmail = settings().value("activateEmail", "").toString();
m_CryptoEnabled = settings().value("cryptoEnabled", true).toBool(); m_CryptoEnabled = settings().value("cryptoEnabled", true).toBool();
@ -174,7 +172,6 @@ void AppConfig::saveSettings()
// flag is mapped this way // flag is mapped this way
settings().setValue("elevateMode", m_ElevateMode == ElevateAlways); settings().setValue("elevateMode", m_ElevateMode == ElevateAlways);
settings().setValue("elevateModeEnum", static_cast<int>(m_ElevateMode)); settings().setValue("elevateModeEnum", static_cast<int>(m_ElevateMode));
settings().setValue("autoConfigPrompted", m_AutoConfigPrompted);
settings().setValue("edition", m_Edition); settings().setValue("edition", m_Edition);
settings().setValue("cryptoEnabled", m_CryptoEnabled); settings().setValue("cryptoEnabled", m_CryptoEnabled);
settings().setValue("autoHide", m_AutoHide); settings().setValue("autoHide", m_AutoHide);
@ -234,13 +231,6 @@ void AppConfig::setAutoConfig(bool autoConfig)
m_AutoConfig = autoConfig; m_AutoConfig = autoConfig;
} }
bool AppConfig::autoConfigPrompted() { return m_AutoConfigPrompted; }
void AppConfig::setAutoConfigPrompted(bool prompted)
{
m_AutoConfigPrompted = prompted;
}
#ifndef SYNERGY_ENTERPRISE #ifndef SYNERGY_ENTERPRISE
void AppConfig::setEdition(Edition e) { void AppConfig::setEdition(Edition e) {
m_Edition = e; m_Edition = e;

View File

@ -77,8 +77,6 @@ class AppConfig: public QObject
bool startedBefore() const; bool startedBefore() const;
bool autoConfig() const; bool autoConfig() const;
void setAutoConfig(bool autoConfig); void setAutoConfig(bool autoConfig);
bool autoConfigPrompted();
void setAutoConfigPrompted(bool prompted);
#ifndef SYNERGY_ENTERPRISE #ifndef SYNERGY_ENTERPRISE
void setEdition(Edition); void setEdition(Edition);
Edition edition() const; Edition edition() const;
@ -141,7 +139,6 @@ protected:
bool m_StartedBefore; bool m_StartedBefore;
bool m_AutoConfig; bool m_AutoConfig;
ElevateMode m_ElevateMode; ElevateMode m_ElevateMode;
bool m_AutoConfigPrompted;
Edition m_Edition; Edition m_Edition;
QString m_ActivateEmail; QString m_ActivateEmail;
bool m_CryptoEnabled; bool m_CryptoEnabled;

View File

@ -0,0 +1,203 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012-2018 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 "BonjourWindows.h"
#if defined(Q_OS_WIN)
#include "MainWindow.h"
#include "SettingsDialog.h"
#include "DataDownloader.h"
#include "QUtility.h"
#include "CommandProcess.h"
#include <QUrl>
#include <QThread>
#include <QDir>
#include <QStandardPaths>
#include <QMessageBox>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
BonjourWindows::BonjourWindows(
SettingsDialog* settingsDialog,
MainWindow* mainWindow,
AppConfig& appConfig) :
m_pSettingsDialog(settingsDialog),
m_pMainWindow(mainWindow),
m_pBonjourInstall(nullptr),
m_pDownloadMessageBox(nullptr),
m_pDataDownloader(nullptr),
m_appConfig(appConfig)
{
}
BonjourWindows::~BonjourWindows()
{
if (m_pBonjourInstall != nullptr) {
delete m_pBonjourInstall;
}
if (m_pDownloadMessageBox != nullptr) {
delete m_pDownloadMessageBox;
}
if (m_pDataDownloader != nullptr) {
delete m_pDataDownloader;
}
}
void BonjourWindows::downloadAndInstall()
{
QUrl url;
int arch = getProcessorArch();
if (arch == kProcessorArchWin32) {
url.setUrl(bonjourBaseUrl + bonjourFilename32);
m_pMainWindow->appendLogInfo("downloading bonjour (32-bit)");
}
else if (arch == kProcessorArchWin64) {
url.setUrl(bonjourBaseUrl + bonjourFilename64);
m_pMainWindow->appendLogInfo("downloading bonjour (64-bit)");
}
else {
QMessageBox::critical(
m_pSettingsDialog, tr("Synergy Auto Config"),
tr("Failed to detect system architecture."));
return;
}
if (m_pDataDownloader == nullptr) {
m_pDataDownloader = new DataDownloader(this);
connect(m_pDataDownloader, SIGNAL(isComplete()), SLOT(downloadFinished()));
}
m_pDataDownloader->download(url);
if (m_pDownloadMessageBox != nullptr) {
delete m_pDownloadMessageBox;
m_pDownloadMessageBox = nullptr;
}
m_pDownloadMessageBox = new QMessageBox(m_pSettingsDialog);
m_pDownloadMessageBox->setWindowTitle("Synergy Auto Config");
m_pDownloadMessageBox->setIcon(QMessageBox::Information);
m_pDownloadMessageBox->setText("Installing Bonjour, please wait...");
QAbstractButton* cancel = m_pDownloadMessageBox->addButton(
tr("Cancel"), QMessageBox::RejectRole);
m_pDownloadMessageBox->exec();
if (cancel == m_pDownloadMessageBox->clickedButton()) {
m_pDataDownloader->cancel();
}
}
void BonjourWindows::downloadFinished()
{
m_pMainWindow->appendLogInfo("bonjour downloaded");
install();
}
void BonjourWindows::install()
{
m_pMainWindow->appendLogInfo("installing bonjour");
QString tempLocation = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
QString filename = tempLocation;
filename.append("\\").append(bonjourTargetFilename);
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
m_pDownloadMessageBox->hide();
QMessageBox::warning(
m_pSettingsDialog, "Synergy",
tr("Failed to download Bonjour installer to location: %1")
.arg(tempLocation));
return;
}
file.write(m_pDataDownloader->data());
file.close();
QStringList arguments;
arguments.append("/i");
QString winFilename = QDir::toNativeSeparators(filename);
arguments.append(winFilename);
arguments.append("/passive");
if (m_pBonjourInstall != nullptr) {
delete m_pBonjourInstall;
m_pBonjourInstall = nullptr;
}
m_pBonjourInstall = new CommandProcess("msiexec", arguments);
QThread* thread = new QThread;
connect(m_pBonjourInstall, SIGNAL(finished()), this, SLOT(installFinished()));
connect(m_pBonjourInstall, SIGNAL(finished()), thread, SLOT(quit()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
m_pBonjourInstall->moveToThread(thread);
thread->start();
QMetaObject::invokeMethod(m_pBonjourInstall, "run", Qt::QueuedConnection);
m_pDownloadMessageBox->hide();
}
bool BonjourWindows::isRunning() const
{
QString name = "Bonjour Service";
SC_HANDLE hSCManager;
hSCManager = OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT);
if (hSCManager == nullptr) {
m_pMainWindow->appendLogError(
QString("failed to open a service controller manager, error: %1").arg(GetLastError()));
return false;
}
auto array = name.toLocal8Bit();
SC_HANDLE hService = OpenService(hSCManager, array.data(), SERVICE_QUERY_STATUS);
if (hService == nullptr) {
m_pMainWindow->appendLogDebug(
QString("failed to open service: %1").arg(name));
return false;
}
SERVICE_STATUS status;
if (QueryServiceStatus(hService, &status)) {
if (status.dwCurrentState == SERVICE_RUNNING) {
return true;
}
}
return false;
}
void BonjourWindows::installFinished()
{
m_pMainWindow->appendLogInfo("bonjour installed");
m_appConfig.setAutoConfig(true);
m_pSettingsDialog->allowAutoConfig();
}
#endif // Q_OS_WIN

View File

@ -0,0 +1,65 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012-2018 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 <QtCore/QObject>
#if defined(Q_OS_WIN)
#include <QMessageBox>
static QString bonjourBaseUrl = "http://binaries.symless.com/bonjour/";
static const char bonjourFilename32[] = "Bonjour.msi";
static const char bonjourFilename64[] = "Bonjour64.msi";
static const char bonjourTargetFilename[] = "Bonjour.msi";
class SettingsDialog;
class MainWindow;
class CommandProcess;
class DataDownloader;
class AppConfig;
class BonjourWindows : public QObject
{
Q_OBJECT
public:
BonjourWindows(SettingsDialog* settingsDialog, MainWindow* mainWindow, AppConfig& appConfig);
virtual ~BonjourWindows();
public:
void downloadAndInstall();
bool isRunning() const;
protected slots:
void downloadFinished();
void installFinished();
private:
void install();
private:
SettingsDialog* m_pSettingsDialog;
MainWindow* m_pMainWindow;
CommandProcess* m_pBonjourInstall;
QMessageBox* m_pDownloadMessageBox;
DataDownloader* m_pDataDownloader;
AppConfig& m_appConfig;
};
#endif // Q_OS_WIN

View File

@ -34,6 +34,7 @@ void DataDownloader::complete(QNetworkReply* reply)
{ {
m_Data = reply->readAll(); m_Data = reply->readAll();
reply->deleteLater(); reply->deleteLater();
m_pReply = nullptr;
if (!m_Data.isEmpty()) { if (!m_Data.isEmpty()) {
m_IsFinished = true; m_IsFinished = true;
@ -48,7 +49,9 @@ QByteArray DataDownloader::data() const
void DataDownloader::cancel() void DataDownloader::cancel()
{ {
m_pReply->abort(); if (m_pReply != nullptr) {
m_pReply->abort();
}
} }
void DataDownloader::download(QUrl url) void DataDownloader::download(QUrl url)

View File

@ -27,7 +27,6 @@
#include "ServerConfigDialog.h" #include "ServerConfigDialog.h"
#include "SettingsDialog.h" #include "SettingsDialog.h"
#include "ActivationDialog.h" #include "ActivationDialog.h"
#include "ZeroconfService.h"
#include "DataDownloader.h" #include "DataDownloader.h"
#include "CommandProcess.h" #include "CommandProcess.h"
#include "LicenseManager.h" #include "LicenseManager.h"
@ -35,6 +34,7 @@
#include "QUtility.h" #include "QUtility.h"
#include "ProcessorArch.h" #include "ProcessorArch.h"
#include "SslCertificate.h" #include "SslCertificate.h"
#include "Zeroconf.h"
#include <QtCore> #include <QtCore>
#include <QtGui> #include <QtGui>
@ -51,18 +51,9 @@
#include <ApplicationServices/ApplicationServices.h> #include <ApplicationServices/ApplicationServices.h>
#endif #endif
#if defined(Q_OS_WIN)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
static const char synergyConfigName[] = "synergy.sgc"; static const char synergyConfigName[] = "synergy.sgc";
static const QString synergyConfigFilter(QObject::tr("Synergy Configurations (*.sgc);;All files (*.*)")); static const QString synergyConfigFilter(QObject::tr("Synergy Configurations (*.sgc);;All files (*.*)"));
static QString bonjourBaseUrl = "http://binaries.symless.com/bonjour/";
static const char bonjourFilename32[] = "Bonjour.msi";
static const char bonjourFilename64[] = "Bonjour64.msi";
static const char bonjourTargetFilename[] = "Bonjour.msi";
#else #else
static const char synergyConfigName[] = "synergy.conf"; static const char synergyConfigName[] = "synergy.conf";
static const QString synergyConfigFilter(QObject::tr("Synergy Configurations (*.conf);;All files (*.*)")); static const QString synergyConfigFilter(QObject::tr("Synergy Configurations (*.conf);;All files (*.*)"));
@ -71,6 +62,8 @@ static const QString synergyConfigFilter(QObject::tr("Synergy Configurations (*.
static const char* tlsVersion = "TLS 1.2"; static const char* tlsVersion = "TLS 1.2";
static const char* tlsCheckString = "network encryption protocol: TLSv1.2"; static const char* tlsCheckString = "network encryption protocol: TLSv1.2";
static const int debugLogLevel = 1;
static const char* synergyIconFiles[] = static const char* synergyIconFiles[] =
{ {
":/res/icons/16x16/synergy-disconnected.png", ":/res/icons/16x16/synergy-disconnected.png",
@ -85,11 +78,14 @@ MainWindow::MainWindow (QSettings& settings, AppConfig& appConfig)
MainWindow::MainWindow (QSettings& settings, AppConfig& appConfig, MainWindow::MainWindow (QSettings& settings, AppConfig& appConfig,
LicenseManager& licenseManager) LicenseManager& licenseManager)
#endif #endif
: m_Settings(settings), :
m_AppConfig(&appConfig),
#ifndef SYNERGY_ENTERPRISE #ifndef SYNERGY_ENTERPRISE
m_LicenseManager(&licenseManager), m_LicenseManager(&licenseManager),
m_ActivationDialogRunning(false),
#endif #endif
m_pZeroconf(nullptr),
m_Settings(settings),
m_AppConfig(&appConfig),
m_pSynergy(NULL), m_pSynergy(NULL),
m_SynergyState(synergyDisconnected), m_SynergyState(synergyDisconnected),
m_ServerConfig(&m_Settings, 5, 3, m_AppConfig->screenName(), this), m_ServerConfig(&m_Settings, 5, 3, m_AppConfig->screenName(), this),
@ -102,22 +98,15 @@ MainWindow::MainWindow (QSettings& settings, AppConfig& appConfig,
m_pMenuEdit(NULL), m_pMenuEdit(NULL),
m_pMenuWindow(NULL), m_pMenuWindow(NULL),
m_pMenuHelp(NULL), m_pMenuHelp(NULL),
#ifndef SYNERGY_ENTERPRISE
m_pZeroconfService(NULL),
#endif
m_pDataDownloader(NULL),
m_DownloadMessageBox(NULL),
m_pCancelButton(NULL), m_pCancelButton(NULL),
m_SuppressAutoConfigWarning(false),
m_BonjourInstall(NULL),
m_SuppressEmptyServerWarning(false),
m_ExpectedRunningState(kStopped), m_ExpectedRunningState(kStopped),
m_pSslCertificate(NULL) m_pSslCertificate(NULL),
#ifndef SYNERGY_ENTERPRISE m_SecureSocket(false)
, m_ActivationDialogRunning(false)
#endif
, m_SecureSocket(false)
{ {
#ifndef SYNERGY_ENTERPRISE
m_pZeroconf = new Zeroconf(this);
#endif
setupUi(this); setupUi(this);
createMenuBar(); createMenuBar();
@ -146,11 +135,6 @@ MainWindow::MainWindow (QSettings& settings, AppConfig& appConfig,
setMinimumSize(size()); setMinimumSize(size());
#endif #endif
m_SuppressAutoConfigWarning = true;
m_pCheckBoxAutoConfig->setChecked(appConfig.autoConfig());
m_SuppressAutoConfigWarning = false;
m_pComboServerList->hide();
m_trialWidget->hide(); m_trialWidget->hide();
// hide padlock icon // hide padlock icon
@ -191,7 +175,11 @@ MainWindow::MainWindow (QSettings& settings, AppConfig& appConfig,
#ifdef SYNERGY_ENTERPRISE #ifdef SYNERGY_ENTERPRISE
m_pActivate->setVisible(false); m_pActivate->setVisible(false);
m_pCheckBoxAutoConfig->setVisible(false); #endif
#ifndef SYNERGY_ENTERPRISE
updateZeroconfService();
updateAutoConfigWidgets();
#endif #endif
} }
@ -202,19 +190,11 @@ MainWindow::~MainWindow()
stopDesktop(); stopDesktop();
} }
saveSettings();
#ifndef SYNERGY_ENTERPRISE #ifndef SYNERGY_ENTERPRISE
delete m_pZeroconfService; delete m_pZeroconf;
#endif #endif
if (m_DownloadMessageBox != NULL) { saveSettings();
delete m_DownloadMessageBox;
}
if (m_BonjourInstall != NULL) {
delete m_BonjourInstall;
}
delete m_pSslCertificate; delete m_pSslCertificate;
} }
@ -229,19 +209,11 @@ void MainWindow::open()
m_VersionChecker.checkLatest(); m_VersionChecker.checkLatest();
#ifndef SYNERGY_ENTERPRISE
if (!appConfig().autoConfigPrompted()) {
promptAutoConfig();
}
#endif
// only start if user has previously started. this stops the gui from // only start if user has previously started. this stops the gui from
// auto hiding before the user has configured synergy (which of course // auto hiding before the user has configured synergy (which of course
// confuses first time users, who think synergy has crashed). // confuses first time users, who think synergy has crashed).
if (appConfig().startedBefore() && appConfig().processMode() == Desktop) { if (appConfig().startedBefore() && appConfig().processMode() == Desktop) {
m_SuppressEmptyServerWarning = true;
startSynergy(); startSynergy();
m_SuppressEmptyServerWarning = false;
} }
} }
@ -438,7 +410,7 @@ void MainWindow::appendLogInfo(const QString& text)
} }
void MainWindow::appendLogDebug(const QString& text) { void MainWindow::appendLogDebug(const QString& text) {
if (appConfig().logLevel() >= 4) { if (appConfig().logLevel() >= debugLogLevel) {
appendLogRaw(getTimeStamp() + " DEBUG: " + text); appendLogRaw(getTimeStamp() + " DEBUG: " + text);
} }
} }
@ -773,7 +745,7 @@ bool MainWindow::clientArgs(QStringList& args, QString& app)
#ifndef SYNERGY_ENTERPRISE #ifndef SYNERGY_ENTERPRISE
// check auto config first, if it is disabled or no server detected, // check auto config first, if it is disabled or no server detected,
// use line edit host name if it is not empty // use line edit host name if it is not empty
if (m_pCheckBoxAutoConfig->isChecked()) { if (appConfig().autoConfig()) {
if (m_pComboServerList->count() != 0) { if (m_pComboServerList->count() != 0) {
QString serverIp = m_pComboServerList->currentText(); QString serverIp = m_pComboServerList->currentText();
args << serverIp + ":" + QString::number(appConfig().port()); args << serverIp + ":" + QString::number(appConfig().port());
@ -784,15 +756,13 @@ bool MainWindow::clientArgs(QStringList& args, QString& app)
if (m_pLineEditHostname->text().isEmpty()) { if (m_pLineEditHostname->text().isEmpty()) {
show(); show();
if (!m_SuppressEmptyServerWarning) { QMessageBox::warning(
QMessageBox::warning(this, tr("Hostname is empty"), this, tr("Hostname is empty"),
tr("Please fill in a hostname for the synergy client to connect to.")); tr("Please fill in a hostname for the synergy client to connect to."));
}
return false; return false;
} }
args << m_pLineEditHostname->text() + ":" + QString::number(appConfig().port()); args << m_pLineEditHostname->text() + ":" + QString::number(appConfig().port());
return true; return true;
} }
@ -1101,30 +1071,19 @@ void MainWindow::changeEvent(QEvent* event)
} }
} }
#ifndef SYNERGY_ENTERPRISE void MainWindow::zeroconfServerDetected(const QString name)
void MainWindow::updateZeroconfService()
{ {
QMutexLocker locker(&m_UpdateZeroconfMutex); // don't add to the server combo box if not in client mode.
if (synergyType() != synergyClient) {
if (isBonjourRunning()) { return;
if (!m_AppConfig->wizardShouldRun()) { }
if (m_pZeroconfService) {
delete m_pZeroconfService; // don't add yourself to the server list.
m_pZeroconfService = NULL; if (getIPAddresses().contains(name)) {
} return;
if (m_AppConfig->autoConfig() || synergyType() == synergyServer) {
m_pZeroconfService = new ZeroconfService(this);
}
}
} }
}
#endif
void MainWindow::serverDetected(const QString name)
{
if (m_pComboServerList->findText(name) == -1) { if (m_pComboServerList->findText(name) == -1) {
// Note: the first added item triggers startSynergy
m_pComboServerList->addItem(name); m_pComboServerList->addItem(name);
} }
@ -1223,21 +1182,15 @@ MainWindow::licenseManager() const
void MainWindow::on_m_pGroupClient_toggled(bool on) void MainWindow::on_m_pGroupClient_toggled(bool on)
{ {
m_pGroupServer->setChecked(!on); m_pGroupServer->setChecked(!on);
#ifndef SYNERGY_ENTERPRISE
if (on) { // only call in either client or server toggle, but not both
updateZeroconfService(); // since the toggle functions call eachother indirectly.
} updateZeroconfService();
#endif
} }
void MainWindow::on_m_pGroupServer_toggled(bool on) void MainWindow::on_m_pGroupServer_toggled(bool on)
{ {
m_pGroupClient->setChecked(!on); m_pGroupClient->setChecked(!on);
#ifndef SYNERGY_ENTERPRISE
if (on) {
updateZeroconfService();
}
#endif
} }
bool MainWindow::on_m_pButtonBrowseConfigFile_clicked() bool MainWindow::on_m_pButtonBrowseConfigFile_clicked()
@ -1272,9 +1225,51 @@ void MainWindow::on_m_pActionAbout_triggered()
dlg.exec(); dlg.exec();
} }
void MainWindow::updateZeroconfService()
{
#ifndef SYNERGY_ENTERPRISE
// reset the server list in case one has gone away.
// it'll be re-added after the zeroconf service restarts.
m_pComboServerList->clear();
if (m_pZeroconf != nullptr) {
if (appConfig().autoConfig()) {
m_pZeroconf->startService();
}
else {
m_pZeroconf->stopService();
}
}
#endif
}
void MainWindow::updateAutoConfigWidgets()
{
if (appConfig().autoConfig()) {
m_pLabelAutoDetected->show();
m_pComboServerList->show();
m_pLabelServerName->hide();
m_pLineEditHostname->hide();
m_pWidgetAutoConfig->hide();
}
else {
m_pLabelServerName->show();
m_pLineEditHostname->show();
m_pLabelAutoDetected->hide();
m_pComboServerList->hide();
m_pWidgetAutoConfig->show();
}
}
void MainWindow::on_m_pActionSettings_triggered() void MainWindow::on_m_pActionSettings_triggered()
{ {
ProcessMode lastProcessMode = appConfig().processMode(); ProcessMode lastProcessMode = appConfig().processMode();
bool lastAutoConfig = appConfig().autoConfig();
SettingsDialog dlg(this, appConfig()); SettingsDialog dlg(this, appConfig());
dlg.exec(); dlg.exec();
@ -1283,40 +1278,45 @@ void MainWindow::on_m_pActionSettings_triggered()
{ {
onModeChanged(true, true); onModeChanged(true, true);
} }
if (lastAutoConfig != appConfig().autoConfig()) {
updateAutoConfigWidgets();
updateZeroconfService();
}
} }
void MainWindow::autoAddScreen(const QString name) void MainWindow::autoAddScreen(const QString name)
{ {
if (!m_ServerConfig.ignoreAutoConfigClient()) { if (m_ServerConfig.ignoreAutoConfigClient()) {
appendLogDebug(QString("ignoring zeroconf screen: %1").arg(name));
return;
}
#ifndef SYNERGY_ENTERPRISE #ifndef SYNERGY_ENTERPRISE
if (m_ActivationDialogRunning) { if (m_ActivationDialogRunning) {
// TODO: refactor this code // TODO: refactor this code
// add this screen to the pending list and check this list until // add this screen to the pending list and check this list until
// users finish activation dialog // users finish activation dialog
m_PendingClientNames.append(name); m_PendingClientNames.append(name);
return; return;
} }
#endif #endif
int r = m_ServerConfig.autoAddScreen(name); int r = m_ServerConfig.autoAddScreen(name);
if (r != kAutoAddScreenOk) { if (r != kAutoAddScreenOk) {
switch (r) { switch (r) {
case kAutoAddScreenManualServer: case kAutoAddScreenManualServer:
showConfigureServer( showConfigureServer(
tr("Please add the server (%1) to the grid.") tr("Please add the server (%1) to the grid.")
.arg(appConfig().screenName())); .arg(appConfig().screenName()));
break; break;
case kAutoAddScreenManualClient: case kAutoAddScreenManualClient:
showConfigureServer( showConfigureServer(
tr("Please drag the new client screen (%1) " tr("Please drag the new client screen (%1) "
"to the desired position on the grid.") "to the desired position on the grid.")
.arg(name)); .arg(name));
break; break;
}
}
else {
restartSynergy();
} }
} }
} }
@ -1345,211 +1345,7 @@ void MainWindow::on_m_pButtonApply_clicked()
restartSynergy(); restartSynergy();
} }
#if defined(Q_OS_WIN)
bool MainWindow::isServiceRunning(QString name)
{
SC_HANDLE hSCManager;
hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (hSCManager == NULL) {
appendLogError("failed to open a service controller manager, error: " +
GetLastError());
return false;
}
auto array = name.toLocal8Bit();
SC_HANDLE hService = OpenService(hSCManager, array.data(), SERVICE_QUERY_STATUS);
if (hService == NULL) {
appendLogDebug("failed to open service: " + name);
return false;
}
SERVICE_STATUS status;
if (QueryServiceStatus(hService, &status)) {
if (status.dwCurrentState == SERVICE_RUNNING) {
return true;
}
}
#else
bool MainWindow::isServiceRunning()
{
#endif
return false;
}
#ifndef SYNERGY_ENTERPRISE #ifndef SYNERGY_ENTERPRISE
bool MainWindow::isBonjourRunning()
{
bool result = false;
#if defined(Q_OS_WIN)
result = isServiceRunning("Bonjour Service");
#else
result = true;
#endif
return result;
}
void MainWindow::downloadBonjour()
{
#if defined(Q_OS_WIN)
QUrl url;
int arch = getProcessorArch();
if (arch == kProcessorArchWin32) {
url.setUrl(bonjourBaseUrl + bonjourFilename32);
appendLogInfo("downloading 32-bit Bonjour");
}
else if (arch == kProcessorArchWin64) {
url.setUrl(bonjourBaseUrl + bonjourFilename64);
appendLogInfo("downloading 64-bit Bonjour");
}
else {
QMessageBox::critical(
this, tr("Synergy"),
tr("Failed to detect system architecture."));
return;
}
if (m_pDataDownloader == NULL) {
m_pDataDownloader = new DataDownloader(this);
connect(m_pDataDownloader, SIGNAL(isComplete()), SLOT(installBonjour()));
}
m_pDataDownloader->download(url);
if (m_DownloadMessageBox == NULL) {
m_DownloadMessageBox = new QMessageBox(this);
m_DownloadMessageBox->setWindowTitle("Synergy");
m_DownloadMessageBox->setIcon(QMessageBox::Information);
m_DownloadMessageBox->setText("Installing Bonjour, please wait...");
m_DownloadMessageBox->setStandardButtons(0);
m_pCancelButton = m_DownloadMessageBox->addButton(
tr("Cancel"), QMessageBox::RejectRole);
}
m_DownloadMessageBox->exec();
if (m_DownloadMessageBox->clickedButton() == m_pCancelButton) {
m_pDataDownloader->cancel();
}
#endif
}
void MainWindow::installBonjour()
{
#if defined(Q_OS_WIN)
#if QT_VERSION >= 0x050000
QString tempLocation = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
#else
QString tempLocation = QDesktopServices::storageLocation(
QDesktopServices::TempLocation);
#endif
QString filename = tempLocation;
filename.append("\\").append(bonjourTargetFilename);
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
m_DownloadMessageBox->hide();
QMessageBox::warning(
this, "Synergy",
tr("Failed to download Bonjour installer to location: %1")
.arg(tempLocation));
return;
}
file.write(m_pDataDownloader->data());
file.close();
QStringList arguments;
arguments.append("/i");
QString winFilename = QDir::toNativeSeparators(filename);
arguments.append(winFilename);
arguments.append("/passive");
if (m_BonjourInstall == NULL) {
m_BonjourInstall = new CommandProcess("msiexec", arguments);
}
QThread* thread = new QThread;
connect(m_BonjourInstall, SIGNAL(finished()), this,
SLOT(bonjourInstallFinished()));
connect(m_BonjourInstall, SIGNAL(finished()), thread, SLOT(quit()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
m_BonjourInstall->moveToThread(thread);
thread->start();
QMetaObject::invokeMethod(m_BonjourInstall, "run", Qt::QueuedConnection);
m_DownloadMessageBox->hide();
#endif
}
void MainWindow::promptAutoConfig()
{
if (!isBonjourRunning()) {
int r = QMessageBox::question(
this, tr("Synergy"),
tr("Do you want to enable auto config and install Bonjour?\n\n"
"This feature helps you establish the connection."),
QMessageBox::Yes | QMessageBox::No);
if (r == QMessageBox::Yes) {
m_AppConfig->setAutoConfig(true);
downloadBonjour();
}
else {
m_AppConfig->setAutoConfig(false);
m_pCheckBoxAutoConfig->setChecked(false);
}
}
m_AppConfig->setAutoConfigPrompted(true);
}
void MainWindow::on_m_pComboServerList_currentIndexChanged(QString )
{
if (m_pComboServerList->count() != 0) {
restartSynergy();
}
}
void MainWindow::on_m_pCheckBoxAutoConfig_toggled(bool checked)
{
if (!isBonjourRunning() && checked) {
if (!m_SuppressAutoConfigWarning) {
int r = QMessageBox::information(
this, tr("Synergy"),
tr("Auto config feature requires Bonjour.\n\n"
"Do you want to install Bonjour?"),
QMessageBox::Yes | QMessageBox::No);
if (r == QMessageBox::Yes) {
downloadBonjour();
}
}
m_pCheckBoxAutoConfig->setChecked(false);
return;
}
m_pLineEditHostname->setDisabled(checked);
appConfig().setAutoConfig(checked);
updateZeroconfService();
if (!checked) {
m_pComboServerList->clear();
m_pComboServerList->hide();
}
}
void MainWindow::bonjourInstallFinished()
{
appendLogInfo("Bonjour install finished");
m_pCheckBoxAutoConfig->setChecked(true);
}
int MainWindow::raiseActivationDialog() int MainWindow::raiseActivationDialog()
{ {
if (m_ActivationDialogRunning) { if (m_ActivationDialogRunning) {
@ -1568,9 +1364,6 @@ int MainWindow::raiseActivationDialog()
m_PendingClientNames.clear(); m_PendingClientNames.clear();
} }
if (result == QDialog::Accepted) {
restartSynergy();
}
return result; return result;
} }
#endif #endif
@ -1612,3 +1405,8 @@ void MainWindow::secureSocket(bool secureSocket)
m_pLabelPadlock->hide(); m_pLabelPadlock->hide();
} }
} }
void MainWindow::on_m_pLabelAutoConfig_linkActivated(const QString &)
{
m_pActionSettings->trigger();
}

View File

@ -16,9 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#if !defined(MAINWINDOW__H) #pragma once
#define MAINWINDOW__H
#include <QMainWindow> #include <QMainWindow>
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
@ -54,11 +52,11 @@ class QAbstractButton;
class LogDialog; class LogDialog;
class QSynergyApplication; class QSynergyApplication;
class SetupWizard; class SetupWizard;
class ZeroconfService;
class DataDownloader; class DataDownloader;
class CommandProcess; class CommandProcess;
class SslCertificate; class SslCertificate;
class LicenseManager; class LicenseManager;
class Zeroconf;
class MainWindow : public QMainWindow, public Ui::MainWindowBase class MainWindow : public QMainWindow, public Ui::MainWindowBase
{ {
@ -119,14 +117,16 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
void showConfigureServer(const QString& message); void showConfigureServer(const QString& message);
void showConfigureServer() { showConfigureServer(""); } void showConfigureServer() { showConfigureServer(""); }
void autoAddScreen(const QString name); void autoAddScreen(const QString name);
void serverDetected(const QString name); void zeroconfServerDetected(const QString name);
void updateLocalFingerprint(); void updateLocalFingerprint();
Zeroconf& zeroconf() { return *m_pZeroconf; }
#ifndef SYNERGY_ENTERPRISE #ifndef SYNERGY_ENTERPRISE
void updateZeroconfService();
LicenseManager& licenseManager() const; LicenseManager& licenseManager() const;
int raiseActivationDialog(); int raiseActivationDialog();
#endif #endif
void updateZeroconfService();
public slots: public slots:
void setEdition(Edition edition); void setEdition(Edition edition);
#ifndef SYNERGY_ENTERPRISE #ifndef SYNERGY_ENTERPRISE
@ -155,9 +155,6 @@ public slots:
void logOutput(); void logOutput();
void logError(); void logError();
void updateFound(const QString& version); void updateFound(const QString& version);
#ifndef SYNERGY_ENTERPRISE
void bonjourInstallFinished();
#endif
void saveSettings(); void saveSettings();
protected: protected:
@ -190,11 +187,6 @@ public slots:
bool isServiceRunning(); bool isServiceRunning();
#endif #endif
#ifndef SYNERGY_ENTERPRISE
bool isBonjourRunning();
void downloadBonjour();
void promptAutoConfig();
#endif
QString getProfileRootForArg(); QString getProfileRootForArg();
void checkConnected(const QString& line); void checkConnected(const QString& line);
void checkFingerprint(const QString& line); void checkFingerprint(const QString& line);
@ -211,9 +203,14 @@ public slots:
void secureSocket(bool secureSocket); void secureSocket(bool secureSocket);
private: private:
#ifndef SYNERGY_ENTERPRISE
LicenseManager* m_LicenseManager;
bool m_ActivationDialogRunning;
QStringList m_PendingClientNames;
#endif
Zeroconf* m_pZeroconf;
QSettings& m_Settings; QSettings& m_Settings;
AppConfig* m_AppConfig; AppConfig* m_AppConfig;
LicenseManager* m_LicenseManager;
QProcess* m_pSynergy; QProcess* m_pSynergy;
int m_SynergyState; int m_SynergyState;
ServerConfig m_ServerConfig; ServerConfig m_ServerConfig;
@ -228,37 +225,20 @@ public slots:
QMenu* m_pMenuEdit; QMenu* m_pMenuEdit;
QMenu* m_pMenuWindow; QMenu* m_pMenuWindow;
QMenu* m_pMenuHelp; QMenu* m_pMenuHelp;
#ifndef SYNERGY_ENTERPRISE
ZeroconfService* m_pZeroconfService;
#endif
DataDownloader* m_pDataDownloader;
QMessageBox* m_DownloadMessageBox;
QAbstractButton* m_pCancelButton; QAbstractButton* m_pCancelButton;
QMutex m_UpdateZeroconfMutex;
bool m_SuppressAutoConfigWarning;
CommandProcess* m_BonjourInstall;
bool m_SuppressEmptyServerWarning;
qRuningState m_ExpectedRunningState; qRuningState m_ExpectedRunningState;
QMutex m_StopDesktopMutex; QMutex m_StopDesktopMutex;
SslCertificate* m_pSslCertificate; SslCertificate* m_pSslCertificate;
#ifndef SYNERGY_ENTERPRISE
bool m_ActivationDialogRunning;
QStringList m_PendingClientNames;
#endif
bool m_SecureSocket; bool m_SecureSocket;
void updateAutoConfigWidgets();
private slots: private slots:
void on_m_pButtonApply_clicked(); void on_m_pButtonApply_clicked();
#ifndef SYNERGY_ENTERPRISE
void on_m_pCheckBoxAutoConfig_toggled(bool checked);
void on_m_pComboServerList_currentIndexChanged(QString );
void installBonjour();
#endif
void on_windowShown(); void on_windowShown();
void on_m_pLabelAutoConfig_linkActivated(const QString &link);
signals: signals:
void windowShown(); void windowShown();
}; };
#endif

View File

@ -48,7 +48,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="Synergy.qrc">:/res/icons/16x16/warning.png</pixmap> <pixmap resource="../res/Synergy.qrc">:/res/icons/16x16/warning.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -99,7 +99,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="Synergy.qrc">:/res/icons/16x16/warning.png</pixmap> <pixmap resource="../res/Synergy.qrc">:/res/icons/16x16/warning.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -129,6 +129,81 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QWidget" name="m_pWidgetAutoConfig" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>28</height>
</size>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<widget class="QLabel" name="m_pIconAutoConfig">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>16</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>244</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../res/Synergy.qrc">:/res/icons/16x16/auto-config.png</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_pLabelAutoConfig">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Manual Config mode active, consider using Auto Config instead (&lt;a href=&quot;#&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;Settings&lt;/span&gt;&lt;/a&gt;)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
</widget>
</item>
<item>
<spacer name="m_pSpacerAutoConfig">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QGroupBox" name="m_pGroupServer"> <widget class="QGroupBox" name="m_pGroupServer">
<property name="sizePolicy"> <property name="sizePolicy">
@ -289,9 +364,9 @@
<enum>QFormLayout::AllNonFixedFieldsGrow</enum> <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property> </property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_5"> <widget class="QLabel" name="m_pLabelComputerName">
<property name="text"> <property name="text">
<string>Screen name:</string> <string>Client name:</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -305,7 +380,7 @@
<item row="2" column="0"> <item row="2" column="0">
<widget class="QLabel" name="m_pLabelServerName"> <widget class="QLabel" name="m_pLabelServerName">
<property name="text"> <property name="text">
<string>&amp;Server IP:</string> <string>&amp;Server:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>m_pLineEditHostname</cstring> <cstring>m_pLineEditHostname</cstring>
@ -313,16 +388,25 @@
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="2" column="1">
<widget class="QLineEdit" name="m_pLineEditHostname"/> <widget class="QLineEdit" name="m_pLineEditHostname">
</item> <property name="sizePolicy">
<item row="3" column="0"> <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<widget class="QCheckBox" name="m_pCheckBoxAutoConfig"> <horstretch>0</horstretch>
<property name="text"> <verstretch>0</verstretch>
<string>Auto config</string> </sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Hostname or IP address of the server computer.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="4" column="1">
<widget class="QComboBox" name="m_pComboServerList"> <widget class="QComboBox" name="m_pComboServerList">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred"> <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
@ -332,12 +416,19 @@
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>120</width> <width>200</width>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0">
<widget class="QLabel" name="m_pLabelAutoDetected">
<property name="text">
<string>Server:</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -391,7 +482,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="Synergy.qrc">:/res/icons/16x16/padlock.png</pixmap> <pixmap resource="../res/Synergy.qrc">:/res/icons/16x16/padlock.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -542,7 +633,7 @@
</action> </action>
</widget> </widget>
<resources> <resources>
<include location="Synergy.qrc"/> <include location="../res/Synergy.qrc"/>
</resources> </resources>
<connections> <connections>
<connection> <connection>

View File

@ -303,7 +303,7 @@ int ServerConfig::autoAddScreen(const QString name)
} }
} }
if (findScreenName(name, targetIndex)) { if (findScreenName(name, targetIndex)) {
// already exists. m_pMainWindow->appendLogDebug(QString("ignoring screen already in config: %1").arg(name));
return kAutoAddScreenIgnore; return kAutoAddScreenIgnore;
} }

View File

@ -25,6 +25,8 @@
#include "AppConfig.h" #include "AppConfig.h"
#include "SslCertificate.h" #include "SslCertificate.h"
#include "MainWindow.h" #include "MainWindow.h"
#include "BonjourWindows.h"
#include "Zeroconf.h"
#include <QtCore> #include <QtCore>
#include <QtGui> #include <QtGui>
@ -37,10 +39,14 @@ static const char networkSecurity[] = "ns";
SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) : SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) :
QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint), QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
Ui::SettingsDialogBase(), Ui::SettingsDialogBase(),
m_appConfig(config) m_appConfig(config),
m_pBonjourWindows(nullptr)
{ {
setupUi(this); setupUi(this);
// TODO: maybe just accept MainWindow type in ctor?
m_pMainWindow = dynamic_cast<MainWindow*>(parent);
m_Locale.fillLanguageComboBox(m_pComboLanguage); m_Locale.fillLanguageComboBox(m_pComboLanguage);
m_pLineEditScreenName->setText(appConfig().screenName()); m_pLineEditScreenName->setText(appConfig().screenName());
@ -53,20 +59,41 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) :
m_pCheckBoxAutoHide->setChecked(appConfig().getAutoHide()); m_pCheckBoxAutoHide->setChecked(appConfig().getAutoHide());
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
m_pComboElevate->setCurrentIndex(static_cast<int>(appConfig().elevateMode())); m_pBonjourWindows = new BonjourWindows(this, m_pMainWindow, m_appConfig);
if (m_pBonjourWindows->isRunning()) {
allowAutoConfig();
}
m_pComboElevate->setCurrentIndex(static_cast<int>(appConfig().elevateMode()));
m_pCheckBoxAutoHide->hide(); m_pCheckBoxAutoHide->hide();
#else #else
// elevate checkbox is only useful on ms windows. // elevate checkbox is only useful on ms windows.
m_pLabelElevate->hide(); m_pLabelElevate->hide();
m_pComboElevate->hide(); m_pComboElevate->hide();
// for linux and mac, allow auto config by default
allowAutoConfig();
#endif #endif
m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled()); m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled());
#ifdef SYNERGY_ENTERPRISE #ifdef SYNERGY_ENTERPRISE
m_pCheckBoxEnableCrypto->setEnabled(true); m_pCheckBoxEnableCrypto->setEnabled(true);
m_pLabelProUpgrade->hide();
m_pCheckBoxAutoConfig->hide();
m_pLabelInstallBonjour->hide();
#else #else
m_pCheckBoxEnableCrypto->setEnabled(m_appConfig.edition() == kPro);
bool isPro = m_appConfig.edition() == kPro;
m_pCheckBoxEnableCrypto->setEnabled(isPro);
m_pLabelProUpgrade->setVisible(!isPro);
m_pCheckBoxAutoConfig->setChecked(appConfig().autoConfig());
#endif #endif
} }
@ -81,6 +108,7 @@ void SettingsDialog::accept()
appConfig().setLanguage(m_pComboLanguage->itemData(m_pComboLanguage->currentIndex()).toString()); appConfig().setLanguage(m_pComboLanguage->itemData(m_pComboLanguage->currentIndex()).toString());
appConfig().setElevateMode(static_cast<ElevateMode>(m_pComboElevate->currentIndex())); appConfig().setElevateMode(static_cast<ElevateMode>(m_pComboElevate->currentIndex()));
appConfig().setAutoHide(m_pCheckBoxAutoHide->isChecked()); appConfig().setAutoHide(m_pCheckBoxAutoHide->isChecked());
appConfig().setAutoConfig(m_pCheckBoxAutoConfig->isChecked());
appConfig().saveSettings(); appConfig().saveSettings();
QDialog::accept(); QDialog::accept();
} }
@ -96,7 +124,7 @@ void SettingsDialog::reject()
void SettingsDialog::changeEvent(QEvent* event) void SettingsDialog::changeEvent(QEvent* event)
{ {
if (event != 0) if (event != nullptr)
{ {
switch (event->type()) switch (event->type())
{ {
@ -118,6 +146,13 @@ void SettingsDialog::changeEvent(QEvent* event)
} }
} }
void SettingsDialog::allowAutoConfig()
{
m_pLabelInstallBonjour->hide();
m_pCheckBoxAutoConfig->setEnabled(true);
m_pCheckBoxAutoConfig->setChecked(m_appConfig.autoConfig());
}
void SettingsDialog::on_m_pCheckBoxLogToFile_stateChanged(int i) void SettingsDialog::on_m_pCheckBoxLogToFile_stateChanged(int i)
{ {
bool checked = i == 2; bool checked = i == 2;
@ -152,7 +187,13 @@ void SettingsDialog::on_m_pCheckBoxEnableCrypto_toggled(bool checked)
if (checked) { if (checked) {
SslCertificate sslCertificate; SslCertificate sslCertificate;
sslCertificate.generateCertificate(); sslCertificate.generateCertificate();
MainWindow& mainWindow = dynamic_cast<MainWindow&> (*this->parent()); m_pMainWindow->updateLocalFingerprint();
mainWindow.updateLocalFingerprint();
} }
} }
void SettingsDialog::on_m_pLabelInstallBonjour_linkActivated(const QString&)
{
#if defined(Q_OS_WIN)
m_pBonjourWindows->downloadAndInstall();
#endif
}

View File

@ -25,7 +25,9 @@
#include "SynergyLocale.h" #include "SynergyLocale.h"
#include "CoreInterface.h" #include "CoreInterface.h"
class MainWindow;
class AppConfig; class AppConfig;
class BonjourWindows;
class SettingsDialog : public QDialog, public Ui::SettingsDialogBase class SettingsDialog : public QDialog, public Ui::SettingsDialogBase
{ {
@ -35,6 +37,7 @@ class SettingsDialog : public QDialog, public Ui::SettingsDialogBase
SettingsDialog(QWidget* parent, AppConfig& config); SettingsDialog(QWidget* parent, AppConfig& config);
static QString browseForSynergyc(QWidget* parent, const QString& programDir, const QString& synergycName); static QString browseForSynergyc(QWidget* parent, const QString& programDir, const QString& synergycName);
static QString browseForSynergys(QWidget* parent, const QString& programDir, const QString& synergysName); static QString browseForSynergys(QWidget* parent, const QString& programDir, const QString& synergysName);
void allowAutoConfig();
protected: protected:
void accept(); void accept();
@ -43,15 +46,18 @@ class SettingsDialog : public QDialog, public Ui::SettingsDialogBase
AppConfig& appConfig() { return m_appConfig; } AppConfig& appConfig() { return m_appConfig; }
private: private:
MainWindow* m_pMainWindow;
AppConfig& m_appConfig; AppConfig& m_appConfig;
SynergyLocale m_Locale; SynergyLocale m_Locale;
CoreInterface m_CoreInterface; CoreInterface m_CoreInterface;
BonjourWindows* m_pBonjourWindows;
private slots: private slots:
void on_m_pCheckBoxEnableCrypto_toggled(bool checked); void on_m_pCheckBoxEnableCrypto_toggled(bool checked);
void on_m_pComboLanguage_currentIndexChanged(int index); void on_m_pComboLanguage_currentIndexChanged(int index);
void on_m_pCheckBoxLogToFile_stateChanged(int ); void on_m_pCheckBoxLogToFile_stateChanged(int );
void on_m_pButtonBrowseLog_clicked(); void on_m_pButtonBrowseLog_clicked();
void on_m_pLabelInstallBonjour_linkActivated(const QString &link);
}; };
#endif #endif

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>368</width> <width>357</width>
<height>446</height> <height>496</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -157,7 +157,23 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="m_pGroupNetworkSecurity"> <spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="m_pGroupNetwork">
<property name="enabled"> <property name="enabled">
<bool>true</bool> <bool>true</bool>
</property> </property>
@ -168,38 +184,96 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="title"> <property name="title">
<string>&amp;Network Security</string> <string>&amp;Network</string>
</property> </property>
<layout class="QFormLayout" name="formLayout"> <layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy"> <property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum> <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property> </property>
<item row="0" column="0"> <property name="leftMargin">
<widget class="QCheckBox" name="m_pCheckBoxEnableCrypto"> <number>2</number>
<property name="enabled"> </property>
<bool>false</bool> <property name="topMargin">
</property> <number>12</number>
<property name="text"> </property>
<string>Use &amp;TLS encryption</string> <property name="rightMargin">
</property> <number>2</number>
</widget> </property>
</item> <property name="bottomMargin">
<number>12</number>
</property>
<item row="0" column="1"> <item row="0" column="1">
<spacer name="horizontalSpacer"> <layout class="QGridLayout" name="m_pGridLayoutNetwork">
<property name="orientation"> <property name="leftMargin">
<enum>Qt::Horizontal</enum> <number>0</number>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="verticalSpacing">
<size> <number>12</number>
<width>40</width>
<height>20</height>
</size>
</property> </property>
</spacer> <item row="1" column="0">
<widget class="QCheckBox" name="m_pCheckBoxEnableCrypto">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Enable &amp;TLS Encryption</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="m_pCheckBoxAutoConfig">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Enable Auto Config</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="m_pLabelInstallBonjour">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;#&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;Install Bonjour&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="m_pLabelProUpgrade">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://symless.com/account?source=gui&amp;amp;intent=upgrade&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;Upgrade to Pro&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item> </item>
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<widget class="QGroupBox" name="m_pGroupLog"> <widget class="QGroupBox" name="m_pGroupLog">
<property name="sizePolicy"> <property name="sizePolicy">
@ -290,10 +364,13 @@
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>20</width> <width>20</width>
<height>40</height> <height>10</height>
</size> </size>
</property> </property>
</spacer> </spacer>
@ -317,7 +394,6 @@
<tabstop>m_pLineEditInterface</tabstop> <tabstop>m_pLineEditInterface</tabstop>
<tabstop>m_pComboElevate</tabstop> <tabstop>m_pComboElevate</tabstop>
<tabstop>m_pCheckBoxAutoHide</tabstop> <tabstop>m_pCheckBoxAutoHide</tabstop>
<tabstop>m_pCheckBoxEnableCrypto</tabstop>
<tabstop>m_pComboLogLevel</tabstop> <tabstop>m_pComboLogLevel</tabstop>
<tabstop>m_pCheckBoxLogToFile</tabstop> <tabstop>m_pCheckBoxLogToFile</tabstop>
<tabstop>m_pLineEditLogFilename</tabstop> <tabstop>m_pLineEditLogFilename</tabstop>

View File

@ -126,9 +126,6 @@ void SetupWizard::accept()
if (m_StartMain) if (m_StartMain)
{ {
#ifndef SYNERGY_ENTERPRISE
m_MainWindow.updateZeroconfService();
#endif
m_MainWindow.open(); m_MainWindow.open();
} }
} }

58
src/gui/src/Zeroconf.cpp Normal file
View File

@ -0,0 +1,58 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012-2018 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 "Zeroconf.h"
#include "ZeroconfService.h"
#include "MainWindow.h"
Zeroconf::Zeroconf(MainWindow* mainWindow) :
m_pMainWindow(mainWindow),
m_pZeroconfService(nullptr)
{
}
Zeroconf::~Zeroconf()
{
stopService();
}
void Zeroconf::startService()
{
if (m_pZeroconfService != nullptr) {
m_pMainWindow->appendLogInfo("restarting zeroconf service");
delete m_pZeroconfService;
m_pZeroconfService = nullptr;
}
else {
m_pMainWindow->appendLogInfo("starting zeroconf service");
}
m_pZeroconfService = new ZeroconfService(m_pMainWindow);
m_pMainWindow->appendLogInfo("started zeroconf service");
}
void Zeroconf::stopService()
{
if (m_pZeroconfService != nullptr) {
m_pMainWindow->appendLogInfo("stopping zeroconf service");
delete m_pZeroconfService;
m_pZeroconfService = nullptr;
m_pMainWindow->appendLogInfo("stopped zeroconf service");
}
}

38
src/gui/src/Zeroconf.h Normal file
View File

@ -0,0 +1,38 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012-2018 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 <QObject>
class MainWindow;
class ZeroconfService;
class Zeroconf : public QObject
{
Q_OBJECT
public:
Zeroconf(MainWindow* mainWindow);
virtual ~Zeroconf();
void startService();
void stopService();
private:
MainWindow* m_pMainWindow;
ZeroconfService* m_pZeroconfService;
};

View File

@ -38,8 +38,8 @@ const char* ZeroconfService:: m_ClientServiceName = "_synergyClient._tcp";
ZeroconfService::ZeroconfService(MainWindow* mainWindow) : ZeroconfService::ZeroconfService(MainWindow* mainWindow) :
m_pMainWindow(mainWindow), m_pMainWindow(mainWindow),
m_pZeroconfBrowser(0), m_pZeroconfBrowser(nullptr),
m_pZeroconfRegister(0), m_pZeroconfRegister(nullptr),
m_ServiceRegistered(false) m_ServiceRegistered(false)
{ {
if (m_pMainWindow->synergyType() == MainWindow::synergyServer) { if (m_pMainWindow->synergyType() == MainWindow::synergyServer) {
@ -81,7 +81,7 @@ void ZeroconfService::serverDetected(const QList<ZeroconfRecord>& list)
registerService(false); registerService(false);
m_pMainWindow->appendLogInfo(tr("zeroconf server detected: %1").arg( m_pMainWindow->appendLogInfo(tr("zeroconf server detected: %1").arg(
record.serviceName)); record.serviceName));
m_pMainWindow->serverDetected(record.serviceName); m_pMainWindow->zeroconfServerDetected(record.serviceName);
} }
} }
@ -96,7 +96,8 @@ void ZeroconfService::clientDetected(const QList<ZeroconfRecord>& list)
void ZeroconfService::errorHandle(DNSServiceErrorType errorCode) void ZeroconfService::errorHandle(DNSServiceErrorType errorCode)
{ {
QMessageBox::critical(0, tr("Zero configuration service"), QMessageBox::critical(
m_pMainWindow, tr("Synergy Auto Config"),
tr("Error code: %1.").arg(errorCode)); tr("Error code: %1.").arg(errorCode));
} }
@ -127,8 +128,9 @@ bool ZeroconfService::registerService(bool server)
if (!m_ServiceRegistered) { if (!m_ServiceRegistered) {
if (!m_zeroconfServer.listen()) { if (!m_zeroconfServer.listen()) {
QMessageBox::critical(0, tr("Zero configuration service"), QMessageBox::critical(
tr("Unable to start the zeroconf: %1.") m_pMainWindow, tr("Synergy Auto Config"),
tr("Unable to start zeroconf: %1.")
.arg(m_zeroconfServer.errorString())); .arg(m_zeroconfServer.errorString()));
result = false; result = false;
} }
@ -137,7 +139,8 @@ bool ZeroconfService::registerService(bool server)
if (server) { if (server) {
QString localIP = getLocalIPAddresses(); QString localIP = getLocalIPAddresses();
if (localIP.isEmpty()) { if (localIP.isEmpty()) {
QMessageBox::warning(m_pMainWindow, tr("Synergy"), QMessageBox::warning(
m_pMainWindow, tr("Synergy Auto Config"),
tr("Failed to get local IP address. " tr("Failed to get local IP address. "
"Please manually type in server address " "Please manually type in server address "
"on your clients")); "on your clients"));