Merge 1.4.1 into trunk

This commit is contained in:
Nick Bolton 2010-06-12 17:20:54 +00:00
parent 1698161945
commit a8eb2a3bfd
27 changed files with 841 additions and 351 deletions

View File

@ -27,6 +27,6 @@
int int
main(int argc, char** argv) main(int argc, char** argv)
{ {
CClientApp app; CClientApp app(createTaskBarReceiver);
return app.run(argc, argv, createTaskBarReceiver); return app.run(argc, argv);
} }

View File

@ -27,6 +27,6 @@
int int
main(int argc, char** argv) main(int argc, char** argv)
{ {
CServerApp app; CServerApp app(createTaskBarReceiver);
return app.run(argc, argv, createTaskBarReceiver); return app.run(argc, argv);
} }

View File

@ -1,21 +1,20 @@
QT += network QT += network
TEMPLATE = app TEMPLATE = app
TARGET = qsynergy TARGET = qsynergy
DEPENDPATH += . res DEPENDPATH += . \
INCLUDEPATH += . src res
INCLUDEPATH += . \
FORMS += \ src
res/MainWindowBase.ui \ FORMS += res/MainWindowBase.ui \
res/AboutDialogBase.ui \ res/AboutDialogBase.ui \
res/ServerConfigDialogBase.ui \ res/ServerConfigDialogBase.ui \
res/ScreenSettingsDialogBase.ui \ res/ScreenSettingsDialogBase.ui \
res/ActionDialogBase.ui \ res/ActionDialogBase.ui \
res/HotkeyDialogBase.ui \ res/HotkeyDialogBase.ui \
res/SettingsDialogBase.ui \ res/SettingsDialogBase.ui \
res/LogDialogBase.ui res/LogDialogBase.ui \
SOURCES += \ res/WindowsServicesBase.ui
src/main.cpp \ SOURCES += src/main.cpp \
src/MainWindow.cpp \ src/MainWindow.cpp \
src/AboutDialog.cpp \ src/AboutDialog.cpp \
src/ServerConfig.cpp \ src/ServerConfig.cpp \
@ -36,9 +35,9 @@ SOURCES += \
src/LogDialog.cpp \ src/LogDialog.cpp \
src/SettingsDialog.cpp \ src/SettingsDialog.cpp \
src/AppConfig.cpp \ src/AppConfig.cpp \
src/QSynergyApplication.cpp src/QSynergyApplication.cpp \
HEADERS += \ src/WindowsServices.cpp
src/MainWindow.h \ HEADERS += src/MainWindow.h \
src/AboutDialog.h \ src/AboutDialog.h \
src/ServerConfig.h \ src/ServerConfig.h \
src/ServerConfigDialog.h \ src/ServerConfigDialog.h \
@ -58,10 +57,10 @@ HEADERS += \
src/LogDialog.h \ src/LogDialog.h \
src/SettingsDialog.h \ src/SettingsDialog.h \
src/AppConfig.h \ src/AppConfig.h \
src/QSynergyApplication.h src/QSynergyApplication.h \
src/WindowsServices.h
RESOURCES += res/QSynergy.qrc RESOURCES += res/QSynergy.qrc
RC_FILE = res/win/QSynergy.rc RC_FILE = res/win/QSynergy.rc
macx { macx {
QMAKE_INFO_PLIST = res/mac/QSynergy.plist QMAKE_INFO_PLIST = res/mac/QSynergy.plist
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4
@ -70,18 +69,15 @@ macx {
QSYNERGY_ICON.path = Contents/Resources QSYNERGY_ICON.path = Contents/Resources
QMAKE_BUNDLE_DATA += QSYNERGY_ICON QMAKE_BUNDLE_DATA += QSYNERGY_ICON
} }
debug { debug {
OBJECTS_DIR = tmp/debug OBJECTS_DIR = tmp/debug
MOC_DIR = tmp/debug MOC_DIR = tmp/debug
RCC_DIR = tmp/debug RCC_DIR = tmp/debug
} }
release { release {
OBJECTS_DIR = tmp/release OBJECTS_DIR = tmp/release
MOC_DIR = tmp/release MOC_DIR = tmp/release
RCC_DIR = tmp/release RCC_DIR = tmp/release
} }
Debug:DESTDIR = ../bin/Debug Debug:DESTDIR = ../bin/Debug
Release:DESTDIR = ../bin/Release Release:DESTDIR = ../bin/Release

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>400</width> <width>400</width>
<height>247</height> <height>260</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -19,13 +19,13 @@
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>400</width> <width>400</width>
<height>247</height> <height>260</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>400</width> <width>400</width>
<height>247</height> <height>260</height>
</size> </size>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -33,7 +33,7 @@
</property> </property>
<widget class="QWidget" name="centralwidget"> <widget class="QWidget" name="centralwidget">
<layout class="QGridLayout"> <layout class="QGridLayout">
<item row="6" column="3"> <item row="5" column="3">
<widget class="QPushButton" name="m_pButtonToggleStart"> <widget class="QPushButton" name="m_pButtonToggleStart">
<property name="text"> <property name="text">
<string>&amp;Start</string> <string>&amp;Start</string>
@ -133,19 +133,6 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="3" column="0" colspan="4">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0" colspan="4"> <item row="2" column="0" colspan="4">
<widget class="QGroupBox" name="m_pGroupClient"> <widget class="QGroupBox" name="m_pGroupClient">
<property name="sizePolicy"> <property name="sizePolicy">
@ -177,14 +164,14 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="6" column="1"> <item row="5" column="1">
<widget class="QLabel" name="m_pStatusLabel"> <widget class="QLabel" name="m_pStatusLabel">
<property name="text"> <property name="text">
<string>Ready</string> <string>Ready</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="2"> <item row="5" column="2">
<spacer> <spacer>
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
@ -201,7 +188,7 @@
</widget> </widget>
<action name="m_pActionAbout"> <action name="m_pActionAbout">
<property name="text"> <property name="text">
<string>&amp;About QSynergy...</string> <string>&amp;About Synergy+...</string>
</property> </property>
</action> </action>
<action name="m_pActionQuit"> <action name="m_pActionQuit">
@ -209,7 +196,7 @@
<string>&amp;Quit</string> <string>&amp;Quit</string>
</property> </property>
<property name="statusTip"> <property name="statusTip">
<string>Quit QSynergy.</string> <string>Quit</string>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+Q</string> <string>Ctrl+Q</string>
@ -217,10 +204,10 @@
</action> </action>
<action name="m_pActionStartSynergy"> <action name="m_pActionStartSynergy">
<property name="text"> <property name="text">
<string>&amp;Start Synergy</string> <string>&amp;Start</string>
</property> </property>
<property name="statusTip"> <property name="statusTip">
<string>Run synergy program.</string> <string>Run</string>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+S</string> <string>Ctrl+S</string>
@ -231,10 +218,10 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="text"> <property name="text">
<string>S&amp;top Synergy</string> <string>S&amp;top</string>
</property> </property>
<property name="statusTip"> <property name="statusTip">
<string>Stop Synergy program.</string> <string>Stop</string>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+T</string> <string>Ctrl+T</string>
@ -274,7 +261,7 @@
<string>Settings</string> <string>Settings</string>
</property> </property>
<property name="statusTip"> <property name="statusTip">
<string>Edit settings for QSynergy and synergy itself</string> <string>Edit settings</string>
</property> </property>
</action> </action>
<action name="m_pActionLogOutput"> <action name="m_pActionLogOutput">
@ -282,7 +269,12 @@
<string>Log output</string> <string>Log output</string>
</property> </property>
<property name="statusTip"> <property name="statusTip">
<string>Open a window with synergy's output</string> <string>Open a window with output</string>
</property>
</action>
<action name="m_pActionServices">
<property name="text">
<string>Services</string>
</property> </property>
</action> </action>
</widget> </widget>

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>372</width> <width>372</width>
<height>350</height> <height>412</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -15,7 +15,7 @@
</property> </property>
<layout class="QGridLayout"> <layout class="QGridLayout">
<item row="1" column="0" colspan="2"> <item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="m_pGroupBox_3"> <widget class="QGroupBox" name="m_pGroupAdvanced">
<property name="title"> <property name="title">
<string>&amp;Advanced</string> <string>&amp;Advanced</string>
</property> </property>
@ -81,7 +81,7 @@
</widget> </widget>
</item> </item>
<item row="2" column="0" colspan="2"> <item row="2" column="0" colspan="2">
<widget class="QGroupBox" name="m_pGroupRunOptions"> <widget class="QGroupBox" name="m_pGroupStart">
<property name="title"> <property name="title">
<string>&amp;Start</string> <string>&amp;Start</string>
</property> </property>
@ -89,14 +89,116 @@
<item> <item>
<widget class="QCheckBox" name="m_pCheckBoxAutoConnect"> <widget class="QCheckBox" name="m_pCheckBoxAutoConnect">
<property name="text"> <property name="text">
<string>A&amp;utomatically start synergy when QSynergy starts</string> <string>A&amp;utomatically start server or client when GUI starts</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="4" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="m_pGroupPrograms">
<property name="title">
<string>&amp;Programs</string>
</property>
<layout class="QGridLayout">
<item row="0" column="0" rowspan="2" colspan="3">
<layout class="QVBoxLayout" name="m_pVerticalLayout_2">
<item>
<widget class="QCheckBox" name="m_pCheckBoxAutoDetectPaths">
<property name="text">
<string>Auto detect program paths</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="m_pLabel_17">
<property name="whatsThis">
<string>This is the synergy client program, usually called synergyc or synergyc.exe.</string>
</property>
<property name="text">
<string>&amp;Client:</string>
</property>
<property name="buddy">
<cstring>m_pLineEditSynergyc</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="m_pLineEditSynergyc">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QPushButton" name="m_pButtonBrowseSynergyc">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="m_pLabel_18">
<property name="toolTip">
<string/>
</property>
<property name="whatsThis">
<string>This is the synergy server program, usually called synergys or synergys.exe.</string>
</property>
<property name="text">
<string>S&amp;erver:</string>
</property>
<property name="buddy">
<cstring>m_pLineEditSynergys</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="m_pLineEditSynergys">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QPushButton" name="m_pButtonBrowseSynergys">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QGroupBox" name="m_pGroupLog">
<property name="title">
<string>Logging</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="m_pLabel_3"> <widget class="QLabel" name="m_pLabel_3">
<property name="text"> <property name="text">
<string>&amp;Logging level:</string> <string>&amp;Logging level:</string>
@ -106,7 +208,31 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="1" column="0">
<widget class="QCheckBox" name="m_pCheckBoxLogToFile">
<property name="text">
<string>Log to file:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="m_pLineEditLogFilename">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="m_pButtonBrowseLog">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="m_pComboLogLevel"> <widget class="QComboBox" name="m_pComboLogLevel">
<item> <item>
<property name="text"> <property name="text">
@ -145,82 +271,6 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="4" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="m_pGroupBox_2">
<property name="title">
<string>&amp;Programs</string>
</property>
<layout class="QGridLayout">
<item row="3" column="0">
<widget class="QLabel" name="m_pLabel_17">
<property name="whatsThis">
<string>This is the synergy client program, usually called synergyc or synergyc.exe.</string>
</property>
<property name="text">
<string>&amp;Client:</string>
</property>
<property name="buddy">
<cstring>m_pLineEditSynergyc</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="m_pLineEditSynergyc"/>
</item>
<item row="3" column="2">
<widget class="QPushButton" name="m_pButtonBrowseSynergyc">
<property name="text">
<string>&amp;Browse...</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="m_pLabel_18">
<property name="toolTip">
<string/>
</property>
<property name="whatsThis">
<string>This is the synergy server program, usually called synergys or synergys.exe.</string>
</property>
<property name="text">
<string>S&amp;erver:</string>
</property>
<property name="buddy">
<cstring>m_pLineEditSynergys</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="m_pLineEditSynergys"/>
</item>
<item row="4" column="2">
<widget class="QPushButton" name="m_pButtonBrowseSynergys">
<property name="text">
<string>Bro&amp;wse...</string>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="2" colspan="3">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="m_pCheckBoxAutoDetectPaths">
<property name="text">
<string>Auto detect program paths</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -237,6 +287,9 @@
<tabstop>m_pLineEditInterface</tabstop> <tabstop>m_pLineEditInterface</tabstop>
<tabstop>m_pCheckBoxAutoConnect</tabstop> <tabstop>m_pCheckBoxAutoConnect</tabstop>
<tabstop>m_pComboLogLevel</tabstop> <tabstop>m_pComboLogLevel</tabstop>
<tabstop>m_pCheckBoxLogToFile</tabstop>
<tabstop>m_pLineEditLogFilename</tabstop>
<tabstop>m_pButtonBrowseLog</tabstop>
<tabstop>buttonBox</tabstop> <tabstop>buttonBox</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>

View File

@ -0,0 +1,161 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WindowsServicesBase</class>
<widget class="QDialog" name="WindowsServicesBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>264</width>
<height>200</height>
</rect>
</property>
<property name="windowTitle">
<string>Windows Services</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Server</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="m_pUninstallServer">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Uninstall</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="m_pInstallServer">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Install</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Client</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="m_pUninstallClient">
<property name="text">
<string>Uninstall</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="m_pInstallClient">
<property name="text">
<string>Install</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>To start and stop a service, use the Windows services snap-in.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>WindowsServicesBase</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>WindowsServicesBase</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -7,12 +7,24 @@
const char AppConfig::m_SynergysName[] = "synergys.exe"; const char AppConfig::m_SynergysName[] = "synergys.exe";
const char AppConfig::m_SynergycName[] = "synergyc.exe"; const char AppConfig::m_SynergycName[] = "synergyc.exe";
const char AppConfig::m_SynergyProgramDir[] = "bin/"; const char AppConfig::m_SynergyProgramDir[] = "bin/";
const char AppConfig::m_SynergyLogDir[] = "log/";
#else #else
const char AppConfig::m_SynergysName[] = "synergys"; const char AppConfig::m_SynergysName[] = "synergys";
const char AppConfig::m_SynergycName[] = "synergyc"; const char AppConfig::m_SynergycName[] = "synergyc";
const char AppConfig::m_SynergyProgramDir[] = "/usr/bin/"; const char AppConfig::m_SynergyProgramDir[] = "/usr/bin/";
const char AppConfig::m_SynergyLogDir[] = "/var/log/";
#endif #endif
static const char* logLevelNames[] =
{
"ERROR",
"WARNING",
"NOTE",
"INFO",
"DEBUG",
"DEBUG1",
"DEBUG2"
};
AppConfig::AppConfig(QSettings* settings) : AppConfig::AppConfig(QSettings* settings) :
m_pSettings(settings), m_pSettings(settings),
@ -34,6 +46,33 @@ AppConfig::~AppConfig()
saveSettings(); saveSettings();
} }
QString AppConfig::synergyLogDir()
{
#if defined(Q_OS_WIN)
// on windows, we want to log to program files
return QString(QDir::currentPath() + "/log/");
#else
// on unix, we'll log to the standard log dir
return "/var/log/";
#endif
}
void AppConfig::persistLogDir()
{
QDir dir = synergyLogDir();
// persist the log directory
if (!dir.exists())
{
dir.mkpath(dir.path());
}
}
QString AppConfig::logLevelText() const
{
return logLevelNames[logLevel()];
}
void AppConfig::loadSettings() void AppConfig::loadSettings()
{ {
m_AutoConnect = settings().value("autoConnectChecked", false).toBool(); m_AutoConnect = settings().value("autoConnectChecked", false).toBool();
@ -42,8 +81,10 @@ void AppConfig::loadSettings()
m_ScreenName = settings().value("screenName", QHostInfo::localHostName()).toString(); m_ScreenName = settings().value("screenName", QHostInfo::localHostName()).toString();
m_Port = settings().value("port", 24800).toInt(); m_Port = settings().value("port", 24800).toInt();
m_Interface = settings().value("interface").toString(); m_Interface = settings().value("interface").toString();
m_LogLevel = settings().value("logLevelIndex", 0).toInt(); m_LogLevel = settings().value("logLevel", 2).toInt();
m_AutoDetectPaths = settings().value("autoDetectPaths", true).toBool(); m_AutoDetectPaths = settings().value("autoDetectPaths", true).toBool();
m_LogToFile = settings().value("logToFile", true).toBool();
m_LogFilename = settings().value("logFilename", synergyLogDir() + "synergy.log").toString();
} }
void AppConfig::saveSettings() void AppConfig::saveSettings()
@ -54,7 +95,30 @@ void AppConfig::saveSettings()
settings().setValue("screenName", m_ScreenName); settings().setValue("screenName", m_ScreenName);
settings().setValue("port", m_Port); settings().setValue("port", m_Port);
settings().setValue("interface", m_Interface); settings().setValue("interface", m_Interface);
settings().setValue("logLevelIndex", m_LogLevel); settings().setValue("logLevel", m_LogLevel);
settings().setValue("autoDetectPaths", m_AutoDetectPaths); settings().setValue("autoDetectPaths", m_AutoDetectPaths);
settings().setValue("logToFile", m_LogToFile);
settings().setValue("logFilename", m_LogFilename);
} }
bool AppConfig::detectPath(const QString& name, QString& path)
{
// look in current working dir and default dir
QStringList searchDirs;
searchDirs.append("./");
searchDirs.append(synergyProgramDir());
// use the first valid path we find
for (int i = 0; i < searchDirs.length(); i++)
{
QFile f(searchDirs[i] + name);
if (f.exists())
{
path = f.fileName();
return true;
}
}
// nothing found!
return false;
}

