2016-08-25 00:45:32 +02:00
# include "./settingsdialog.h"
2018-04-11 23:15:15 +02:00
# include "../misc/syncthinglauncher.h"
2016-09-30 23:55:25 +02:00
# include "../../connector/syncthingconfig.h"
2017-05-01 03:34:43 +02:00
# include "../../connector/syncthingconnection.h"
2016-09-30 23:55:25 +02:00
# include "../../connector/syncthingprocess.h"
2018-11-01 19:55:08 +01:00
# include "../../connector/utils.h"
2016-12-18 16:50:35 +01:00
# ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
2017-05-01 03:34:43 +02:00
# include "../../connector/syncthingservice.h"
# include "../../model/colors.h"
2019-05-19 17:56:11 +02:00
# include "../../model/syncthingicons.h"
2016-12-18 16:50:35 +01:00
# endif
2016-08-25 00:45:32 +02:00
2016-08-29 20:51:30 +02:00
# include "ui_appearanceoptionpage.h"
2016-08-30 20:01:07 +02:00
# include "ui_autostartoptionpage.h"
2017-05-01 03:34:43 +02:00
# include "ui_connectionoptionpage.h"
2019-05-19 17:56:11 +02:00
# include "ui_iconsoptionpage.h"
2016-09-03 19:39:43 +02:00
# include "ui_launcheroptionpage.h"
2017-05-01 03:34:43 +02:00
# include "ui_notificationsoptionpage.h"
2016-12-18 16:50:35 +01:00
# ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
2017-05-01 03:34:43 +02:00
# include "ui_systemdoptionpage.h"
2016-12-18 16:50:35 +01:00
# endif
2016-08-25 00:45:32 +02:00
# include "ui_webviewoptionpage.h"
2017-04-23 18:27:31 +02:00
// use meta-data of syncthingtray application here
# include "resources/../../tray/resources/config.h"
2016-09-01 16:34:30 +02:00
2019-05-19 17:56:11 +02:00
# include <qtutilities/paletteeditor/colorbutton.h>
2016-08-25 00:45:32 +02:00
# include <qtutilities/settingsdialog/optioncategory.h>
# include <qtutilities/settingsdialog/optioncategorymodel.h>
# include <qtutilities/settingsdialog/qtsettings.h>
2019-07-07 12:59:47 +02:00
# include <qtutilities/widgets/iconbutton.h>
2016-12-11 17:58:58 +01:00
# ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
2017-05-01 03:34:43 +02:00
# include <qtutilities/misc/dbusnotification.h>
2016-12-11 17:58:58 +01:00
# endif
2016-12-18 16:50:35 +01:00
# ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
2017-05-01 03:34:43 +02:00
# include <c++utilities/chrono/datetime.h>
# include <qtutilities/misc/dialogutils.h>
2016-12-18 16:50:35 +01:00
# endif
2016-08-25 00:45:32 +02:00
2016-09-01 16:34:30 +02:00
# include <QFileDialog>
# include <QHostAddress>
2017-05-01 03:34:43 +02:00
# include <QMessageBox>
2016-09-03 19:39:43 +02:00
# if defined(PLATFORM_LINUX) && !defined(Q_OS_ANDROID)
2017-05-01 03:34:43 +02:00
# include <QStandardPaths>
2016-09-03 19:39:43 +02:00
# elif defined(PLATFORM_WINDOWS)
2017-05-01 03:34:43 +02:00
# include <QSettings>
2019-07-20 06:10:32 +02:00
# elif defined(PLATFORM_MAC)
# include <QFileInfo>
2016-09-03 19:39:43 +02:00
# endif
2016-12-27 16:38:33 +01:00
# include <QApplication>
2017-05-01 03:34:43 +02:00
# include <QFontDatabase>
2017-01-13 10:25:50 +01:00
# include <QStringBuilder>
2017-05-01 03:34:43 +02:00
# include <QStyle>
2019-07-07 14:31:09 +02:00
# include <QTextBlock>
2017-05-01 03:34:43 +02:00
# include <QTextCursor>
2016-09-01 16:34:30 +02:00
2016-08-25 00:45:32 +02:00
# include <functional>
using namespace std ;
2016-09-03 19:39:43 +02:00
using namespace std : : placeholders ;
2016-08-25 00:45:32 +02:00
using namespace Settings ;
using namespace Data ;
2019-06-10 22:48:26 +02:00
using namespace CppUtilities ;
using namespace QtUtilities ;
2016-08-25 00:45:32 +02:00
namespace QtGui {
// ConnectionOptionPage
2017-05-01 03:34:43 +02:00
ConnectionOptionPage : : ConnectionOptionPage ( Data : : SyncthingConnection * connection , QWidget * parentWidget )
: ConnectionOptionPageBase ( parentWidget )
, m_connection ( connection )
, m_currentIndex ( 0 )
{
}
2016-08-25 00:45:32 +02:00
ConnectionOptionPage : : ~ ConnectionOptionPage ( )
2017-05-01 03:34:43 +02:00
{
}
2016-08-25 00:45:32 +02:00
QWidget * ConnectionOptionPage : : setupWidget ( )
{
2018-02-19 19:46:26 +01:00
auto * const widget = ConnectionOptionPageBase : : setupWidget ( ) ;
2016-09-03 20:14:52 +02:00
ui ( ) - > certPathSelection - > provideCustomFileMode ( QFileDialog : : ExistingFile ) ;
2017-05-01 03:34:43 +02:00
ui ( ) - > certPathSelection - > lineEdit ( ) - > setPlaceholderText (
QCoreApplication : : translate ( " QtGui::ConnectionOptionPage " , " Auto-detected for local instance " ) ) ;
2016-12-27 16:38:33 +01:00
ui ( ) - > instanceNoteIcon - > setPixmap ( QApplication : : style ( ) - > standardIcon ( QStyle : : SP_MessageBoxInformation ) . pixmap ( 32 , 32 ) ) ;
2016-08-25 00:45:32 +02:00
QObject : : connect ( m_connection , & SyncthingConnection : : statusChanged , bind ( & ConnectionOptionPage : : updateConnectionStatus , this ) ) ;
QObject : : connect ( ui ( ) - > connectPushButton , & QPushButton : : clicked , bind ( & ConnectionOptionPage : : applyAndReconnect , this ) ) ;
2016-09-01 16:34:30 +02:00
QObject : : connect ( ui ( ) - > insertFromConfigFilePushButton , & QPushButton : : clicked , bind ( & ConnectionOptionPage : : insertFromConfigFile , this ) ) ;
2017-05-01 03:34:43 +02:00
QObject : : connect ( ui ( ) - > selectionComboBox , static_cast < void ( QComboBox : : * ) ( int ) > ( & QComboBox : : currentIndexChanged ) ,
bind ( & ConnectionOptionPage : : showConnectionSettings , this , _1 ) ) ;
QObject : : connect ( ui ( ) - > selectionComboBox , static_cast < void ( QComboBox : : * ) ( const QString & ) > ( & QComboBox : : editTextChanged ) ,
2017-09-07 16:42:24 +02:00
bind ( & ConnectionOptionPage : : saveCurrentConfigName , this , _1 ) ) ;
QObject : : connect ( ui ( ) - > downPushButton , & QPushButton : : clicked , bind ( & ConnectionOptionPage : : moveSelectedConfigDown , this ) ) ;
QObject : : connect ( ui ( ) - > upPushButton , & QPushButton : : clicked , bind ( & ConnectionOptionPage : : moveSelectedConfigUp , this ) ) ;
QObject : : connect ( ui ( ) - > addPushButton , & QPushButton : : clicked , bind ( & ConnectionOptionPage : : addNewConfig , this ) ) ;
QObject : : connect ( ui ( ) - > removePushButton , & QPushButton : : clicked , bind ( & ConnectionOptionPage : : removeSelectedConfig , this ) ) ;
2018-02-19 19:46:26 +01:00
return widget ;
2016-08-25 00:45:32 +02:00
}
2016-09-01 16:34:30 +02:00
void ConnectionOptionPage : : insertFromConfigFile ( )
{
2018-02-19 19:46:26 +01:00
auto configFile ( SyncthingConfig : : locateConfigFile ( ) ) ;
2017-09-07 16:42:24 +02:00
if ( configFile . isEmpty ( ) ) {
// allow user to select config file manually if it could not be located
configFile = QFileDialog : : getOpenFileName (
widget ( ) , QCoreApplication : : translate ( " QtGui::ConnectionOptionPage " , " Select Syncthing config file " ) + QStringLiteral ( " - " APP_NAME ) ) ;
}
if ( configFile . isEmpty ( ) ) {
return ;
}
SyncthingConfig config ;
if ( ! config . restore ( configFile ) ) {
QMessageBox : : critical ( widget ( ) , widget ( ) - > windowTitle ( ) + QStringLiteral ( " - " APP_NAME ) ,
QCoreApplication : : translate ( " QtGui::ConnectionOptionPage " , " Unable to parse the Syncthing config file. " ) ) ;
return ;
}
2018-11-01 19:55:08 +01:00
2017-09-07 16:42:24 +02:00
if ( ! config . guiAddress . isEmpty ( ) ) {
2018-11-01 19:55:08 +01:00
const auto portStart ( config . guiAddress . indexOf ( QChar ( ' : ' ) ) ) ;
QString guiHost ( config . guiAddress . mid ( 0 , portStart ) ) ;
const QStringRef guiPort ( portStart > 0 ? config . guiAddress . midRef ( portStart ) : QStringRef ( ) ) ;
const QHostAddress guiAddress ( guiHost ) ;
// assume local connection if address is eg. 0.0.0.0
auto localConnection = true ;
if ( guiAddress = = QHostAddress : : AnyIPv4 ) {
guiHost = QStringLiteral ( " 127.0.0.1 " ) ;
} else if ( guiAddress = = QHostAddress : : AnyIPv6 ) {
guiHost = QStringLiteral ( " [::1] " ) ;
} else if ( ! isLocal ( guiHost , guiAddress ) ) {
localConnection = false ;
}
const QString guiProtocol ( ( config . guiEnforcesSecureConnection | | ! localConnection ) ? QStringLiteral ( " https:// " ) : QStringLiteral ( " http:// " ) ) ;
2017-09-07 16:42:24 +02:00
ui ( ) - > urlLineEdit - > selectAll ( ) ;
2018-11-01 19:55:08 +01:00
ui ( ) - > urlLineEdit - > insert ( guiProtocol % guiHost % guiPort ) ;
2017-09-07 16:42:24 +02:00
}
if ( ! config . guiUser . isEmpty ( ) | | ! config . guiPasswordHash . isEmpty ( ) ) {
ui ( ) - > authCheckBox - > setChecked ( true ) ;
ui ( ) - > userNameLineEdit - > selectAll ( ) ;
ui ( ) - > userNameLineEdit - > insert ( config . guiUser ) ;
} else {
ui ( ) - > authCheckBox - > setChecked ( false ) ;
}
if ( ! config . guiApiKey . isEmpty ( ) ) {
ui ( ) - > apiKeyLineEdit - > selectAll ( ) ;
ui ( ) - > apiKeyLineEdit - > insert ( config . guiApiKey ) ;
2016-09-01 16:34:30 +02:00
}
}
2016-08-25 00:45:32 +02:00
void ConnectionOptionPage : : updateConnectionStatus ( )
{
2017-09-27 00:21:53 +02:00
ui ( ) - > statusLabel - > setText ( m_connection - > statusText ( ) ) ;
2016-08-25 00:45:32 +02:00
}
2016-09-03 20:14:52 +02:00
bool ConnectionOptionPage : : showConnectionSettings ( int index )
{
2017-09-07 16:42:24 +02:00
if ( index = = m_currentIndex ) {
return true ;
2016-09-03 20:14:52 +02:00
}
2017-09-07 16:42:24 +02:00
if ( ! cacheCurrentSettings ( false ) ) {
ui ( ) - > selectionComboBox - > setCurrentIndex ( m_currentIndex ) ;
return false ;
}
const SyncthingConnectionSettings & connectionSettings = ( index = = 0 ? m_primarySettings : m_secondarySettings [ static_cast < size_t > ( index - 1 ) ] ) ;
ui ( ) - > urlLineEdit - > setText ( connectionSettings . syncthingUrl ) ;
ui ( ) - > authCheckBox - > setChecked ( connectionSettings . authEnabled ) ;
ui ( ) - > userNameLineEdit - > setText ( connectionSettings . userName ) ;
ui ( ) - > passwordLineEdit - > setText ( connectionSettings . password ) ;
ui ( ) - > apiKeyLineEdit - > setText ( connectionSettings . apiKey ) ;
ui ( ) - > certPathSelection - > lineEdit ( ) - > setText ( connectionSettings . httpsCertPath ) ;
ui ( ) - > pollTrafficSpinBox - > setValue ( connectionSettings . trafficPollInterval ) ;
ui ( ) - > pollDevStatsSpinBox - > setValue ( connectionSettings . devStatsPollInterval ) ;
ui ( ) - > pollErrorsSpinBox - > setValue ( connectionSettings . errorsPollInterval ) ;
ui ( ) - > reconnectSpinBox - > setValue ( connectionSettings . reconnectInterval ) ;
setCurrentIndex ( index ) ;
return true ;
2016-09-03 20:14:52 +02:00
}
bool ConnectionOptionPage : : cacheCurrentSettings ( bool applying )
{
2017-09-07 16:42:24 +02:00
if ( m_currentIndex < 0 ) {
return true ;
}
SyncthingConnectionSettings & connectionSettings
= ( m_currentIndex = = 0 ? m_primarySettings : m_secondarySettings [ static_cast < size_t > ( m_currentIndex - 1 ) ] ) ;
connectionSettings . syncthingUrl = ui ( ) - > urlLineEdit - > text ( ) ;
connectionSettings . authEnabled = ui ( ) - > authCheckBox - > isChecked ( ) ;
connectionSettings . userName = ui ( ) - > userNameLineEdit - > text ( ) ;
connectionSettings . password = ui ( ) - > passwordLineEdit - > text ( ) ;
connectionSettings . apiKey = ui ( ) - > apiKeyLineEdit - > text ( ) . toUtf8 ( ) ;
connectionSettings . expectedSslErrors . clear ( ) ;
connectionSettings . httpsCertPath = ui ( ) - > certPathSelection - > lineEdit ( ) - > text ( ) ;
connectionSettings . trafficPollInterval = ui ( ) - > pollTrafficSpinBox - > value ( ) ;
connectionSettings . devStatsPollInterval = ui ( ) - > pollDevStatsSpinBox - > value ( ) ;
connectionSettings . errorsPollInterval = ui ( ) - > pollErrorsSpinBox - > value ( ) ;
connectionSettings . reconnectInterval = ui ( ) - > reconnectSpinBox - > value ( ) ;
if ( ! connectionSettings . loadHttpsCert ( ) ) {
const QString errorMessage = QCoreApplication : : translate ( " QtGui::ConnectionOptionPage " , " Unable to load specified certificate \" %1 \" . " )
. arg ( connectionSettings . httpsCertPath ) ;
if ( ! applying ) {
QMessageBox : : critical ( widget ( ) , QCoreApplication : : applicationName ( ) , errorMessage ) ;
} else {
errors ( ) < < errorMessage ;
2016-09-03 20:14:52 +02:00
}
2017-09-07 16:42:24 +02:00
return false ;
2016-09-03 20:14:52 +02:00
}
2017-09-07 16:42:24 +02:00
return true ;
2016-09-03 20:14:52 +02:00
}
2017-09-07 16:42:24 +02:00
void ConnectionOptionPage : : saveCurrentConfigName ( const QString & name )
2016-09-03 20:14:52 +02:00
{
const int index = ui ( ) - > selectionComboBox - > currentIndex ( ) ;
2017-05-01 03:34:43 +02:00
if ( index = = m_currentIndex & & index > = 0 ) {
2016-09-03 20:14:52 +02:00
( index = = 0 ? m_primarySettings : m_secondarySettings [ static_cast < size_t > ( index - 1 ) ] ) . label = name ;
ui ( ) - > selectionComboBox - > setItemText ( index , name ) ;
}
}
2017-09-07 16:42:24 +02:00
void ConnectionOptionPage : : addNewConfig ( )
2016-09-03 20:14:52 +02:00
{
m_secondarySettings . emplace_back ( ) ;
2017-05-01 03:34:43 +02:00
m_secondarySettings . back ( ) . label
= QCoreApplication : : translate ( " QtGui::ConnectionOptionPage " , " Instance %1 " ) . arg ( ui ( ) - > selectionComboBox - > count ( ) + 1 ) ;
2016-09-03 20:14:52 +02:00
ui ( ) - > selectionComboBox - > addItem ( m_secondarySettings . back ( ) . label ) ;
ui ( ) - > selectionComboBox - > setCurrentIndex ( ui ( ) - > selectionComboBox - > count ( ) - 1 ) ;
2017-09-07 16:42:24 +02:00
ui ( ) - > removePushButton - > setEnabled ( true ) ;
2016-09-03 20:14:52 +02:00
}
2017-09-07 16:42:24 +02:00
void ConnectionOptionPage : : removeSelectedConfig ( )
2016-09-03 20:14:52 +02:00
{
2017-09-07 16:42:24 +02:00
if ( m_secondarySettings . empty ( ) ) {
return ;
}
const int index = ui ( ) - > selectionComboBox - > currentIndex ( ) ;
2017-10-08 16:34:02 +02:00
if ( index < 0 | | static_cast < unsigned > ( index ) > m_secondarySettings . size ( ) ) {
2017-09-07 16:42:24 +02:00
return ;
}
if ( index = = 0 ) {
m_primarySettings = move ( m_secondarySettings . front ( ) ) ;
m_secondarySettings . erase ( m_secondarySettings . begin ( ) ) ;
} else {
2016-09-03 20:14:52 +02:00
m_secondarySettings . erase ( m_secondarySettings . begin ( ) + ( index - 1 ) ) ;
}
2017-09-07 16:42:24 +02:00
m_currentIndex = - 1 ;
ui ( ) - > selectionComboBox - > removeItem ( index ) ;
ui ( ) - > removePushButton - > setEnabled ( ! m_secondarySettings . empty ( ) ) ;
}
void ConnectionOptionPage : : moveSelectedConfigDown ( )
{
if ( m_secondarySettings . empty ( ) ) {
return ;
}
const int index = ui ( ) - > selectionComboBox - > currentIndex ( ) ;
if ( index < 0 ) {
return ;
}
if ( index = = 0 ) {
swap ( m_primarySettings , m_secondarySettings . front ( ) ) ;
ui ( ) - > selectionComboBox - > setItemText ( 0 , m_primarySettings . label ) ;
ui ( ) - > selectionComboBox - > setItemText ( 1 , m_secondarySettings . front ( ) . label ) ;
setCurrentIndex ( 1 ) ;
} else if ( static_cast < unsigned > ( index ) < m_secondarySettings . size ( ) ) {
SyncthingConnectionSettings & current = m_secondarySettings [ static_cast < unsigned > ( index ) - 1 ] ;
SyncthingConnectionSettings & exchange = m_secondarySettings [ static_cast < unsigned > ( index ) ] ;
swap ( current , exchange ) ;
ui ( ) - > selectionComboBox - > setItemText ( index , current . label ) ;
ui ( ) - > selectionComboBox - > setItemText ( index + 1 , exchange . label ) ;
setCurrentIndex ( index + 1 ) ;
}
ui ( ) - > selectionComboBox - > setCurrentIndex ( m_currentIndex ) ;
}
void ConnectionOptionPage : : moveSelectedConfigUp ( )
{
if ( m_secondarySettings . empty ( ) ) {
return ;
}
const int index = ui ( ) - > selectionComboBox - > currentIndex ( ) ;
if ( index < = 0 ) {
return ;
}
if ( index = = 1 ) {
swap ( m_primarySettings , m_secondarySettings . front ( ) ) ;
ui ( ) - > selectionComboBox - > setItemText ( 0 , m_primarySettings . label ) ;
ui ( ) - > selectionComboBox - > setItemText ( 1 , m_secondarySettings . front ( ) . label ) ;
setCurrentIndex ( 0 ) ;
} else if ( static_cast < unsigned > ( index ) - 1 < m_secondarySettings . size ( ) ) {
SyncthingConnectionSettings & current = m_secondarySettings [ static_cast < unsigned > ( index ) - 1 ] ;
SyncthingConnectionSettings & exchange = m_secondarySettings [ static_cast < unsigned > ( index ) - 2 ] ;
swap ( current , exchange ) ;
ui ( ) - > selectionComboBox - > setItemText ( index , current . label ) ;
ui ( ) - > selectionComboBox - > setItemText ( index - 1 , exchange . label ) ;
setCurrentIndex ( index - 1 ) ;
}
ui ( ) - > selectionComboBox - > setCurrentIndex ( m_currentIndex ) ;
}
void ConnectionOptionPage : : setCurrentIndex ( int currentIndex )
{
m_currentIndex = currentIndex ;
ui ( ) - > downPushButton - > setEnabled ( currentIndex > = 0 & & static_cast < unsigned > ( currentIndex ) < m_secondarySettings . size ( ) ) ;
ui ( ) - > upPushButton - > setEnabled ( currentIndex > 0 & & static_cast < unsigned > ( currentIndex ) - 1 < m_secondarySettings . size ( ) ) ;
2016-09-03 20:14:52 +02:00
}
2016-08-25 00:45:32 +02:00
bool ConnectionOptionPage : : apply ( )
{
2017-09-07 16:42:24 +02:00
if ( ! cacheCurrentSettings ( true ) ) {
return false ;
2016-08-25 00:45:32 +02:00
}
2017-09-07 16:42:24 +02:00
values ( ) . connection . primary = m_primarySettings ;
values ( ) . connection . secondary = m_secondarySettings ;
return true ;
2016-08-25 00:45:32 +02:00
}
void ConnectionOptionPage : : reset ( )
{
2017-09-07 16:42:24 +02:00
m_primarySettings = values ( ) . connection . primary ;
m_secondarySettings = values ( ) . connection . secondary ;
m_currentIndex = - 1 ;
2016-10-06 23:51:45 +02:00
2017-09-07 16:42:24 +02:00
QStringList itemTexts ;
itemTexts . reserve ( 1 + static_cast < int > ( m_secondarySettings . size ( ) ) ) ;
itemTexts < < m_primarySettings . label ;
for ( const SyncthingConnectionSettings & settings : m_secondarySettings ) {
itemTexts < < settings . label ;
2016-08-25 00:45:32 +02:00
}
2017-09-07 16:42:24 +02:00
ui ( ) - > selectionComboBox - > clear ( ) ;
ui ( ) - > selectionComboBox - > addItems ( itemTexts ) ;
ui ( ) - > selectionComboBox - > setCurrentIndex ( 0 ) ;
updateConnectionStatus ( ) ;
2016-08-25 00:45:32 +02:00
}
void ConnectionOptionPage : : applyAndReconnect ( )
{
apply ( ) ;
2016-10-06 23:51:45 +02:00
m_connection - > reconnect ( ( m_currentIndex = = 0 ? m_primarySettings : m_secondarySettings [ static_cast < size_t > ( m_currentIndex - 1 ) ] ) ) ;
2016-08-25 00:45:32 +02:00
}
// NotificationsOptionPage
2017-09-11 23:47:46 +02:00
NotificationsOptionPage : : NotificationsOptionPage ( GuiType guiType , QWidget * parentWidget )
2017-05-01 03:34:43 +02:00
: NotificationsOptionPageBase ( parentWidget )
2017-09-11 23:47:46 +02:00
, m_guiType ( guiType )
2017-05-01 03:34:43 +02:00
{
}
2016-08-25 00:45:32 +02:00
NotificationsOptionPage : : ~ NotificationsOptionPage ( )
2017-05-01 03:34:43 +02:00
{
}
2016-08-25 00:45:32 +02:00
2017-09-08 16:56:50 +02:00
QWidget * NotificationsOptionPage : : setupWidget ( )
{
2018-02-19 19:46:26 +01:00
auto * const widget = NotificationsOptionPageBase : : setupWidget ( ) ;
2017-09-11 23:47:46 +02:00
switch ( m_guiType ) {
case GuiType : : TrayWidget :
break ;
case GuiType : : Plasmoid :
ui ( ) - > apiGroupBox - > setHidden ( true ) ;
break ;
}
2018-02-19 19:46:26 +01:00
return widget ;
2017-09-08 16:56:50 +02:00
}
2016-08-25 00:45:32 +02:00
bool NotificationsOptionPage : : apply ( )
{
2016-12-11 17:58:58 +01:00
bool ok = true ;
2018-05-01 22:27:03 +02:00
auto & settings ( values ( ) ) ;
auto & notifyOn ( settings . notifyOn ) ;
2017-09-27 00:21:53 +02:00
notifyOn . disconnect = ui ( ) - > notifyOnDisconnectCheckBox - > isChecked ( ) ;
notifyOn . internalErrors = ui ( ) - > notifyOnErrorsCheckBox - > isChecked ( ) ;
2019-07-12 20:24:19 +02:00
notifyOn . launcherErrors = ui ( ) - > notifyOnLauncherErrorsCheckBox - > isChecked ( ) ;
2018-03-31 22:31:28 +02:00
notifyOn . localSyncComplete = ui ( ) - > notifyOnLocalSyncCompleteCheckBox - > isChecked ( ) ;
notifyOn . remoteSyncComplete = ui ( ) - > notifyOnRemoteSyncCompleteCheckBox - > isChecked ( ) ;
2017-09-27 00:21:53 +02:00
notifyOn . syncthingErrors = ui ( ) - > showSyncthingNotificationsCheckBox - > isChecked ( ) ;
2018-05-01 22:27:03 +02:00
notifyOn . newDeviceConnects = ui ( ) - > notifyOnNewDevConnectsCheckBox - > isChecked ( ) ;
notifyOn . newDirectoryShared = ui ( ) - > notifyOnNewDirSharedCheckBox - > isChecked ( ) ;
2016-12-11 17:58:58 +01:00
# ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
2018-05-01 22:27:03 +02:00
if ( ( settings . dbusNotifications = ui ( ) - > dbusRadioButton - > isChecked ( ) ) & & ! DBusNotification : : isAvailable ( ) ) {
2017-09-27 00:21:53 +02:00
errors ( ) < < QCoreApplication : : translate (
" QtGui::NotificationsOptionPage " , " Configured to use D-Bus notifications but D-Bus notification daemon seems unavailabe. " ) ;
ok = false ;
2016-08-25 00:45:32 +02:00
}
2017-09-27 00:21:53 +02:00
# endif
values ( ) . ignoreInavailabilityAfterStart = static_cast < unsigned int > ( ui ( ) - > ignoreInavailabilityAfterStartSpinBox - > value ( ) ) ;
2016-12-11 17:58:58 +01:00
return ok ;
2016-08-25 00:45:32 +02:00
}
void NotificationsOptionPage : : reset ( )
{
2017-09-27 00:21:53 +02:00
const auto & notifyOn = values ( ) . notifyOn ;
ui ( ) - > notifyOnDisconnectCheckBox - > setChecked ( notifyOn . disconnect ) ;
ui ( ) - > notifyOnErrorsCheckBox - > setChecked ( notifyOn . internalErrors ) ;
2019-07-12 20:24:19 +02:00
ui ( ) - > notifyOnLauncherErrorsCheckBox - > setChecked ( notifyOn . launcherErrors ) ;
2018-03-31 22:31:28 +02:00
ui ( ) - > notifyOnLocalSyncCompleteCheckBox - > setChecked ( notifyOn . localSyncComplete ) ;
ui ( ) - > notifyOnRemoteSyncCompleteCheckBox - > setChecked ( notifyOn . remoteSyncComplete ) ;
2017-09-27 00:21:53 +02:00
ui ( ) - > showSyncthingNotificationsCheckBox - > setChecked ( notifyOn . syncthingErrors ) ;
2018-05-01 22:27:03 +02:00
ui ( ) - > notifyOnNewDevConnectsCheckBox - > setChecked ( notifyOn . newDeviceConnects ) ;
ui ( ) - > notifyOnNewDirSharedCheckBox - > setChecked ( notifyOn . newDirectoryShared ) ;
2016-12-11 17:58:58 +01:00
# ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
2017-09-27 00:21:53 +02:00
( values ( ) . dbusNotifications ? ui ( ) - > dbusRadioButton : ui ( ) - > qtRadioButton ) - > setChecked ( true ) ;
2016-12-11 17:58:58 +01:00
# else
2017-09-27 00:21:53 +02:00
ui ( ) - > dbusRadioButton - > setEnabled ( false ) ;
ui ( ) - > qtRadioButton - > setChecked ( true ) ;
2016-12-11 17:58:58 +01:00
# endif
2017-09-27 00:21:53 +02:00
ui ( ) - > ignoreInavailabilityAfterStartSpinBox - > setValue ( static_cast < int > ( values ( ) . ignoreInavailabilityAfterStart ) ) ;
2016-08-25 00:45:32 +02:00
}
2016-08-29 20:51:30 +02:00
// AppearanceOptionPage
2017-09-18 20:29:36 +02:00
AppearanceOptionPage : : AppearanceOptionPage ( QWidget * parentWidget )
2017-05-01 03:34:43 +02:00
: AppearanceOptionPageBase ( parentWidget )
{
}
2016-08-29 20:51:30 +02:00
AppearanceOptionPage : : ~ AppearanceOptionPage ( )
2017-05-01 03:34:43 +02:00
{
}
2016-08-29 20:51:30 +02:00
bool AppearanceOptionPage : : apply ( )
{
2017-09-11 23:47:46 +02:00
auto & settings = values ( ) . appearance ;
2017-09-18 20:29:36 +02:00
settings . trayMenuSize . setWidth ( ui ( ) - > widthSpinBox - > value ( ) ) ;
settings . trayMenuSize . setHeight ( ui ( ) - > heightSpinBox - > value ( ) ) ;
settings . showTraffic = ui ( ) - > showTrafficCheckBox - > isChecked ( ) ;
int style ;
switch ( ui ( ) - > frameShapeComboBox - > currentIndex ( ) ) {
case 0 :
style = QFrame : : NoFrame ;
break ;
case 1 :
style = QFrame : : Box ;
break ;
case 2 :
style = QFrame : : Panel ;
break ;
default :
style = QFrame : : StyledPanel ;
2016-08-29 20:51:30 +02:00
}
2017-09-18 20:29:36 +02:00
switch ( ui ( ) - > frameShadowComboBox - > currentIndex ( ) ) {
case 0 :
style | = QFrame : : Plain ;
break ;
case 1 :
style | = QFrame : : Raised ;
break ;
default :
style | = QFrame : : Sunken ;
}
settings . frameStyle = style ;
settings . tabPosition = ui ( ) - > tabPosComboBox - > currentIndex ( ) ;
2017-09-11 23:47:46 +02:00
settings . brightTextColors = ui ( ) - > brightTextColorsCheckBox - > isChecked ( ) ;
2019-06-22 17:28:09 +02:00
settings . positioning . useCursorPosition = ui ( ) - > useCursorPosCheckBox - > isChecked ( ) ;
settings . positioning . assumedIconPosition = QPoint ( ui ( ) - > xPosSpinBox - > value ( ) , ui ( ) - > yPosSpinBox - > value ( ) ) ;
2016-08-29 20:51:30 +02:00
return true ;
}
void AppearanceOptionPage : : reset ( )
{
2017-09-11 23:47:46 +02:00
const auto & settings = values ( ) . appearance ;
2017-09-18 20:29:36 +02:00
ui ( ) - > widthSpinBox - > setValue ( settings . trayMenuSize . width ( ) ) ;
ui ( ) - > heightSpinBox - > setValue ( settings . trayMenuSize . height ( ) ) ;
ui ( ) - > showTrafficCheckBox - > setChecked ( settings . showTraffic ) ;
int index ;
switch ( settings . frameStyle & QFrame : : Shape_Mask ) {
case QFrame : : NoFrame :
index = 0 ;
break ;
case QFrame : : Box :
index = 1 ;
break ;
case QFrame : : Panel :
index = 2 ;
break ;
default :
index = 3 ;
}
ui ( ) - > frameShapeComboBox - > setCurrentIndex ( index ) ;
switch ( settings . frameStyle & QFrame : : Shadow_Mask ) {
case QFrame : : Plain :
index = 0 ;
break ;
case QFrame : : Raised :
index = 1 ;
break ;
default :
index = 2 ;
2016-08-29 20:51:30 +02:00
}
2017-09-18 20:29:36 +02:00
ui ( ) - > frameShadowComboBox - > setCurrentIndex ( index ) ;
ui ( ) - > tabPosComboBox - > setCurrentIndex ( settings . tabPosition ) ;
2019-06-22 17:28:09 +02:00
2017-09-11 23:47:46 +02:00
ui ( ) - > brightTextColorsCheckBox - > setChecked ( settings . brightTextColors ) ;
2019-06-22 17:28:09 +02:00
ui ( ) - > useCursorPosCheckBox - > setChecked ( settings . positioning . useCursorPosition ) ;
ui ( ) - > xPosSpinBox - > setValue ( settings . positioning . assumedIconPosition . x ( ) ) ;
ui ( ) - > yPosSpinBox - > setValue ( settings . positioning . assumedIconPosition . y ( ) ) ;
2016-08-29 20:51:30 +02:00
}
2019-05-19 17:56:11 +02:00
// IconsOptionPage
2019-07-31 20:16:43 +02:00
IconsOptionPage : : IconsOptionPage ( Context context , QWidget * parentWidget )
2019-05-19 17:56:11 +02:00
: IconsOptionPageBase ( parentWidget )
2019-07-31 20:16:43 +02:00
, m_context ( context )
2019-05-19 17:56:11 +02:00
{
}
IconsOptionPage : : ~ IconsOptionPage ( )
{
}
QWidget * IconsOptionPage : : setupWidget ( )
{
auto * const widget = IconsOptionPageBase : : setupWidget ( ) ;
2019-07-31 20:16:43 +02:00
// set context-specific elements
switch ( m_context ) {
case Context : : Combined :
ui ( ) - > contextLabel - > hide ( ) ;
ui ( ) - > contextCheckBox - > hide ( ) ;
break ;
case Context : : UI :
widget - > setWindowTitle ( QCoreApplication : : translate ( " QtGui::IconsOptionPageBase " , " UI icons " ) ) ;
ui ( ) - > contextLabel - > setText ( QCoreApplication : : translate ( " QtGui::IconsOptionPageBase " , " These icon colors are used within Syncthing Tray's UI. " ) ) ;
ui ( ) - > contextCheckBox - > hide ( ) ;
break ;
case Context : : System :
widget - > setWindowTitle ( QCoreApplication : : translate ( " QtGui::IconsOptionPageBase " , " System icons " ) ) ;
ui ( ) - > contextLabel - > setText ( QCoreApplication : : translate ( " QtGui::IconsOptionPageBase " , " These icon colors are used for the system tray icon and the notifications. " ) ) ;
ui ( ) - > contextCheckBox - > setText ( QCoreApplication : : translate ( " QtGui::IconsOptionPageBase " , " Use same colors as for UI icons " ) ) ;
break ;
}
2019-05-19 17:56:11 +02:00
// populate form for status icon colors
auto * const gridLayout = ui ( ) - > gridLayout ;
2019-05-21 17:56:08 +02:00
auto * const statusIconsGroupBox = ui ( ) - > statusIconsGroupBox ;
2019-05-19 17:56:11 +02:00
int index = 0 ;
for ( auto & colorMapping : m_settings . colorMapping ( ) ) {
// populate widgets array
auto & widgetsForColor = m_widgets [ index + + ] = {
{
2019-06-10 22:48:26 +02:00
new ColorButton ( statusIconsGroupBox ) ,
new ColorButton ( statusIconsGroupBox ) ,
new ColorButton ( statusIconsGroupBox ) ,
2019-05-19 17:56:11 +02:00
} ,
2019-05-21 17:56:08 +02:00
new QLabel ( statusIconsGroupBox ) ,
2019-05-19 17:56:11 +02:00
& colorMapping . setting ,
colorMapping . defaultEmblem ,
} ;
// add label for color name
2019-05-21 17:56:08 +02:00
gridLayout - > addWidget ( new QLabel ( colorMapping . colorName , statusIconsGroupBox ) , index , 0 , Qt : : AlignRight | Qt : : AlignVCenter ) ;
2019-05-19 17:56:11 +02:00
// setup preview
2019-05-21 17:56:08 +02:00
gridLayout - > addWidget ( widgetsForColor . previewLabel , index , 4 , Qt : : AlignCenter ) ;
2019-05-19 17:56:11 +02:00
const auto updatePreview = [ & widgetsForColor ] {
2019-05-21 17:56:08 +02:00
widgetsForColor . previewLabel - > setPixmap ( renderSvgImage ( makeSyncthingIcon (
StatusIconColorSet {
widgetsForColor . colorButtons [ 0 ] - > color ( ) ,
widgetsForColor . colorButtons [ 1 ] - > color ( ) ,
widgetsForColor . colorButtons [ 2 ] - > color ( ) ,
} ,
widgetsForColor . statusEmblem ) ,
QSize ( 32 , 32 ) ) ) ;
2019-05-19 17:56:11 +02:00
} ;
for ( const auto & colorButton : widgetsForColor . colorButtons ) {
2019-06-10 22:48:26 +02:00
QObject : : connect ( colorButton , & ColorButton : : colorChanged , updatePreview ) ;
2019-05-19 17:56:11 +02:00
}
// setup color buttons
2019-05-21 17:56:08 +02:00
widgetsForColor . colorButtons [ 0 ] - > setColor ( colorMapping . setting . backgroundStart ) ;
widgetsForColor . colorButtons [ 1 ] - > setColor ( colorMapping . setting . backgroundEnd ) ;
widgetsForColor . colorButtons [ 2 ] - > setColor ( colorMapping . setting . foreground ) ;
2019-05-19 17:56:11 +02:00
gridLayout - > addWidget ( widgetsForColor . colorButtons [ 0 ] , index , 1 ) ;
gridLayout - > addWidget ( widgetsForColor . colorButtons [ 1 ] , index , 2 ) ;
2019-05-21 17:56:08 +02:00
gridLayout - > addWidget ( widgetsForColor . colorButtons [ 2 ] , index , 3 ) ;
2019-05-19 17:56:11 +02:00
if ( index > = StatusIconSettings : : distinguishableColorCount ) {
break ;
}
}
// setup additional buttons
QObject : : connect ( ui ( ) - > restoreDefaultsPushButton , & QPushButton : : clicked , [ this ] {
m_settings = Data : : StatusIconSettings ( ) ;
update ( ) ;
} ) ;
QObject : : connect ( ui ( ) - > restorePreviousPushButton , & QPushButton : : clicked , [ this ] { reset ( ) ; } ) ;
return widget ;
}
bool IconsOptionPage : : apply ( )
{
for ( auto & widgetsForColor : m_widgets ) {
2019-05-21 17:56:08 +02:00
* widgetsForColor . setting = StatusIconColorSet {
widgetsForColor . colorButtons [ 0 ] - > color ( ) ,
widgetsForColor . colorButtons [ 1 ] - > color ( ) ,
widgetsForColor . colorButtons [ 2 ] - > color ( ) ,
} ;
2019-05-19 17:56:11 +02:00
}
2019-07-31 20:16:43 +02:00
auto & iconSettings = values ( ) . icons ;
switch ( m_context ) {
case Context : : Combined :
case Context : : UI :
iconSettings . status = m_settings ;
break ;
case Context : : System :
iconSettings . tray = m_settings ;
iconSettings . distinguishTrayIcons = ! ui ( ) - > contextCheckBox - > isChecked ( ) ;
break ;
}
2019-05-19 17:56:11 +02:00
return true ;
}
void IconsOptionPage : : update ( )
{
for ( auto & widgetsForColor : m_widgets ) {
2019-05-21 17:56:08 +02:00
widgetsForColor . colorButtons [ 0 ] - > setColor ( widgetsForColor . setting - > backgroundStart ) ;
widgetsForColor . colorButtons [ 1 ] - > setColor ( widgetsForColor . setting - > backgroundEnd ) ;
widgetsForColor . colorButtons [ 2 ] - > setColor ( widgetsForColor . setting - > foreground ) ;
2019-05-19 17:56:11 +02:00
}
}
void IconsOptionPage : : reset ( )
{
2019-07-31 20:16:43 +02:00
const auto & iconSettings = values ( ) . icons ;
switch ( m_context ) {
case Context : : Combined :
case Context : : UI :
m_settings = iconSettings . status ;
break ;
case Context : : System :
m_settings = iconSettings . tray ;
ui ( ) - > contextCheckBox - > setChecked ( ! iconSettings . distinguishTrayIcons ) ;
break ;
}
2019-05-19 17:56:11 +02:00
update ( ) ;
}
2016-09-03 19:39:43 +02:00
// AutostartOptionPage
2017-05-01 03:34:43 +02:00
AutostartOptionPage : : AutostartOptionPage ( QWidget * parentWidget )
: AutostartOptionPageBase ( parentWidget )
{
}
2016-08-25 00:45:32 +02:00
2016-08-30 20:01:07 +02:00
AutostartOptionPage : : ~ AutostartOptionPage ( )
2017-05-01 03:34:43 +02:00
{
}
2016-08-25 00:45:32 +02:00
2016-09-03 19:39:43 +02:00
QWidget * AutostartOptionPage : : setupWidget ( )
{
auto * widget = AutostartOptionPageBase : : setupWidget ( ) ;
2017-09-11 23:47:46 +02:00
2017-05-01 03:34:43 +02:00
ui ( ) - > infoIconLabel - > setPixmap (
QApplication : : style ( ) - > standardIcon ( QStyle : : SP_MessageBoxInformation , nullptr , ui ( ) - > infoIconLabel ) . pixmap ( ui ( ) - > infoIconLabel - > size ( ) ) ) ;
2017-01-14 02:25:20 +01:00
# if defined(PLATFORM_LINUX) && !defined(PLATFORM_ANDROID)
2017-05-01 03:34:43 +02:00
ui ( ) - > platformNoteLabel - > setText ( QCoreApplication : : translate ( " QtGui::AutostartOptionPage " ,
" This is achieved by adding a *.desktop file under <i>~/.config/autostart</i> so the setting only affects the current user. " ) ) ;
2016-09-03 19:39:43 +02:00
# elif defined(PLATFORM_WINDOWS)
2017-05-01 03:34:43 +02:00
ui ( ) - > platformNoteLabel - > setText ( QCoreApplication : : translate ( " QtGui::AutostartOptionPage " ,
" This is achieved by adding a registry key under <i>HKEY_CURRENT_USER \\ SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ Run</i> so the setting "
" only affects the current user. Note that the startup entry is invalidated when moving <i>syncthingtray.exe</i>. " ) ) ;
2019-07-20 06:10:32 +02:00
# elif defined(PLATFORM_MAC)
ui ( ) - > platformNoteLabel - > setText ( QCoreApplication : : translate ( " QtGui::AutostartOptionPage " ,
" This is achieved by adding a *.plist file under <i>~/Library/LaunchAgents</i> so the setting only affects the current user. " ) ) ;
2016-09-03 19:39:43 +02:00
# else
2017-05-01 03:34:43 +02:00
ui ( ) - > platformNoteLabel - > setText (
QCoreApplication : : translate ( " QtGui::AutostartOptionPage " , " This feature has not been implemented for your platform (yet). " ) ) ;
2016-09-03 19:39:43 +02:00
ui ( ) - > autostartCheckBox - > setEnabled ( false ) ;
# endif
return widget ;
}
/*!
* \ brief Returns whether the application is launched on startup .
* \ remarks
* - Only implemented under Linux / Windows . Always returns false on other platforms .
* - Does not check whether the startup entry is functional ( eg . the specified path is still valid ) .
*/
bool isAutostartEnabled ( )
{
# if defined(PLATFORM_LINUX) && !defined(Q_OS_ANDROID)
QFile desktopFile ( QStandardPaths : : locate ( QStandardPaths : : ConfigLocation , QStringLiteral ( " autostart/ " PROJECT_NAME " .desktop " ) ) ) ;
2019-07-20 06:10:32 +02:00
// check whether the file can be opened and whether it is enabled but prevent reading large files
2017-05-01 03:34:43 +02:00
if ( desktopFile . open ( QFile : : ReadOnly ) & & ( desktopFile . size ( ) > ( 5 * 1024 ) | | ! desktopFile . readAll ( ) . contains ( " Hidden=true " ) ) ) {
2016-09-03 19:39:43 +02:00
return true ;
}
return false ;
# elif defined(PLATFORM_WINDOWS)
QSettings settings ( QStringLiteral ( " HKEY_CURRENT_USER \\ SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ Run " ) , QSettings : : NativeFormat ) ;
return settings . contains ( QStringLiteral ( PROJECT_NAME ) ) ;
2019-07-20 06:10:32 +02:00
# elif defined(PLATFORM_MAC)
return QFileInfo ( QDir : : home ( ) , QStringLiteral ( " Library/LaunchAgents/ " PROJECT_NAME " .plist " ) ) . isReadable ( ) ;
2016-09-03 19:39:43 +02:00
# else
return false ;
# endif
}
2018-02-21 23:37:34 +01:00
# if (QT_VERSION < QT_VERSION_CHECK(5, 10, 0))
/*!
2019-07-20 17:12:55 +02:00
* \ brief Provides a fallback for qEnvironmentVariable ( ) when using old Qt versions .
2018-02-21 23:37:34 +01:00
*/
QString qEnvironmentVariable ( const char * varName , const QString & defaultValue )
{
const auto val ( qgetenv ( varName ) ) ;
return ! val . isEmpty ( ) ? QString : : fromLocal8Bit ( val ) : defaultValue ;
}
# endif
2016-09-03 19:39:43 +02:00
/*!
* \ brief Sets whether the application is launchedc on startup .
* \ remarks
* - Only implemented under Linux / Windows . Does nothing on other platforms .
* - If a startup entry already exists and \ a enabled is true , this function will ensure the path of the existing entry is valid .
* - If no startup entry could be detected via isAutostartEnabled ( ) and \ a enabled is false this function doesn ' t touch anything .
*/
bool setAutostartEnabled ( bool enabled )
{
2017-05-01 03:34:43 +02:00
if ( ! isAutostartEnabled ( ) & & ! enabled ) {
2016-09-03 19:39:43 +02:00
return true ;
}
2019-07-20 17:12:55 +02:00
2016-09-03 19:39:43 +02:00
# if defined(PLATFORM_LINUX) && !defined(Q_OS_ANDROID)
const QString configPath ( QStandardPaths : : writableLocation ( QStandardPaths : : ConfigLocation ) ) ;
2017-05-01 03:34:43 +02:00
if ( configPath . isEmpty ( ) ) {
2016-09-03 19:39:43 +02:00
return ! enabled ;
}
2017-05-01 03:34:43 +02:00
if ( enabled & & ! QDir ( ) . mkpath ( configPath + QStringLiteral ( " /autostart " ) ) ) {
2016-09-03 19:39:43 +02:00
return false ;
}
QFile desktopFile ( configPath + QStringLiteral ( " /autostart/ " PROJECT_NAME " .desktop " ) ) ;
2017-05-01 03:34:43 +02:00
if ( enabled ) {
2018-02-19 19:46:26 +01:00
if ( ! desktopFile . open ( QFile : : WriteOnly | QFile : : Truncate ) ) {
return false ;
2016-09-03 19:39:43 +02:00
}
2018-02-19 19:46:26 +01:00
desktopFile . write ( " [Desktop Entry] \n "
" Name= " APP_NAME " \n "
2018-02-22 03:24:32 +01:00
" Exec= \" " ) ;
2018-02-19 19:46:26 +01:00
desktopFile . write ( qEnvironmentVariable ( " APPIMAGE " , QCoreApplication : : applicationFilePath ( ) ) . toUtf8 ( ) . data ( ) ) ;
2018-02-22 03:24:32 +01:00
desktopFile . write ( " \" \n Comment= " APP_DESCRIPTION " \n "
2018-02-19 19:46:26 +01:00
" Icon= " PROJECT_NAME " \n "
" Type=Application \n "
" Terminal=false \n "
" X-GNOME-Autostart-Delay=0 \n "
" X-GNOME-Autostart-enabled=true " ) ;
return desktopFile . error ( ) = = QFile : : NoError & & desktopFile . flush ( ) ;
2016-09-03 19:39:43 +02:00
} else {
return ! desktopFile . exists ( ) | | desktopFile . remove ( ) ;
}
# elif defined(PLATFORM_WINDOWS)
QSettings settings ( QStringLiteral ( " HKEY_CURRENT_USER \\ SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ Run " ) , QSettings : : NativeFormat ) ;
2017-05-01 03:34:43 +02:00
if ( enabled ) {
2016-09-03 20:14:52 +02:00
settings . setValue ( QStringLiteral ( PROJECT_NAME ) , QCoreApplication : : applicationFilePath ( ) . replace ( QChar ( ' / ' ) , QChar ( ' \\ ' ) ) ) ;
2016-09-03 19:39:43 +02:00
} else {
settings . remove ( QStringLiteral ( PROJECT_NAME ) ) ;
}
settings . sync ( ) ;
return true ;
2019-07-20 17:12:55 +02:00
2019-07-20 06:10:32 +02:00
# elif defined(PLATFORM_MAC)
2019-07-20 17:12:55 +02:00
const QString libraryPath ( QDir : : home ( ) . filePath ( QStringLiteral ( " Library " ) ) ) ;
2019-07-20 06:10:32 +02:00
if ( enabled & & ! QDir ( ) . mkpath ( libraryPath + QStringLiteral ( " /LaunchAgents " ) ) ) {
return false ;
}
QFile launchdPlistFile ( libraryPath + QStringLiteral ( " /LaunchAgents/ " PROJECT_NAME " .plist " ) ) ;
if ( enabled ) {
if ( ! launchdPlistFile . open ( QFile : : WriteOnly | QFile : : Truncate ) ) {
return false ;
}
launchdPlistFile . write ( " <?xml version= \" 1.0 \" encoding= \" UTF-8 \" ?> \n "
" <!DOCTYPE plist PUBLIC \" -//Apple//DTD PLIST 1.0//EN \" \" http://www.apple.com/DTDs/PropertyList-1.0.dtd \" > \n "
" <plist version= \" 1.0 \" > \n "
" <dict> \n "
" <key>Label</key> \n "
" <string> " PROJECT_NAME " </string> \n "
" <key>ProgramArguments</key> \n "
" <array> \n "
" <string> " ) ;
launchdPlistFile . write ( QCoreApplication : : applicationFilePath ( ) . toUtf8 ( ) . data ( ) ) ;
launchdPlistFile . write ( " </string> \n "
" </array> \n "
" <key>KeepAlive</key> \n "
" <true/> \n "
" </dict> \n "
" </plist> \n " ) ;
return launchdPlistFile . error ( ) = = QFile : : NoError & & launchdPlistFile . flush ( ) ;
} else {
return ! launchdPlistFile . exists ( ) | | launchdPlistFile . remove ( ) ;
}
2016-09-03 19:39:43 +02:00
# endif
}
2016-08-30 20:01:07 +02:00
bool AutostartOptionPage : : apply ( )
2016-08-25 00:45:32 +02:00
{
2017-09-27 00:21:53 +02:00
if ( ! setAutostartEnabled ( ui ( ) - > autostartCheckBox - > isChecked ( ) ) ) {
errors ( ) < < QCoreApplication : : translate ( " QtGui::AutostartOptionPage " , " unable to modify startup entry " ) ;
return false ;
2016-08-25 00:45:32 +02:00
}
2017-09-27 00:21:53 +02:00
return true ;
2016-08-25 00:45:32 +02:00
}
2016-08-30 20:01:07 +02:00
void AutostartOptionPage : : reset ( )
2016-08-25 00:45:32 +02:00
{
2017-05-01 03:34:43 +02:00
if ( hasBeenShown ( ) ) {
2016-09-03 19:39:43 +02:00
ui ( ) - > autostartCheckBox - > setChecked ( isAutostartEnabled ( ) ) ;
}
}
// LauncherOptionPage
2017-05-01 03:34:43 +02:00
LauncherOptionPage : : LauncherOptionPage ( QWidget * parentWidget )
2019-07-07 13:52:07 +02:00
: QObject ( parentWidget )
, LauncherOptionPageBase ( parentWidget )
2018-04-11 23:15:15 +02:00
, m_process ( nullptr )
, m_launcher ( SyncthingLauncher : : mainInstance ( ) )
2017-05-01 03:34:43 +02:00
, m_kill ( false )
{
}
LauncherOptionPage : : LauncherOptionPage ( const QString & tool , QWidget * parentWidget )
2019-07-07 13:52:07 +02:00
: QObject ( parentWidget )
, LauncherOptionPageBase ( parentWidget )
2018-04-11 23:15:15 +02:00
, m_process ( & Launcher : : toolProcess ( tool ) )
, m_launcher ( nullptr )
2019-07-07 12:59:47 +02:00
, m_restoreArgsButton ( nullptr )
2017-05-01 03:34:43 +02:00
, m_kill ( false )
, m_tool ( tool )
{
}
2017-03-17 00:38:42 +01:00
2016-09-03 19:39:43 +02:00
LauncherOptionPage : : ~ LauncherOptionPage ( )
{
}
QWidget * LauncherOptionPage : : setupWidget ( )
{
2018-02-19 19:46:26 +01:00
auto * const widget = LauncherOptionPageBase : : setupWidget ( ) ;
2019-07-07 12:59:47 +02:00
2017-03-17 00:38:42 +01:00
// adjust labels to use name of additional tool instead of "Syncthing"
2019-07-12 20:26:56 +02:00
const auto isSyncthing = m_tool . isEmpty ( ) ;
if ( ! isSyncthing ) {
2019-07-07 14:36:35 +02:00
widget - > setWindowTitle ( tr ( " %1-launcher " ) . arg ( m_tool ) ) ;
ui ( ) - > enabledCheckBox - > setText ( tr ( " Launch %1 when starting the tray icon " ) . arg ( m_tool ) ) ;
ui ( ) - > syncthingPathLabel - > setText ( tr ( " %1 executable " ) . arg ( m_tool ) ) ;
ui ( ) - > logLabel - > setText ( tr ( " %1 log (interleaved stdout/stderr) " ) . arg ( m_tool ) ) ;
2019-07-07 12:59:47 +02:00
2019-07-12 20:26:56 +02:00
// hide "consider for reconnect" and "show start/stop button on tray" checkboxes for tools
ui ( ) - > considerForReconnectCheckBox - > setVisible ( false ) ;
ui ( ) - > showButtonCheckBox - > setVisible ( false ) ;
}
2019-07-07 12:59:47 +02:00
2019-07-12 20:26:56 +02:00
// add "restore to defaults" action for Syncthing arguments
if ( isSyncthing ) {
2019-07-07 12:59:47 +02:00
m_restoreArgsButton = new IconButton ( ui ( ) - > argumentsLineEdit ) ;
m_restoreArgsButton - > setPixmap (
QIcon : : fromTheme ( QStringLiteral ( " edit-undo " ) , QIcon ( QStringLiteral ( " :/icons/hicolor/scalable/actions/edit-paste.svg " ) ) ) . pixmap ( 16 ) ) ;
2019-07-07 14:36:35 +02:00
m_restoreArgsButton - > setToolTip ( tr ( " Restore default " ) ) ;
2019-07-07 14:32:40 +02:00
connect ( m_restoreArgsButton , & IconButton : : clicked , this , & LauncherOptionPage : : restoreDefaultArguments ) ;
2019-07-07 12:59:47 +02:00
ui ( ) - > argumentsLineEdit - > insertCustomButton ( 0 , m_restoreArgsButton ) ;
2019-07-17 17:53:36 +02:00
ui ( ) - > configDirPathSelection - > provideCustomFileMode ( QFileDialog : : Directory ) ;
2019-07-07 12:59:47 +02:00
}
2017-03-17 00:38:42 +01:00
// setup other widgets
2016-09-03 19:39:43 +02:00
ui ( ) - > syncthingPathSelection - > provideCustomFileMode ( QFileDialog : : ExistingFile ) ;
ui ( ) - > logTextEdit - > setFont ( QFontDatabase : : systemFont ( QFontDatabase : : FixedFont ) ) ;
2019-07-17 17:53:36 +02:00
const auto running = isRunning ( ) ;
2016-09-03 19:39:43 +02:00
ui ( ) - > launchNowPushButton - > setHidden ( running ) ;
ui ( ) - > stopPushButton - > setHidden ( ! running ) ;
2019-07-17 17:53:36 +02:00
ui ( ) - > useBuiltInVersionCheckBox - > setVisible ( isSyncthing & & SyncthingLauncher : : isLibSyncthingAvailable ( ) ) ;
2019-07-28 22:01:30 +02:00
if ( isSyncthing ) {
ui ( ) - > useBuiltInVersionCheckBox - > setToolTip ( SyncthingLauncher : : libSyncthingVersionInfo ( ) ) ;
}
2019-07-07 12:59:47 +02:00
2017-03-17 00:38:42 +01:00
// connect signals & slots
2018-04-11 23:15:15 +02:00
if ( m_process ) {
2019-07-07 14:32:40 +02:00
connect ( m_process , & SyncthingProcess : : readyRead , this , & LauncherOptionPage : : handleSyncthingReadyRead , Qt : : QueuedConnection ) ;
connect ( m_process , static_cast < void ( SyncthingProcess : : * ) ( int exitCode , QProcess : : ExitStatus exitStatus ) > ( & SyncthingProcess : : finished ) , this ,
2019-07-07 13:52:07 +02:00
& LauncherOptionPage : : handleSyncthingExited , Qt : : QueuedConnection ) ;
2019-07-07 14:32:40 +02:00
connect ( m_process , & SyncthingProcess : : errorOccurred , this , & LauncherOptionPage : : handleSyncthingError , Qt : : QueuedConnection ) ;
2018-04-11 23:15:15 +02:00
} else if ( m_launcher ) {
2019-07-12 20:26:56 +02:00
connect ( m_launcher , & SyncthingLauncher : : runningChanged , this , & LauncherOptionPage : : handleSyncthingLaunched ) ;
2019-07-07 14:32:40 +02:00
connect ( m_launcher , & SyncthingLauncher : : outputAvailable , this , & LauncherOptionPage : : handleSyncthingOutputAvailable , Qt : : QueuedConnection ) ;
connect ( m_launcher , & SyncthingLauncher : : exited , this , & LauncherOptionPage : : handleSyncthingExited , Qt : : QueuedConnection ) ;
connect ( m_launcher , & SyncthingLauncher : : errorOccurred , this , & LauncherOptionPage : : handleSyncthingError , Qt : : QueuedConnection ) ;
2019-08-02 17:03:39 +02:00
m_launcher - > setEmittingOutput ( true ) ;
2019-07-07 14:32:40 +02:00
}
connect ( ui ( ) - > launchNowPushButton , & QPushButton : : clicked , this , & LauncherOptionPage : : launch ) ;
connect ( ui ( ) - > stopPushButton , & QPushButton : : clicked , this , & LauncherOptionPage : : stop ) ;
2019-07-07 12:59:47 +02:00
2016-09-03 19:39:43 +02:00
return widget ;
}
bool LauncherOptionPage : : apply ( )
{
2017-09-27 00:21:53 +02:00
auto & settings = values ( ) . launcher ;
if ( m_tool . isEmpty ( ) ) {
2019-07-12 20:26:56 +02:00
settings . autostartEnabled = ui ( ) - > enabledCheckBox - > isChecked ( ) ;
2018-04-18 23:27:45 +02:00
settings . useLibSyncthing = ui ( ) - > useBuiltInVersionCheckBox - > isChecked ( ) ;
2019-07-17 17:53:36 +02:00
settings . libSyncthing . configDir = ui ( ) - > configDirPathSelection - > lineEdit ( ) - > text ( ) ;
2017-09-27 00:21:53 +02:00
settings . syncthingPath = ui ( ) - > syncthingPathSelection - > lineEdit ( ) - > text ( ) ;
settings . syncthingArgs = ui ( ) - > argumentsLineEdit - > text ( ) ;
2018-04-03 00:11:55 +02:00
settings . considerForReconnect = ui ( ) - > considerForReconnectCheckBox - > isChecked ( ) ;
2019-07-12 20:26:56 +02:00
settings . showButton = ui ( ) - > showButtonCheckBox - > isChecked ( ) ;
2017-09-27 00:21:53 +02:00
} else {
ToolParameter & params = settings . tools [ m_tool ] ;
params . autostart = ui ( ) - > enabledCheckBox - > isChecked ( ) ;
params . path = ui ( ) - > syncthingPathSelection - > lineEdit ( ) - > text ( ) ;
params . args = ui ( ) - > argumentsLineEdit - > text ( ) ;
2016-09-03 19:39:43 +02:00
}
return true ;
}
void LauncherOptionPage : : reset ( )
{
2017-09-27 00:21:53 +02:00
const auto & settings = values ( ) . launcher ;
if ( m_tool . isEmpty ( ) ) {
2019-07-12 20:26:56 +02:00
ui ( ) - > enabledCheckBox - > setChecked ( settings . autostartEnabled ) ;
2018-04-18 23:27:45 +02:00
ui ( ) - > useBuiltInVersionCheckBox - > setChecked ( settings . useLibSyncthing ) ;
ui ( ) - > useBuiltInVersionCheckBox - > setVisible ( settings . useLibSyncthing | | SyncthingLauncher : : isLibSyncthingAvailable ( ) ) ;
2019-07-17 17:53:36 +02:00
ui ( ) - > configDirPathSelection - > lineEdit ( ) - > setText ( settings . libSyncthing . configDir ) ;
2017-09-27 00:21:53 +02:00
ui ( ) - > syncthingPathSelection - > lineEdit ( ) - > setText ( settings . syncthingPath ) ;
ui ( ) - > argumentsLineEdit - > setText ( settings . syncthingArgs ) ;
2018-04-03 00:11:55 +02:00
ui ( ) - > considerForReconnectCheckBox - > setChecked ( settings . considerForReconnect ) ;
2019-07-12 20:26:56 +02:00
ui ( ) - > showButtonCheckBox - > setChecked ( settings . showButton ) ;
2017-09-27 00:21:53 +02:00
} else {
const ToolParameter params = settings . tools . value ( m_tool ) ;
2018-04-18 23:27:45 +02:00
ui ( ) - > useBuiltInVersionCheckBox - > setChecked ( false ) ;
ui ( ) - > useBuiltInVersionCheckBox - > setVisible ( false ) ;
2017-09-27 00:21:53 +02:00
ui ( ) - > enabledCheckBox - > setChecked ( params . autostart ) ;
ui ( ) - > syncthingPathSelection - > lineEdit ( ) - > setText ( params . path ) ;
ui ( ) - > argumentsLineEdit - > setText ( params . args ) ;
2016-09-03 19:39:43 +02:00
}
}
2019-07-12 20:26:56 +02:00
void LauncherOptionPage : : handleSyncthingLaunched ( bool running )
{
if ( ! running ) {
return ; // Syncthing being stopped is handled elsewhere
}
ui ( ) - > launchNowPushButton - > hide ( ) ;
ui ( ) - > stopPushButton - > show ( ) ;
ui ( ) - > stopPushButton - > setText ( tr ( " Stop launched instance " ) ) ;
m_kill = false ;
}
2016-09-03 19:39:43 +02:00
void LauncherOptionPage : : handleSyncthingReadyRead ( )
2018-04-11 23:15:15 +02:00
{
handleSyncthingOutputAvailable ( m_process - > readAll ( ) ) ;
}
void LauncherOptionPage : : handleSyncthingOutputAvailable ( const QByteArray & output )
2016-09-03 19:39:43 +02:00
{
2017-09-27 00:21:53 +02:00
if ( ! hasBeenShown ( ) ) {
return ;
}
2018-04-11 23:15:15 +02:00
QTextCursor cursor ( ui ( ) - > logTextEdit - > textCursor ( ) ) ;
2017-09-27 00:21:53 +02:00
cursor . movePosition ( QTextCursor : : End ) ;
2018-04-18 23:27:45 +02:00
cursor . insertText ( QString : : fromUtf8 ( output ) ) ;
2017-09-27 00:21:53 +02:00
if ( ui ( ) - > ensureCursorVisibleCheckBox - > isChecked ( ) ) {
2019-07-07 14:31:09 +02:00
ui ( ) - > logTextEdit - > moveCursor ( QTextCursor : : End ) ;
2017-09-27 00:21:53 +02:00
ui ( ) - > logTextEdit - > ensureCursorVisible ( ) ;
2016-09-03 19:39:43 +02:00
}
}
void LauncherOptionPage : : handleSyncthingExited ( int exitCode , QProcess : : ExitStatus exitStatus )
{
2017-09-27 00:21:53 +02:00
if ( ! hasBeenShown ( ) ) {
return ;
2016-09-03 19:39:43 +02:00
}
2019-07-07 14:31:09 +02:00
2019-07-07 13:52:37 +02:00
QTextCursor cursor ( ui ( ) - > logTextEdit - > textCursor ( ) ) ;
2017-09-27 00:21:53 +02:00
cursor . movePosition ( QTextCursor : : End ) ;
2019-07-07 14:31:09 +02:00
cursor . insertBlock ( ) ;
2017-09-27 00:21:53 +02:00
switch ( exitStatus ) {
case QProcess : : NormalExit :
2019-07-07 14:36:35 +02:00
cursor . insertText ( tr ( " %1 exited with exit code %2 " ) . arg ( m_tool . isEmpty ( ) ? QStringLiteral ( " Syncthing " ) : m_tool , QString : : number ( exitCode ) ) ) ;
2017-09-27 00:21:53 +02:00
break ;
case QProcess : : CrashExit :
2019-07-07 14:36:35 +02:00
cursor . insertText ( tr ( " %1 crashed with exit code %2 " ) . arg ( m_tool . isEmpty ( ) ? QStringLiteral ( " Syncthing " ) : m_tool , QString : : number ( exitCode ) ) ) ;
2017-09-27 00:21:53 +02:00
break ;
}
2019-07-07 14:31:09 +02:00
cursor . insertBlock ( ) ;
if ( ui ( ) - > ensureCursorVisibleCheckBox - > isChecked ( ) ) {
ui ( ) - > logTextEdit - > moveCursor ( QTextCursor : : End ) ;
ui ( ) - > logTextEdit - > ensureCursorVisible ( ) ;
}
2017-09-27 00:21:53 +02:00
ui ( ) - > stopPushButton - > hide ( ) ;
ui ( ) - > launchNowPushButton - > show ( ) ;
2016-09-03 19:39:43 +02:00
}
2019-07-07 14:31:09 +02:00
void LauncherOptionPage : : handleSyncthingError ( QProcess : : ProcessError error )
{
if ( ! hasBeenShown ( ) ) {
return ;
}
QTextCursor cursor ( ui ( ) - > logTextEdit - > textCursor ( ) ) ;
cursor . movePosition ( QTextCursor : : End ) ;
cursor . insertBlock ( ) ;
QString errorString ;
switch ( error ) {
case QProcess : : FailedToStart :
2019-07-07 14:36:35 +02:00
errorString = tr ( " failed to start (e.g. executable does not exist or not permission error) " ) ;
2019-07-07 14:31:09 +02:00
break ;
case QProcess : : Crashed :
2019-07-07 14:36:35 +02:00
errorString = tr ( " process crashed " ) ;
2019-07-07 14:31:09 +02:00
break ;
case QProcess : : Timedout :
2019-07-07 14:36:35 +02:00
errorString = tr ( " timeout error " ) ;
2019-07-07 14:31:09 +02:00
break ;
case QProcess : : ReadError :
2019-07-07 14:36:35 +02:00
errorString = tr ( " read error " ) ;
2019-07-07 14:31:09 +02:00
break ;
case QProcess : : WriteError :
2019-07-07 14:36:35 +02:00
errorString = tr ( " write error " ) ;
2019-07-07 14:31:09 +02:00
break ;
default :
2019-07-07 14:36:35 +02:00
errorString = tr ( " unknown process error " ) ;
2019-07-07 14:31:09 +02:00
}
2019-07-07 14:36:35 +02:00
cursor . insertText ( tr ( " An error occurred when running %1: %2 " ) . arg ( m_tool . isEmpty ( ) ? QStringLiteral ( " Syncthing " ) : m_tool , errorString ) ) ;
2019-07-07 14:31:09 +02:00
cursor . insertBlock ( ) ;
if ( ( m_launcher & & ! m_launcher - > isRunning ( ) ) | | ( m_process & & ! m_process - > isRunning ( ) ) ) {
ui ( ) - > stopPushButton - > hide ( ) ;
ui ( ) - > launchNowPushButton - > show ( ) ;
}
}
2018-04-11 23:15:15 +02:00
bool LauncherOptionPage : : isRunning ( ) const
{
return ( m_process & & m_process - > isRunning ( ) ) | | ( m_launcher & & m_launcher - > isRunning ( ) ) ;
}
2016-09-03 19:39:43 +02:00
void LauncherOptionPage : : launch ( )
{
2017-09-27 00:21:53 +02:00
if ( ! hasBeenShown ( ) ) {
return ;
}
apply ( ) ;
2018-04-11 23:15:15 +02:00
if ( isRunning ( ) ) {
2018-02-19 19:46:26 +01:00
return ;
}
2018-04-18 23:27:45 +02:00
const auto launcherSettings ( values ( ) . launcher ) ;
2018-02-19 19:46:26 +01:00
if ( m_tool . isEmpty ( ) ) {
2019-07-17 17:53:36 +02:00
m_launcher - > launch ( launcherSettings ) ;
2018-02-19 19:46:26 +01:00
} else {
2018-04-18 23:27:45 +02:00
const auto toolParams ( launcherSettings . tools . value ( m_tool ) ) ;
m_process - > startSyncthing ( toolParams . path , SyncthingProcess : : splitArguments ( toolParams . args ) ) ;
2019-07-12 20:26:56 +02:00
handleSyncthingLaunched ( true ) ;
2016-09-03 19:39:43 +02:00
}
}
void LauncherOptionPage : : stop ( )
{
2018-04-11 23:15:15 +02:00
if ( ! hasBeenShown ( ) ) {
2017-09-27 00:21:53 +02:00
return ;
}
if ( m_kill ) {
2018-04-11 23:15:15 +02:00
if ( m_process ) {
m_process - > killSyncthing ( ) ;
}
if ( m_launcher ) {
m_launcher - > kill ( ) ;
}
2017-09-27 00:21:53 +02:00
} else {
2019-07-07 14:36:35 +02:00
ui ( ) - > stopPushButton - > setText ( tr ( " Kill launched instance " ) ) ;
2017-09-27 00:21:53 +02:00
m_kill = true ;
2018-04-11 23:15:15 +02:00
if ( m_process ) {
m_process - > stopSyncthing ( ) ;
}
if ( m_launcher ) {
m_launcher - > terminate ( ) ;
}
2016-08-25 00:45:32 +02:00
}
}
2019-07-07 12:59:47 +02:00
void LauncherOptionPage : : restoreDefaultArguments ( )
{
static const : : Settings : : Launcher defaults ;
ui ( ) - > argumentsLineEdit - > setText ( defaults . syncthingArgs ) ;
}
2016-12-18 16:50:35 +01:00
// SystemdOptionPage
# ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
2017-05-01 03:34:43 +02:00
SystemdOptionPage : : SystemdOptionPage ( QWidget * parentWidget )
: SystemdOptionPageBase ( parentWidget )
2018-04-11 23:15:15 +02:00
, m_service ( SyncthingService : : mainInstance ( ) )
2017-05-01 03:34:43 +02:00
{
}
2016-12-18 16:50:35 +01:00
SystemdOptionPage : : ~ SystemdOptionPage ( )
2017-05-01 03:34:43 +02:00
{
}
2016-12-18 16:50:35 +01:00
QWidget * SystemdOptionPage : : setupWidget ( )
{
2018-02-19 19:46:26 +01:00
auto * const widget = SystemdOptionPageBase : : setupWidget ( ) ;
2018-04-11 23:15:15 +02:00
if ( ! m_service ) {
return widget ;
}
QObject : : connect ( ui ( ) - > syncthingUnitLineEdit , & QLineEdit : : textChanged , m_service , & SyncthingService : : setUnitName ) ;
QObject : : connect ( ui ( ) - > startPushButton , & QPushButton : : clicked , m_service , & SyncthingService : : start ) ;
QObject : : connect ( ui ( ) - > stopPushButton , & QPushButton : : clicked , m_service , & SyncthingService : : stop ) ;
QObject : : connect ( ui ( ) - > enablePushButton , & QPushButton : : clicked , m_service , & SyncthingService : : enable ) ;
QObject : : connect ( ui ( ) - > disablePushButton , & QPushButton : : clicked , m_service , & SyncthingService : : disable ) ;
QObject : : connect ( m_service , & SyncthingService : : descriptionChanged , bind ( & SystemdOptionPage : : handleDescriptionChanged , this , _1 ) ) ;
QObject : : connect ( m_service , & SyncthingService : : stateChanged , bind ( & SystemdOptionPage : : handleStatusChanged , this , _1 , _2 , _3 ) ) ;
QObject : : connect ( m_service , & SyncthingService : : unitFileStateChanged , bind ( & SystemdOptionPage : : handleEnabledChanged , this , _1 ) ) ;
2016-12-18 16:50:35 +01:00
return widget ;
}
bool SystemdOptionPage : : apply ( )
{
2019-07-12 20:26:56 +02:00
auto & settings = values ( ) ;
auto & systemdSettings = settings . systemd ;
auto & launcherSettings = settings . launcher ;
systemdSettings . syncthingUnit = ui ( ) - > syncthingUnitLineEdit - > text ( ) ;
systemdSettings . showButton = ui ( ) - > showButtonCheckBox - > isChecked ( ) ;
systemdSettings . considerForReconnect = ui ( ) - > considerForReconnectCheckBox - > isChecked ( ) ;
auto result = true ;
if ( systemdSettings . showButton & & launcherSettings . showButton ) {
2019-07-13 13:21:25 +02:00
errors ( ) . append ( QCoreApplication : : translate ( " QtGui::SystemdOptionPage " ,
" It is not possible to show the start/stop button for the systemd service and the internal launcher at the same time. The systemd "
" service precedes. " ) ) ;
2019-07-12 20:26:56 +02:00
result = false ;
}
if ( systemdSettings . considerForReconnect & & launcherSettings . considerForReconnect ) {
2019-07-13 13:21:25 +02:00
errors ( ) . append ( QCoreApplication : : translate ( " QtGui::SystemdOptionPage " ,
" It is not possible to consider the systemd service and the internal launcher for reconnects at the same time. The systemd service "
" precedes. " ) ) ;
2019-07-12 20:26:56 +02:00
result = false ;
}
return result ;
2016-12-18 16:50:35 +01:00
}
void SystemdOptionPage : : reset ( )
{
2017-09-27 00:21:53 +02:00
const auto & settings = values ( ) . systemd ;
ui ( ) - > syncthingUnitLineEdit - > setText ( settings . syncthingUnit ) ;
ui ( ) - > showButtonCheckBox - > setChecked ( settings . showButton ) ;
ui ( ) - > considerForReconnectCheckBox - > setChecked ( settings . considerForReconnect ) ;
2018-04-11 23:15:15 +02:00
if ( ! m_service ) {
return ;
}
handleDescriptionChanged ( m_service - > description ( ) ) ;
handleStatusChanged ( m_service - > activeState ( ) , m_service - > subState ( ) , m_service - > activeSince ( ) ) ;
handleEnabledChanged ( m_service - > unitFileState ( ) ) ;
2016-12-18 16:50:35 +01:00
}
void SystemdOptionPage : : handleDescriptionChanged ( const QString & description )
{
2017-05-01 03:34:43 +02:00
ui ( ) - > descriptionValueLabel - > setText ( description . isEmpty ( )
? QCoreApplication : : translate ( " QtGui::SystemdOptionPage " , " specified unit is either inactive or doesn't exist " )
: description ) ;
2016-12-18 16:50:35 +01:00
}
void setIndicatorColor ( QWidget * indicator , const QColor & color )
{
indicator - > setStyleSheet ( QStringLiteral ( " border-radius:8px;background-color: " ) + color . name ( ) ) ;
}
2019-06-10 22:48:26 +02:00
void SystemdOptionPage : : handleStatusChanged ( const QString & activeState , const QString & subState , DateTime activeSince )
2016-12-18 16:50:35 +01:00
{
QStringList status ;
2017-05-01 03:34:43 +02:00
if ( ! activeState . isEmpty ( ) ) {
2016-12-18 16:50:35 +01:00
status < < activeState ;
}
2017-05-01 03:34:43 +02:00
if ( ! subState . isEmpty ( ) ) {
2016-12-18 16:50:35 +01:00
status < < subState ;
}
2017-01-13 10:25:50 +01:00
2018-04-11 23:15:15 +02:00
const bool isRunning = m_service & & m_service - > isRunning ( ) ;
2017-01-13 10:25:50 +01:00
QString timeStamp ;
2017-05-01 03:34:43 +02:00
if ( isRunning & & ! activeSince . isNull ( ) ) {
timeStamp = QLatin1Char ( ' \n ' ) % QCoreApplication : : translate ( " QtGui::SystemdOptionPage " , " since " )
2019-06-10 22:48:26 +02:00
% QString : : fromUtf8 ( activeSince . toString ( DateTimeOutputFormat : : DateAndTime ) . data ( ) ) ;
2017-05-01 03:34:43 +02:00
}
ui ( ) - > statusValueLabel - > setText (
status . isEmpty ( ) ? QCoreApplication : : translate ( " QtGui::SystemdOptionPage " , " unknown " ) : status . join ( QStringLiteral ( " - " ) ) + timeStamp ) ;
setIndicatorColor ( ui ( ) - > statusIndicator ,
status . isEmpty ( ) ? Colors : : gray ( values ( ) . appearance . brightTextColors )
: ( isRunning ? Colors : : green ( values ( ) . appearance . brightTextColors ) : Colors : : red ( values ( ) . appearance . brightTextColors ) ) ) ;
2016-12-27 16:16:12 +01:00
ui ( ) - > startPushButton - > setVisible ( ! isRunning ) ;
2016-12-18 16:50:35 +01:00
ui ( ) - > stopPushButton - > setVisible ( ! status . isEmpty ( ) & & isRunning ) ;
}
void SystemdOptionPage : : handleEnabledChanged ( const QString & unitFileState )
{
2018-04-11 23:15:15 +02:00
const bool isEnabled = m_service & & m_service - > isEnabled ( ) ;
2017-05-01 03:34:43 +02:00
ui ( ) - > unitFileStateValueLabel - > setText (
unitFileState . isEmpty ( ) ? QCoreApplication : : translate ( " QtGui::SystemdOptionPage " , " unknown " ) : unitFileState ) ;
setIndicatorColor (
ui ( ) - > enabledIndicator , isEnabled ? Colors : : green ( values ( ) . appearance . brightTextColors ) : Colors : : gray ( values ( ) . appearance . brightTextColors ) ) ;
2016-12-27 16:16:12 +01:00
ui ( ) - > enablePushButton - > setVisible ( ! isEnabled ) ;
2016-12-18 16:50:35 +01:00
ui ( ) - > disablePushButton - > setVisible ( ! unitFileState . isEmpty ( ) & & isEnabled ) ;
}
# endif
2016-08-25 00:45:32 +02:00
// WebViewOptionPage
2017-05-01 03:34:43 +02:00
WebViewOptionPage : : WebViewOptionPage ( QWidget * parentWidget )
: WebViewOptionPageBase ( parentWidget )
{
}
2016-08-25 00:45:32 +02:00
WebViewOptionPage : : ~ WebViewOptionPage ( )
2017-05-01 03:34:43 +02:00
{
}
2016-08-25 00:45:32 +02:00
2017-04-23 18:27:31 +02:00
# ifdef SYNCTHINGWIDGETS_NO_WEBVIEW
2016-08-25 00:45:32 +02:00
QWidget * WebViewOptionPage : : setupWidget ( )
{
auto * label = new QLabel ;
label - > setWindowTitle ( QCoreApplication : : translate ( " QtGui::WebViewOptionPage " , " General " ) ) ;
label - > setAlignment ( Qt : : AlignCenter ) ;
2017-09-17 21:48:15 +02:00
label - > setText ( QCoreApplication : : translate ( " QtGui::WebViewOptionPage " ,
" Syncthing Tray has not been built with vieb view support utilizing either Qt WebKit "
" or Qt WebEngine. \n The Web UI will be opened in the default web browser instead. " ) ) ;
2016-08-25 00:45:32 +02:00
return label ;
}
# endif
bool WebViewOptionPage : : apply ( )
{
2017-04-23 18:27:31 +02:00
# ifndef SYNCTHINGWIDGETS_NO_WEBVIEW
2017-09-27 00:21:53 +02:00
auto & webView = values ( ) . webView ;
webView . disabled = ui ( ) - > disableCheckBox - > isChecked ( ) ;
webView . zoomFactor = ui ( ) - > zoomDoubleSpinBox - > value ( ) ;
webView . keepRunning = ui ( ) - > keepRunningCheckBox - > isChecked ( ) ;
2016-08-25 00:45:32 +02:00
# endif
return true ;
}
void WebViewOptionPage : : reset ( )
{
2017-04-23 18:27:31 +02:00
# ifndef SYNCTHINGWIDGETS_NO_WEBVIEW
2017-09-27 00:21:53 +02:00
const auto & webView = values ( ) . webView ;
ui ( ) - > disableCheckBox - > setChecked ( webView . disabled ) ;
ui ( ) - > zoomDoubleSpinBox - > setValue ( webView . zoomFactor ) ;
ui ( ) - > keepRunningCheckBox - > setChecked ( webView . keepRunning ) ;
2016-08-25 00:45:32 +02:00
# endif
}
2017-09-09 21:38:43 +02:00
SettingsDialog : : SettingsDialog ( const QList < OptionCategory * > & categories , QWidget * parent )
2019-06-10 22:48:26 +02:00
: QtUtilities : : SettingsDialog ( parent )
2017-09-09 21:38:43 +02:00
{
categoryModel ( ) - > setCategories ( categories ) ;
init ( ) ;
}
2018-10-10 17:48:48 +02:00
SettingsDialog : : SettingsDialog ( QWidget * parent )
2019-06-10 22:48:26 +02:00
: QtUtilities : : SettingsDialog ( parent )
2018-10-10 17:48:48 +02:00
{
init ( ) ;
}
2017-05-01 03:34:43 +02:00
SettingsDialog : : SettingsDialog ( Data : : SyncthingConnection * connection , QWidget * parent )
2019-06-10 22:48:26 +02:00
: QtUtilities : : SettingsDialog ( parent )
2016-08-25 00:45:32 +02:00
{
// setup categories
2019-06-10 22:48:26 +02:00
QList < OptionCategory * > categories ;
OptionCategory * category ;
2016-08-25 00:45:32 +02:00
category = new OptionCategory ( this ) ;
category - > setDisplayName ( tr ( " Tray " ) ) ;
2019-06-10 22:48:26 +02:00
category - > assignPages ( QList < OptionPage * > ( ) < < new ConnectionOptionPage ( connection ) < < new NotificationsOptionPage < < new AppearanceOptionPage
2019-07-31 20:16:43 +02:00
< < new IconsOptionPage ( IconsOptionPage : : Context : : UI ) < < new IconsOptionPage ( IconsOptionPage : : Context : : System ) ) ;
2016-08-25 00:45:32 +02:00
category - > setIcon ( QIcon ( QStringLiteral ( " :/icons/hicolor/scalable/app/syncthingtray.svg " ) ) ) ;
categories < < category ;
category = new OptionCategory ( this ) ;
category - > setDisplayName ( tr ( " Web view " ) ) ;
2019-06-10 22:48:26 +02:00
category - > assignPages ( QList < OptionPage * > ( ) < < new WebViewOptionPage ) ;
2017-05-01 03:34:43 +02:00
category - > setIcon (
QIcon : : fromTheme ( QStringLiteral ( " internet-web-browser " ) , QIcon ( QStringLiteral ( " :/icons/hicolor/scalable/apps/internet-web-browser.svg " ) ) ) ) ;
2016-08-25 00:45:32 +02:00
categories < < category ;
2016-09-03 19:39:43 +02:00
category = new OptionCategory ( this ) ;
category - > setDisplayName ( tr ( " Startup " ) ) ;
2017-05-01 03:34:43 +02:00
category - > assignPages (
2019-06-10 22:48:26 +02:00
QList < OptionPage * > ( ) < < new AutostartOptionPage < < new LauncherOptionPage < < new LauncherOptionPage ( QStringLiteral ( " Inotify " ) )
2016-12-18 16:50:35 +01:00
# ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
2019-06-10 22:48:26 +02:00
< < new SystemdOptionPage
2016-12-18 16:50:35 +01:00
# endif
2017-09-17 21:48:15 +02:00
) ;
2016-09-03 19:39:43 +02:00
category - > setIcon ( QIcon : : fromTheme ( QStringLiteral ( " system-run " ) , QIcon ( QStringLiteral ( " :/icons/hicolor/scalable/apps/system-run.svg " ) ) ) ) ;
categories < < category ;
2016-11-02 20:03:38 +01:00
categories < < values ( ) . qt . category ( ) ;
2016-08-25 00:45:32 +02:00
categoryModel ( ) - > setCategories ( categories ) ;
2017-09-09 21:38:43 +02:00
init ( ) ;
}
SettingsDialog : : ~ SettingsDialog ( )
{
}
2016-08-25 00:45:32 +02:00
2017-09-09 21:38:43 +02:00
void SettingsDialog : : init ( )
{
2017-01-12 22:38:36 +01:00
resize ( 860 , 620 ) ;
2016-09-03 20:14:52 +02:00
setWindowTitle ( tr ( " Settings " ) + QStringLiteral ( " - " APP_NAME ) ) ;
2017-05-01 03:34:43 +02:00
setWindowIcon (
QIcon : : fromTheme ( QStringLiteral ( " preferences-other " ) , QIcon ( QStringLiteral ( " :/icons/hicolor/scalable/apps/preferences-other.svg " ) ) ) ) ;
2016-08-25 00:45:32 +02:00
// some settings could be applied without restarting the application, good idea?
//connect(this, &Dialogs::SettingsDialog::applied, bind(&Dialogs::QtSettings::apply, &Settings::qtSettings()));
}
2017-09-17 21:48:15 +02:00
} // namespace QtGui
2016-09-12 21:52:04 +02:00
INSTANTIATE_UI_FILE_BASED_OPTION_PAGE_NS ( QtGui , ConnectionOptionPage )
INSTANTIATE_UI_FILE_BASED_OPTION_PAGE_NS ( QtGui , NotificationsOptionPage )
INSTANTIATE_UI_FILE_BASED_OPTION_PAGE_NS ( QtGui , AppearanceOptionPage )
2019-05-19 17:56:11 +02:00
INSTANTIATE_UI_FILE_BASED_OPTION_PAGE_NS ( QtGui , IconsOptionPage )
2016-09-12 21:52:04 +02:00
INSTANTIATE_UI_FILE_BASED_OPTION_PAGE_NS ( QtGui , AutostartOptionPage )
INSTANTIATE_UI_FILE_BASED_OPTION_PAGE_NS ( QtGui , LauncherOptionPage )
2016-12-18 16:50:35 +01:00
# ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
INSTANTIATE_UI_FILE_BASED_OPTION_PAGE_NS ( QtGui , SystemdOptionPage )
# endif
2017-04-23 18:27:31 +02:00
# ifndef SYNCTHINGWIDGETS_NO_WEBVIEW
2016-09-12 21:52:04 +02:00
INSTANTIATE_UI_FILE_BASED_OPTION_PAGE_NS ( QtGui , WebViewOptionPage )
# endif