View File

@ -25,10 +25,17 @@ class AppConfig
const QString& interface() const { return m_Interface; } const QString& interface() const { return m_Interface; }
int logLevel() const { return m_LogLevel; } int logLevel() const { return m_LogLevel; }
bool autoDetectPaths() const { return m_AutoDetectPaths; } bool autoDetectPaths() const { return m_AutoDetectPaths; }
bool logToFile() const { return m_LogToFile; }
const QString& logFilename() const { return m_LogFilename; }
QString logLevelText() const;
QString synergysName() const { return m_SynergysName; } QString synergysName() const { return m_SynergysName; }
QString synergycName() const { return m_SynergycName; } QString synergycName() const { return m_SynergycName; }
QString synergyProgramDir() const { return m_SynergyProgramDir; } QString synergyProgramDir() const { return m_SynergyProgramDir; }
QString synergyLogDir();
bool detectPath(const QString& name, QString& path);
void persistLogDir();
protected: protected:
QSettings& settings() { return *m_pSettings; } QSettings& settings() { return *m_pSettings; }
@ -40,6 +47,8 @@ class AppConfig
void setInterface(const QString& s) { m_Interface = s; } void setInterface(const QString& s) { m_Interface = s; }
void setLogLevel(int i) { m_LogLevel = i; } void setLogLevel(int i) { m_LogLevel = i; }
void setAutoDetectPaths(bool b) { m_AutoDetectPaths = b; } void setAutoDetectPaths(bool b) { m_AutoDetectPaths = b; }
void setLogToFile(bool b) { m_LogToFile = b; }
void setLogFilename(const QString& s) { m_LogFilename = s; }
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
@ -54,10 +63,13 @@ class AppConfig
QString m_Interface; QString m_Interface;
int m_LogLevel; int m_LogLevel;
bool m_AutoDetectPaths; bool m_AutoDetectPaths;
bool m_LogToFile;
QString m_LogFilename;
static const char m_SynergysName[]; static const char m_SynergysName[];
static const char m_SynergycName[]; static const char m_SynergycName[];
static const char m_SynergyProgramDir[]; static const char m_SynergyProgramDir[];
static const char m_SynergyLogDir[];
}; };
#endif #endif

View File

@ -17,6 +17,7 @@ class LogDialog : public QDialog, public Ui::LogDialogBase
public: public:
void append(const QString& s); void append(const QString& s);
void clear() { m_pLogOutput->clear(); }
public slots: public slots:
void readSynergyOutput(); void readSynergyOutput();

View File

@ -3,6 +3,7 @@
#include "ServerConfigDialog.h" #include "ServerConfigDialog.h"
#include "SettingsDialog.h" #include "SettingsDialog.h"
#include "LogDialog.h" #include "LogDialog.h"
#include "WindowsServices.h"
#include <QtCore> #include <QtCore>
#include <QtGui> #include <QtGui>
@ -22,18 +23,6 @@ static const char* synergyIconFiles[] =
":/res/icons/16x16/synergy-connected.png" ":/res/icons/16x16/synergy-connected.png"
}; };
static const char* logLevelNames[] =
{
"ERROR",
"WARNING",
"NOTE",
"INFO",
"DEBUG",
"DEBUG1",
"DEBUG2"
};
MainWindow::MainWindow(QWidget* parent) : MainWindow::MainWindow(QWidget* parent) :
QMainWindow(parent), QMainWindow(parent),
MainWindowBase(), MainWindowBase(),
@ -121,6 +110,9 @@ void MainWindow::createMenuBar()
pMenuFile->addSeparator(); pMenuFile->addSeparator();
pMenuFile->addAction(m_pActionQuit); pMenuFile->addAction(m_pActionQuit);
pMenuEdit->addAction(m_pActionSettings); pMenuEdit->addAction(m_pActionSettings);
#if defined(Q_OS_WIN)
pMenuEdit->addAction(m_pActionServices);
#endif
pMenuView->addAction(m_pActionLogOutput); pMenuView->addAction(m_pActionLogOutput);
pMenuWindow->addAction(m_pActionMinimize); pMenuWindow->addAction(m_pActionMinimize);
pMenuWindow->addAction(m_pActionRestore); pMenuWindow->addAction(m_pActionRestore);
@ -131,13 +123,6 @@ void MainWindow::createMenuBar()
void MainWindow::loadSettings() void MainWindow::loadSettings()
{ {
// gui
QRect rect = settings().value("windowGeometry", geometry()).toRect();
move(rect.x(), rect.y());
resize(rect.width(), rect.height());
// program settings
// the next two must come BEFORE loading groupServerChecked and groupClientChecked or // the next two must come BEFORE loading groupServerChecked and groupClientChecked or
// disabling and/or enabling the right widgets won't automatically work // disabling and/or enabling the right widgets won't automatically work
m_pRadioExternalConfig->setChecked(settings().value("externalConfig", false).toBool()); m_pRadioExternalConfig->setChecked(settings().value("externalConfig", false).toBool());
@ -163,13 +148,6 @@ void MainWindow::initConnections()
void MainWindow::saveSettings() void MainWindow::saveSettings()
{ {
// gui
settings().setValue("windowGeometry", geometry());
#if !defined(Q_OS_MAC)
settings().setValue("windowVisible", isVisible());
#endif
// program settings // program settings
settings().setValue("groupServerChecked", m_pGroupServer->isChecked()); settings().setValue("groupServerChecked", m_pGroupServer->isChecked());
settings().setValue("externalConfig", m_pRadioExternalConfig->isChecked()); settings().setValue("externalConfig", m_pRadioExternalConfig->isChecked());
@ -205,7 +183,7 @@ void MainWindow::startSynergy()
QString app; QString app;
QStringList args; QStringList args;
args << "-f" << "--debug" << logLevelNames[appConfig().logLevel()]; args << "-f" << "--debug" << appConfig().logLevelText();
if (!appConfig().screenName().isEmpty()) if (!appConfig().screenName().isEmpty())
args << "--name" << appConfig().screenName(); args << "--name" << appConfig().screenName();
@ -236,39 +214,9 @@ void MainWindow::startSynergy()
setSynergyState(synergyConnected); setSynergyState(synergyConnected);
} }
bool MainWindow::detectPath(const QString& name, QString& path)
{
// look in current working dir and default dir
QStringList searchDirs;
searchDirs.append("./");
searchDirs.append(appConfig().synergyProgramDir());
// use the first valid path we find
for (int i = 0; i < searchDirs.length(); i++)
{
QFile f(searchDirs[i] + name);
if (f.exists())
{
path = f.fileName();
return true;
}
}
// nothing found!
return false;
}
bool MainWindow::clientArgs(QStringList& args, QString& app) bool MainWindow::clientArgs(QStringList& args, QString& app)
{ {
if (appConfig().autoDetectPaths()) app = appPath(appConfig().synergycName(), appConfig().synergyc());
{
// actually returns bool, but ignore for now
detectPath(appConfig().synergycName(), app);
}
else
{
app = appConfig().synergyc();
}
if (!QFile::exists(app)) if (!QFile::exists(app))
{ {
@ -289,23 +237,76 @@ bool MainWindow::clientArgs(QStringList& args, QString& app)
return false; return false;
} }
if (appConfig().logToFile())
{
appConfig().persistLogDir();
args << "--log" << appConfig().logFilename();
}
args << m_pLineEditHostname->text() + ":" + QString::number(appConfig().port()); args << m_pLineEditHostname->text() + ":" + QString::number(appConfig().port());
return true; return true;
} }
bool MainWindow::serverArgs(QStringList& args, QString& app) QString MainWindow::configFilename()
{ {
if (appConfig().autoDetectPaths()) QString filename;
if (m_pRadioInternalConfig->isChecked())
{ {
// actually returns bool, but ignore for now // TODO: no need to use a temporary file, since we need it to
detectPath(appConfig().synergysName(), app); // be permenant (since it'll be used for Windows services, etc).
m_pTempConfigFile = new QTemporaryFile();
if (!m_pTempConfigFile->open())
{
QMessageBox::critical(this, tr("Cannot write configuration file"), tr("The temporary configuration file required to start synergy can not be written."));
return false;
}
serverConfig().save(*m_pTempConfigFile);
filename = m_pTempConfigFile->fileName();
m_pTempConfigFile->close();
} }
else else
{ {
app = appConfig().synergys(); if (!QFile::exists(m_pLineEditConfigFile->text()))
{
if (QMessageBox::warning(this, tr("Configuration filename invalid"),
tr("You have not filled in a valid configuration file for the synergy server. "
"Do you want to browse for the configuration file now?"), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes
|| !on_m_pButtonBrowseConfigFile_clicked())
return false;
} }
filename = m_pLineEditConfigFile->text();
}
return filename;
}
QString MainWindow::address()
{
return (!appConfig().interface().isEmpty() ? appConfig().interface() : "") + ":" + QString::number(appConfig().port());
}
QString MainWindow::appPath(const QString& name, const QString& defaultPath)
{
QString app;
if (appConfig().autoDetectPaths())
{
// actually returns bool, but ignore for now
appConfig().detectPath(name, app);
}
else
{
app = defaultPath;
}
return app;
}
bool MainWindow::serverArgs(QStringList& args, QString& app)
{
app = appPath(appConfig().synergysName(), appConfig().synergys());
if (!QFile::exists(app)) if (!QFile::exists(app))
{ {
if (QMessageBox::warning(this, tr("Synergy server not found"), tr("The executable for the synergy server does not exist. Do you want to browse for the synergy server now?"), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) if (QMessageBox::warning(this, tr("Synergy server not found"), tr("The executable for the synergy server does not exist. Do you want to browse for the synergy server now?"), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
@ -319,36 +320,13 @@ bool MainWindow::serverArgs(QStringList& args, QString& app)
appConfig().setSynergys(app); appConfig().setSynergys(app);
} }
if (m_pRadioInternalConfig->isChecked()) if (appConfig().logToFile())
{ {
m_pTempConfigFile = new QTemporaryFile(); appConfig().persistLogDir();
if (!m_pTempConfigFile->open()) args << "--log" << appConfig().logFilename();
{
QMessageBox::critical(this, tr("Cannot write configuration file"), tr("The temporary configuration file required to start synergy can not be written."));
return false;
} }
serverConfig().save(*m_pTempConfigFile); args << "-c" << configFilename() << "--address" << address();
args << "-c" << m_pTempConfigFile->fileName();
m_pTempConfigFile->close();
// the file will be removed from disk when the object is deleted; this happens in stopSynergy()
}
else
{
if (!QFile::exists(m_pLineEditConfigFile->text()))
{
if (QMessageBox::warning(this, tr("Configuration filename invalid"),
tr("You have not filled in a valid configuration file for the synergy server. "
"Do you want to browse for the configuration file now?"), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes
|| !on_m_pButtonBrowseConfigFile_clicked())
return false;
}
args << "-c" << m_pLineEditConfigFile->text();
}
args << "--address" << (!appConfig().interface().isEmpty() ? appConfig().interface() : "") + ":" + QString::number(appConfig().port());
return true; return true;
} }
@ -365,7 +343,9 @@ void MainWindow::stopSynergy()
setSynergyState(synergyDisconnected); setSynergyState(synergyDisconnected);
} }
delete m_pTempConfigFile; // HACK: deleting the object deletes the physical file, which is
// bad, since it could be in use by the Windows service!
//delete m_pTempConfigFile;
m_pTempConfigFile = NULL; m_pTempConfigFile = NULL;
} }
@ -460,6 +440,12 @@ void MainWindow::on_m_pActionSettings_triggered()
dlg.exec(); dlg.exec();
} }
void MainWindow::on_m_pActionServices_triggered()
{
WindowsServices dlg(this, appConfig());
dlg.exec();
}
void MainWindow::on_m_pActionLogOutput_triggered() void MainWindow::on_m_pActionLogOutput_triggered()
{ {
Q_ASSERT(m_pLogDialog); Q_ASSERT(m_pLogDialog);

View File

@ -54,6 +54,10 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
void setVisible(bool visible); void setVisible(bool visible);
int synergyType() const { return m_pGroupClient->isChecked() ? synergyClient : synergyServer; } int synergyType() const { return m_pGroupClient->isChecked() ? synergyClient : synergyServer; }
int synergyState() const { return m_SynergyState; } int synergyState() const { return m_SynergyState; }
QString hostname() const { return m_pLineEditHostname->text(); }
QString configFilename();
QString address();
QString appPath(const QString& name, const QString& defaultPath);
protected slots: protected slots:
void on_m_pGroupClient_toggled(bool on) { m_pGroupServer->setChecked(!on); } void on_m_pGroupClient_toggled(bool on) { m_pGroupServer->setChecked(!on); }
@ -63,6 +67,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
bool on_m_pActionSave_triggered(); bool on_m_pActionSave_triggered();
void on_m_pActionAbout_triggered(); void on_m_pActionAbout_triggered();
void on_m_pActionSettings_triggered(); void on_m_pActionSettings_triggered();
void on_m_pActionServices_triggered();
void on_m_pActionLogOutput_triggered(); void on_m_pActionLogOutput_triggered();
void synergyFinished(int exitCode, QProcess::ExitStatus); void synergyFinished(int exitCode, QProcess::ExitStatus);
void iconActivated(QSystemTrayIcon::ActivationReason reason); void iconActivated(QSystemTrayIcon::ActivationReason reason);
@ -87,7 +92,6 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
bool clientArgs(QStringList& args, QString& app); bool clientArgs(QStringList& args, QString& app);
bool serverArgs(QStringList& args, QString& app); bool serverArgs(QStringList& args, QString& app);
void setStatus(const QString& status); void setStatus(const QString& status);
bool detectPath(const QString& name, QString& path);
private: private:
QSettings m_Settings; QSettings m_Settings;

View File

@ -20,6 +20,8 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) :
m_pLineEditInterface->setText(appConfig().interface()); m_pLineEditInterface->setText(appConfig().interface());
m_pComboLogLevel->setCurrentIndex(appConfig().logLevel()); m_pComboLogLevel->setCurrentIndex(appConfig().logLevel());
m_pCheckBoxAutoDetectPaths->setChecked(appConfig().autoDetectPaths()); m_pCheckBoxAutoDetectPaths->setChecked(appConfig().autoDetectPaths());
m_pCheckBoxLogToFile->setChecked(appConfig().logToFile());
m_pLineEditLogFilename->setText(appConfig().logFilename());
} }
QString SettingsDialog::browseForSynergyc(QWidget* parent, const QString& programDir, const QString& synergycName) QString SettingsDialog::browseForSynergyc(QWidget* parent, const QString& programDir, const QString& synergycName)
@ -76,7 +78,29 @@ void SettingsDialog::accept()
appConfig().setInterface(m_pLineEditInterface->text()); appConfig().setInterface(m_pLineEditInterface->text());
appConfig().setLogLevel(m_pComboLogLevel->currentIndex()); appConfig().setLogLevel(m_pComboLogLevel->currentIndex());
appConfig().setAutoDetectPaths(m_pCheckBoxAutoDetectPaths->isChecked()); appConfig().setAutoDetectPaths(m_pCheckBoxAutoDetectPaths->isChecked());
appConfig().setLogToFile(m_pCheckBoxLogToFile->isChecked());
appConfig().setLogFilename(m_pLineEditLogFilename->text());
QDialog::accept(); QDialog::accept();
} }
void SettingsDialog::on_m_pCheckBoxLogToFile_stateChanged(int i)
{
bool checked = i == 2;
m_pLineEditLogFilename->setEnabled(checked);
m_pButtonBrowseLog->setEnabled(checked);
}
void SettingsDialog::on_m_pButtonBrowseLog_clicked()
{
QString fileName = QFileDialog::getSaveFileName(
this, tr("Save log file to..."),
m_pLineEditLogFilename->text(),
"Logs (*.log *.txt)");
if (!fileName.isEmpty())
{
m_pLineEditLogFilename->setText(fileName);
}
}

View File

@ -13,22 +13,22 @@ class SettingsDialog : public QDialog, public Ui::SettingsDialogBase
public: public:
SettingsDialog(QWidget* parent, AppConfig& config); SettingsDialog(QWidget* parent, AppConfig& config);
public:
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);
protected slots:
bool on_m_pButtonBrowseSynergys_clicked();
bool on_m_pButtonBrowseSynergyc_clicked();
void on_m_pCheckBoxAutoDetectPaths_stateChanged(int i);
protected: protected:
void accept(); void accept();
AppConfig& appConfig() { return m_AppConfig; } AppConfig& appConfig() { return m_AppConfig; }
private: private:
AppConfig& m_AppConfig; AppConfig& m_AppConfig;
private slots:
void on_m_pCheckBoxLogToFile_stateChanged(int );
bool on_m_pButtonBrowseSynergys_clicked();
bool on_m_pButtonBrowseSynergyc_clicked();
void on_m_pCheckBoxAutoDetectPaths_stateChanged(int i);
void on_m_pButtonBrowseLog_clicked();
}; };
#endif #endif

130
gui/src/WindowsServices.cpp Normal file
View File

@ -0,0 +1,130 @@
#include "WindowsServices.h"
#include "AppConfig.h"
#include "MainWindow.h"
#include "LogDialog.h"
#include <QWidget>
#include <QProcess>
#include <QMessageBox>
#include <QPushButton>
WindowsServices::WindowsServices(QWidget* parent, AppConfig& appConfig) :
QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
Ui::WindowsServicesBase(),
m_appConfig(appConfig),
m_log(new LogDialog(this, process()))
{
setupUi(this);
}
void WindowsServices::runProc(const QString& app, const QStringList& args, QPushButton* button)
{
// disable until we know we've finished
button->setEnabled(false);
// clear contents so user doesn't get confused by previous messages
m_log->clear();
// deleted at end of function
QProcess proc(this);
m_process = &proc;
// send output to log window
connect(m_process, SIGNAL(readyReadStandardOutput()), m_log, SLOT(readSynergyOutput()));
connect(m_process, SIGNAL(readyReadStandardError()), m_log, SLOT(readSynergyOutput()));
m_process->start(app, args);
m_log->show();
// service management should be instant
m_process->waitForFinished();
if (m_process->exitCode() == 0)
{
QMessageBox::information(m_log, "Service manager", "Completed successfully.");
}
else
{
QMessageBox::critical(
m_log, "Service manager error",
QString("Unable to install or uninstall service. Error code: " +
QString::number(m_process->exitCode())));
}
disconnect(m_process, SIGNAL(readyReadStandardOutput()), m_log, SLOT(readSynergyOutput()));
disconnect(m_process, SIGNAL(readyReadStandardError()), m_log, SLOT(readSynergyOutput()));
button->setEnabled(true);
}
void WindowsServices::on_m_pInstallServer_clicked()
{
QString app = mainWindow()->appPath(
appConfig().synergysName(), appConfig().synergys());
QStringList args;
args <<
"--service" << "install" <<
"--relaunch" <<
"--debug" << appConfig().logLevelText() <<
"-c" << mainWindow()->configFilename() <<
"--address" << mainWindow()->address();
if (appConfig().logToFile())
{
appConfig().persistLogDir();
args << "--log" << appConfig().logFilename();
}
runProc(app, args, m_pInstallServer);
}
void WindowsServices::on_m_pUninstallServer_clicked()
{
QString app = mainWindow()->appPath(
appConfig().synergysName(), appConfig().synergys());
QStringList args;
args << "--service" << "uninstall";
runProc(app, args, m_pInstallServer);
}
void WindowsServices::on_m_pInstallClient_clicked()
{
if (mainWindow()->hostname().isEmpty())
{
QMessageBox::critical(
this, "Service manager error", "Hostname was not specified on main screen.");
return;
}
QString app = mainWindow()->appPath(
appConfig().synergycName(), appConfig().synergyc());
QStringList args;
args <<
"--service" << "install" <<
"--relaunch" <<
"--debug" << appConfig().logLevelText();
if (appConfig().logToFile())
{
appConfig().persistLogDir();
args << "--log" << appConfig().logFilename();
}
// hostname must come last to be a valid arg
args << mainWindow()->hostname();
runProc(app, args, m_pInstallServer);
}
void WindowsServices::on_m_pUninstallClient_clicked()
{
QString app = mainWindow()->appPath(
appConfig().synergycName(), appConfig().synergyc());
QStringList args;
args << "--service" << "uninstall";
runProc(app, args, m_pInstallServer);
}

41
gui/src/WindowsServices.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef WINDOWSSERVICES_H
#define WINDOWSSERVICES_H
#include "ui_WindowsServicesBase.h"
class QWidget;
class QProcess;
class QPushButton;
class QProcess;
class AppConfig;
class MainWindow;
class LogDialog;
class WindowsServices : public QDialog, public Ui::WindowsServicesBase
{
Q_OBJECT
public:
WindowsServices(QWidget* parent, AppConfig& appConfig);
protected:
AppConfig &appConfig() const { return m_appConfig; }
MainWindow* mainWindow() const { return (MainWindow*)parent(); }
QProcess*& process() { return m_process; }
void runProc(const QString& app, const QStringList& args, QPushButton* button);
private:
QString m_app;
AppConfig &m_appConfig;
QProcess* m_process;
LogDialog* m_log;
private slots:
void on_m_pUninstallClient_clicked();
void on_m_pInstallClient_clicked();
void on_m_pUninstallServer_clicked();
void on_m_pInstallServer_clicked();
};
#endif // WINDOWSSERVICES_H

View File

@ -666,9 +666,9 @@ CArch::app() const
} }
int int
CArch::run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver) CArch::run(int argc, char** argv)
{ {
return m_appUtil->run(argc, argv, createTaskBarReceiver); return m_appUtil->run(argc, argv);
} }
void void

View File

@ -186,7 +186,7 @@ public:
virtual bool parseArg(const int& argc, const char* const* argv, int& i); virtual bool parseArg(const int& argc, const char* const* argv, int& i);
virtual void adoptApp(CApp* app); virtual void adoptApp(CApp* app);
virtual CApp& app() const; virtual CApp& app() const;
virtual int run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver); virtual int run(int argc, char** argv);
virtual void beforeAppExit(); virtual void beforeAppExit();
// expose util so we don't need to re-implement all the functions // expose util so we don't need to re-implement all the functions

View File

@ -43,11 +43,14 @@ CArchAppUtilWindows::~CArchAppUtilWindows()
} }
BOOL WINAPI CArchAppUtilWindows::consoleHandler(DWORD CEvent) BOOL WINAPI CArchAppUtilWindows::consoleHandler(DWORD CEvent)
{
if (instance().app().m_taskBarReceiver)
{ {
// HACK: it would be nice to delete the s_taskBarReceiver object, but // HACK: it would be nice to delete the s_taskBarReceiver object, but
// this is best done by the CApp destructor; however i don't feel like // this is best done by the CApp destructor; however i don't feel like
// opening up that can of worms today... i need sleep. // opening up that can of worms today... i need sleep.
instance().app().s_taskBarReceiver->cleanup(); instance().app().m_taskBarReceiver->cleanup();
}
ExitProcess(kExitTerminated); ExitProcess(kExitTerminated);
return TRUE; return TRUE;
@ -83,8 +86,17 @@ CArchAppUtilWindows::parseArg(const int& argc, const char* const* argv, int& i)
app().argsBase().m_debugServiceWait = true; app().argsBase().m_debugServiceWait = true;
} }
else if (app().isArg(i, argc, argv, NULL, "--relaunch")) { else if (app().isArg(i, argc, argv, NULL, "--relaunch")) {
app().argsBase().m_relaunchMode = true; app().argsBase().m_relaunchMode = true;
} }
else if (app().isArg(i, argc, argv, NULL, "--exit-pause")) {
app().argsBase().m_pauseOnExit = true;
}
else if (app().isArg(i, argc, argv, NULL, "--no-tray")) {
app().argsBase().m_disableTray = true;
}
else { else {
// option not supported here // option not supported here
return false; return false;
@ -258,20 +270,17 @@ foregroundStartupStatic(int argc, char** argv)
void void
CArchAppUtilWindows::beforeAppExit() CArchAppUtilWindows::beforeAppExit()
{ {
CString name; // this can be handy for debugging, since the application is launched in
CArchMiscWindows::getParentProcessName(name); // a new console window, and will normally close on exit (making it so
// that we can't see error messages).
// if the user did not launch from the command prompt (i.e. it was launched if (app().argsBase().m_pauseOnExit) {
// by double clicking, or through a debugger), allow user to read any error
// messages (instead of the window closing automatically).
if (name != "cmd.exe") {
std::cout << std::endl << "Press any key to exit..." << std::endl; std::cout << std::endl << "Press any key to exit..." << std::endl;
int c = _getch(); int c = _getch();
} }
} }
int int
CArchAppUtilWindows::run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver) CArchAppUtilWindows::run(int argc, char** argv)
{ {
// record window instance for tray icon, etc // record window instance for tray icon, etc
CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL)); CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
@ -287,7 +296,7 @@ CArchAppUtilWindows::run(int argc, char** argv, CreateTaskBarReceiverFunc create
app().argsBase().m_daemon = false; app().argsBase().m_daemon = false;
} }
return app().runInner(argc, argv, NULL, startup, createTaskBarReceiver); return app().runInner(argc, argv, NULL, startup);
} }
CArchAppUtilWindows& CArchAppUtilWindows&

View File

@ -58,7 +58,7 @@ public:
void debugServiceWait(); void debugServiceWait();
int run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver); int run(int argc, char** argv);
void exitApp(int code); void exitApp(int code);

View File

@ -25,7 +25,7 @@ public:
virtual bool parseArg(const int& argc, const char* const* argv, int& i) = 0; virtual bool parseArg(const int& argc, const char* const* argv, int& i) = 0;
virtual void adoptApp(CApp* app) = 0; virtual void adoptApp(CApp* app) = 0;
virtual CApp& app() const = 0; virtual CApp& app() const = 0;
virtual int run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver) = 0; virtual int run(int argc, char** argv) = 0;
virtual void beforeAppExit() = 0; virtual void beforeAppExit() = 0;
virtual void startNode() = 0; virtual void startNode() = 0;
}; };

View File

@ -30,7 +30,7 @@ CMSWindowsRelauncher::startAsync()
void void
CMSWindowsRelauncher::startThread(void*) CMSWindowsRelauncher::startThread(void*)
{ {
LOG((CLOG_DEBUG "starting relaunch loop")); LOG((CLOG_NOTE "starting relaunch service"));
int ret = relaunchLoop(); int ret = relaunchLoop();
// HACK: this actually throws an exception to exit with 0 (nasty) // HACK: this actually throws an exception to exit with 0 (nasty)

View File

@ -30,11 +30,12 @@
CApp* CApp::s_instance = nullptr; CApp* CApp::s_instance = nullptr;
CApp::CApp(CArgsBase* args) : CApp::CApp(CreateTaskBarReceiverFunc createTaskBarReceiver, CArgsBase* args) :
m_createTaskBarReceiver(createTaskBarReceiver),
m_args(args), m_args(args),
m_bye(&exit), m_bye(&exit),
s_taskBarReceiver(NULL), m_taskBarReceiver(NULL),
s_suspended(false) m_suspended(false)
{ {
assert(s_instance == nullptr); assert(s_instance == nullptr);
s_instance = this; s_instance = this;
@ -50,6 +51,8 @@ CApp::CArgsBase::CArgsBase() :
m_daemon(false), // daemon mode not supported on windows (use --service) m_daemon(false), // daemon mode not supported on windows (use --service)
m_debugServiceWait(false), m_debugServiceWait(false),
m_relaunchMode(false), m_relaunchMode(false),
m_pauseOnExit(false),
m_disableTray(false),
#else #else
m_daemon(true), // backward compatibility for unix (daemon by default) m_daemon(true), // backward compatibility for unix (daemon by default)
#endif #endif
@ -232,7 +235,7 @@ CApp::version()
} }
int int
CApp::run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver) CApp::run(int argc, char** argv)
{ {
#if SYSAPI_WIN32 #if SYSAPI_WIN32
// record window instance for tray icon, etc // record window instance for tray icon, etc
@ -251,7 +254,7 @@ CApp::run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver
int result = kExitFailed; int result = kExitFailed;
try { try {
result = ARCH->run(argc, argv, createTaskBarReceiver); result = ARCH->run(argc, argv);
} }
catch (XExitApp& e) { catch (XExitApp& e) {
// instead of showing a nasty error, just exit with the error code. // instead of showing a nasty error, just exit with the error code.
@ -322,4 +325,16 @@ CApp::initApp(int argc, const char** argv)
// load configuration // load configuration
loadConfig(); loadConfig();
if (!argsBase().m_disableTray) {
// create a log buffer so we can show the latest message
// as a tray icon tooltip
CBufferedLogOutputter* logBuffer = new CBufferedLogOutputter(1000);
CLOG->insert(logBuffer, true);
// make the task bar receiver. the user can control this app
// through the task bar.
m_taskBarReceiver = m_createTaskBarReceiver(logBuffer);
}
} }

View File

@ -44,10 +44,12 @@ public:
#if SYSAPI_WIN32 #if SYSAPI_WIN32
bool m_relaunchMode; bool m_relaunchMode;
bool m_debugServiceWait; bool m_debugServiceWait;
bool m_pauseOnExit;
bool m_disableTray;
#endif #endif
}; };
CApp(CArgsBase* args); CApp(CreateTaskBarReceiverFunc createTaskBarReceiver, CArgsBase* args);
virtual ~CApp(); virtual ~CApp();
// Returns args that are common between server and client. // Returns args that are common between server and client.
@ -62,7 +64,7 @@ public:
// Parse command line arguments. // Parse command line arguments.
virtual void parseArgs(int argc, const char* const* argv) = 0; virtual void parseArgs(int argc, const char* const* argv) = 0;
int run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver); int run(int argc, char** argv);
int daemonMainLoop(int, const char**); int daemonMainLoop(int, const char**);
@ -71,7 +73,7 @@ public:
virtual int mainLoop() = 0; virtual int mainLoop() = 0;
virtual int foregroundStartup(int argc, char** argv) = 0; virtual int foregroundStartup(int argc, char** argv) = 0;
virtual int standardStartup(int argc, char** argv) = 0; virtual int standardStartup(int argc, char** argv) = 0;
virtual int runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup, CreateTaskBarReceiverFunc createTaskBarReceiver) = 0; virtual int runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup) = 0;
// Name of the daemon (used for Unix and Windows). // Name of the daemon (used for Unix and Windows).
virtual const char* daemonName() const = 0; virtual const char* daemonName() const = 0;
@ -90,8 +92,8 @@ public:
static CApp& instance() { assert(s_instance != nullptr); return *s_instance; } static CApp& instance() { assert(s_instance != nullptr); return *s_instance; }
bool s_suspended; bool m_suspended;
IArchTaskBarReceiver* s_taskBarReceiver; IArchTaskBarReceiver* m_taskBarReceiver;
// If --log was specified in args, then add a file logger. // If --log was specified in args, then add a file logger.
void setupFileLogging(); void setupFileLogging();
@ -118,6 +120,7 @@ private:
CArgsBase* m_args; CArgsBase* m_args;
static CApp* s_instance; static CApp* s_instance;
CFileLogOutputter* m_fileLog; CFileLogOutputter* m_fileLog;
CreateTaskBarReceiverFunc m_createTaskBarReceiver;
}; };
#define BYE "\nTry `%s --help' for more information." #define BYE "\nTry `%s --help' for more information."
@ -166,6 +169,9 @@ private:
" --service <action> manage the windows service, valid options are:\n" \ " --service <action> manage the windows service, valid options are:\n" \
" install/uninstall/start/stop\n" \ " install/uninstall/start/stop\n" \
" --relaunch persistently relaunches process in current user \n" \ " --relaunch persistently relaunches process in current user \n" \
" session (useful for vista and upward).\n" " session (useful for vista and upward).\n" \
" --exit-pause wait for key press on exit, can be useful for\n" \
" reading error messages that occur on exit.\n" \
" --no-tray disable the system tray icon.\n"
#endif #endif

View File

@ -49,8 +49,8 @@
#define RETRY_TIME 1.0 #define RETRY_TIME 1.0
CClientApp::CClientApp() : CClientApp::CClientApp(CreateTaskBarReceiverFunc createTaskBarReceiver) :
CApp(new CArgs()), CApp(createTaskBarReceiver, new CArgs()),
s_client(NULL), s_client(NULL),
s_clientScreen(NULL) s_clientScreen(NULL)
{ {
@ -168,6 +168,7 @@ CClientApp::help()
"Usage: %s" "Usage: %s"
" [--yscroll <delta>]" " [--yscroll <delta>]"
WINAPI_ARG WINAPI_ARG
HELP_SYS_ARGS
HELP_COMMON_ARGS HELP_COMMON_ARGS
" <server-address>" " <server-address>"
"\n\n" "\n\n"
@ -175,6 +176,7 @@ CClientApp::help()
"\n" "\n"
HELP_COMMON_INFO_1 HELP_COMMON_INFO_1
WINAPI_INFO WINAPI_INFO
HELP_SYS_INFO
" --yscroll <delta> defines the vertical scrolling delta, which is\n" " --yscroll <delta> defines the vertical scrolling delta, which is\n"
HELP_COMMON_INFO_2 HELP_COMMON_INFO_2
"\n" "\n"
@ -224,14 +226,17 @@ CClientApp::createScreen()
void void
CClientApp::updateStatus() CClientApp::updateStatus()
{ {
s_taskBarReceiver->updateStatus(s_client, ""); updateStatus("");
} }
void void
CClientApp::updateStatus(const CString& msg) CClientApp::updateStatus(const CString& msg)
{ {
s_taskBarReceiver->updateStatus(s_client, msg); if (m_taskBarReceiver)
{
m_taskBarReceiver->updateStatus(s_client, msg);
}
} }
@ -343,7 +348,7 @@ CClientApp::handleClientFailed(const CEvent& e, void*)
} }
else { else {
LOG((CLOG_WARN "failed to connect to server: %s", info->m_what.c_str())); LOG((CLOG_WARN "failed to connect to server: %s", info->m_what.c_str()));
if (!s_suspended) { if (!m_suspended) {
scheduleClientRestart(nextRestartTimeout()); scheduleClientRestart(nextRestartTimeout());
} }
} }
@ -358,7 +363,7 @@ CClientApp::handleClientDisconnected(const CEvent&, void*)
if (!args().m_restartable) { if (!args().m_restartable) {
EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
} }
else if (!s_suspended) { else if (!m_suspended) {
s_client->connect(); s_client->connect();
} }
updateStatus(); updateStatus();
@ -530,7 +535,7 @@ CClientApp::standardStartup(int argc, char** argv)
} }
int int
CClientApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup, CreateTaskBarReceiverFunc createTaskBarReceiver) CClientApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup)
{ {
// general initialization // general initialization
args().m_serverAddress = new CNetworkAddress; args().m_serverAddress = new CNetworkAddress;
@ -541,15 +546,6 @@ CClientApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFun
CLOG->insert(outputter); CLOG->insert(outputter);
} }
// save log messages
// use heap memory because CLog deletes outputters on destruction
CBufferedLogOutputter* logBuffer = new CBufferedLogOutputter(1000);
CLOG->insert(logBuffer, true);
// make the task bar receiver. the user can control this app
// through the task bar.
s_taskBarReceiver = createTaskBarReceiver(logBuffer);
int result; int result;
try try
{ {
@ -557,9 +553,12 @@ CClientApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFun
result = startup(argc, argv); result = startup(argc, argv);
} }
catch (...) catch (...)
{
if (m_taskBarReceiver)
{ {
// done with task bar receiver // done with task bar receiver
delete s_taskBarReceiver; delete m_taskBarReceiver;
}
delete args().m_serverAddress; delete args().m_serverAddress;

View File

@ -33,7 +33,7 @@ public:
CNetworkAddress* m_serverAddress; CNetworkAddress* m_serverAddress;
}; };
CClientApp(); CClientApp(CreateTaskBarReceiverFunc createTaskBarReceiver);
virtual ~CClientApp(); virtual ~CClientApp();
// Parse client specific command line arguments. // Parse client specific command line arguments.
@ -54,7 +54,7 @@ public:
int foregroundStartup(int argc, char** argv); int foregroundStartup(int argc, char** argv);
int standardStartup(int argc, char** argv); int standardStartup(int argc, char** argv);
int runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup, CreateTaskBarReceiverFunc createTaskBarReceiver); int runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup);
CScreen* createScreen(); CScreen* createScreen();
void updateStatus(); void updateStatus();
void updateStatus(const CString& msg); void updateStatus(const CString& msg);

View File

@ -50,8 +50,8 @@
CEvent::Type CServerApp::s_reloadConfigEvent = CEvent::kUnknown; CEvent::Type CServerApp::s_reloadConfigEvent = CEvent::kUnknown;
CServerApp::CServerApp() : CServerApp::CServerApp(CreateTaskBarReceiverFunc createTaskBarReceiver) :
CApp(new CArgs()), CApp(createTaskBarReceiver, new CArgs()),
s_server(NULL), s_server(NULL),
s_forceReconnectEvent(CEvent::kUnknown), s_forceReconnectEvent(CEvent::kUnknown),
s_resetServerEvent(CEvent::kUnknown), s_resetServerEvent(CEvent::kUnknown),
@ -370,12 +370,15 @@ CServerApp::stopRetryTimer()
void void
CServerApp::updateStatus() CServerApp::updateStatus()
{ {
s_taskBarReceiver->updateStatus(s_server, ""); updateStatus("");
} }
void CServerApp::updateStatus( const CString& msg ) void CServerApp::updateStatus( const CString& msg )
{ {
s_taskBarReceiver->updateStatus(s_server, msg); if (m_taskBarReceiver)
{
m_taskBarReceiver->updateStatus(s_server, msg);
}
} }
void void
@ -657,20 +660,20 @@ CServerApp::handleScreenError(const CEvent&, void*)
void void
CServerApp::handleSuspend(const CEvent&, void*) CServerApp::handleSuspend(const CEvent&, void*)
{ {
if (!s_suspended) { if (!m_suspended) {
LOG((CLOG_INFO "suspend")); LOG((CLOG_INFO "suspend"));
stopServer(); stopServer();
s_suspended = true; m_suspended = true;
} }
} }
void void
CServerApp::handleResume(const CEvent&, void*) CServerApp::handleResume(const CEvent&, void*)
{ {
if (s_suspended) { if (m_suspended) {
LOG((CLOG_INFO "resume")); LOG((CLOG_INFO "resume"));
startServer(); startServer();
s_suspended = false; m_suspended = false;
} }
} }
@ -796,7 +799,7 @@ void CServerApp::resetServer(const CEvent&, void*)
} }
int int
CServerApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup, CreateTaskBarReceiverFunc createTaskBarReceiver) CServerApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup)
{ {
// general initialization // general initialization
args().m_synergyAddress = new CNetworkAddress; args().m_synergyAddress = new CNetworkAddress;
@ -808,20 +811,14 @@ CServerApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFun
CLOG->insert(outputter); CLOG->insert(outputter);
} }
// save log messages
// use heap memory because CLog deletes outputters on destruction
CBufferedLogOutputter* logBuffer = new CBufferedLogOutputter(1000);
CLOG->insert(logBuffer, true);
// make the task bar receiver. the user can control this app
// through the task bar.
s_taskBarReceiver = createTaskBarReceiver(logBuffer);
// run // run
int result = startup(argc, argv); int result = startup(argc, argv);
if (m_taskBarReceiver)
{
// done with task bar receiver // done with task bar receiver
delete s_taskBarReceiver; delete m_taskBarReceiver;
}
delete args().m_config; delete args().m_config;
delete args().m_synergyAddress; delete args().m_synergyAddress;

View File

@ -49,7 +49,7 @@ public:
CConfig* m_config; CConfig* m_config;
}; };
CServerApp(); CServerApp(CreateTaskBarReceiverFunc createTaskBarReceiver);
virtual ~CServerApp(); virtual ~CServerApp();
// Parse server specific command line arguments. // Parse server specific command line arguments.
@ -99,7 +99,7 @@ public:
void handleNoClients(const CEvent&, void*); void handleNoClients(const CEvent&, void*);
bool startServer(); bool startServer();
int mainLoop(); int mainLoop();
int runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup, CreateTaskBarReceiverFunc createTaskBarReceiver); int runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup);
int standardStartup(int argc, char** argv); int standardStartup(int argc, char** argv);
int foregroundStartup(int argc, char** argv); int foregroundStartup(int argc, char** argv);
void startNode(); void startNode();