dcc: Add settings page for DCC configuration dcc
authorManuel Nickschas <sputnick@quassel-irc.org>
Sat, 8 Oct 2016 15:06:13 +0000 (17:06 +0200)
committerManuel Nickschas <sputnick@quassel-irc.org>
Sat, 8 Oct 2016 15:06:13 +0000 (17:06 +0200)
src/qtui/mainwin.cpp
src/qtui/settingspages/dccsettingspage.cpp [new file with mode: 0644]
src/qtui/settingspages/dccsettingspage.h [new file with mode: 0644]
src/qtui/settingspages/dccsettingspage.ui [new file with mode: 0644]
src/qtui/settingspages/settingspages.cmake

index 3fc4cb9..cdaf51d 100644 (file)
 #include "settingspages/connectionsettingspage.h"
 #include "settingspages/coreaccountsettingspage.h"
 #include "settingspages/coreconnectionsettingspage.h"
+#include "settingspages/dccsettingspage.h"
 #include "settingspages/highlightsettingspage.h"
 #include "settingspages/identitiessettingspage.h"
 #include "settingspages/ignorelistsettingspage.h"
@@ -1450,6 +1451,7 @@ void MainWin::showSettingsDlg()
     dlg->registerSettingsPage(new NetworksSettingsPage(dlg));
     dlg->registerSettingsPage(new AliasesSettingsPage(dlg));
     dlg->registerSettingsPage(new IgnoreListSettingsPage(dlg));
+    dlg->registerSettingsPage(new DccSettingsPage(dlg));
 
     // Category: Remote Cores
     if (Quassel::runMode() != Quassel::Monolithic) {
diff --git a/src/qtui/settingspages/dccsettingspage.cpp b/src/qtui/settingspages/dccsettingspage.cpp
new file mode 100644 (file)
index 0000000..62fce35
--- /dev/null
@@ -0,0 +1,192 @@
+/***************************************************************************
+ *   Copyright (C) 2005-2016 by the Quassel Project                        *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) version 3.                                           *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
+ ***************************************************************************/
+
+#include "dccsettingspage.h"
+
+#include "client.h"
+#include "clienttransfermanager.h"
+
+DccSettingsPage::DccSettingsPage(QWidget *parent)
+    : SettingsPage(tr("IRC"), tr("DCC"), parent)
+{
+    ui.setupUi(this);
+    initAutoWidgets();
+    connect(ui.ipDetectionMode, SIGNAL(currentIndexChanged(int)), SLOT(updateWidgetStates()));
+    connect(ui.portSelectionMode, SIGNAL(currentIndexChanged(int)), SLOT(updateWidgetStates()));
+    updateWidgetStates();
+
+    connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), SLOT(onClientConfigChanged()));
+    setClientConfig(Client::dccConfig());
+}
+
+
+bool DccSettingsPage::isClientConfigValid() const
+{
+    return _clientConfig != nullptr;
+}
+
+
+void DccSettingsPage::setClientConfig(DccConfig *config)
+{
+    if (_clientConfig) {
+        disconnect(_clientConfig, 0, this, 0);
+    }
+    if (config && !isClientConfigValid()) {
+        qWarning() << "Client DCC config is not valid/synchronized!";
+        _clientConfig = nullptr;
+        ui.dccEnabled->setEnabled(false);
+        return;
+    }
+    _clientConfig = config;
+    if (_clientConfig) {
+        connect(_clientConfig, SIGNAL(updated()), SLOT(load()));
+        load();
+        ui.dccEnabled->setEnabled(true);
+    }
+    else {
+        ui.dccEnabled->setEnabled(false);
+    }
+}
+
+
+void DccSettingsPage::onClientConfigChanged()
+{
+    if (Client::isConnected() && Client::dccConfig() && !Client::dccConfig()->isInitialized()) {
+        connect(Client::dccConfig(), SIGNAL(initDone()), SLOT(onClientConfigChanged()));
+    }
+    else {
+        setClientConfig(Client::isConnected() ? Client::dccConfig() : nullptr);
+    }
+}
+
+
+bool DccSettingsPage::hasDefaults() const
+{
+    return true;
+}
+
+
+void DccSettingsPage::defaults()
+{
+    _localConfig = DccConfig();
+    SettingsPage::load();
+    widgetHasChanged();
+}
+
+
+void DccSettingsPage::load()
+{
+    _localConfig = isClientConfigValid() ? *_clientConfig : DccConfig{};
+    SettingsPage::load();
+    widgetHasChanged();
+}
+
+
+void DccSettingsPage::save()
+{
+    SettingsPage::save();
+    if (isClientConfigValid()) {
+        Client::dccConfig()->requestUpdate(_localConfig.toVariantMap());
+    }
+    setChangedState(false);
+}
+
+
+QVariant DccSettingsPage::loadAutoWidgetValue(const QString& widgetName)
+{
+    if (widgetName == "dccEnabled")
+        return _localConfig.isDccEnabled();
+    if (widgetName == "ipDetectionMode")
+        // NOTE: Use mapping if item order differs from enum order
+        return static_cast<int>(_localConfig.ipDetectionMode());
+    if (widgetName == "portSelectionMode")
+        // NOTE: Use mapping if item order differs from enum order
+        return static_cast<int>(_localConfig.portSelectionMode());
+    if (widgetName == "minPort")
+        return _localConfig.minPort();
+    if (widgetName == "maxPort")
+        return _localConfig.maxPort();
+    if (widgetName == "chunkSize")
+        return _localConfig.chunkSize();
+    if (widgetName == "sendTimeout")
+        return _localConfig.sendTimeout();
+    if (widgetName == "usePassiveDcc")
+        return _localConfig.usePassiveDcc();
+    if (widgetName == "useFastSend")
+        return _localConfig.useFastSend();
+    if (widgetName == "outgoingIp")
+        return _localConfig.outgoingIp().toString();
+
+    qWarning() << "Unknown auto widget" << widgetName;
+    return {};
+}
+
+
+void DccSettingsPage::saveAutoWidgetValue(const QString& widgetName, const QVariant& value)
+{
+    if (widgetName == "dccEnabled")
+        _localConfig.setDccEnabled(value.toBool());
+    else if (widgetName == "ipDetectionMode")
+        // NOTE: Use mapping if item order differs from enum order
+        _localConfig.setIpDetectionMode(static_cast<DccConfig::IpDetectionMode>(value.toInt()));
+    else if (widgetName == "portSelectionMode")
+        // NOTE: Use mapping if item order differs from enum order
+        _localConfig.setPortSelectionMode(static_cast<DccConfig::PortSelectionMode>(value.toInt()));
+    else if (widgetName == "minPort")
+        _localConfig.setMinPort(value.toInt());
+    else if (widgetName == "maxPort")
+        _localConfig.setMaxPort(value.toInt());
+    else if (widgetName == "chunkSize")
+        _localConfig.setChunkSize(value.toInt());
+    else if (widgetName == "sendTimeout")
+        _localConfig.setSendTimeout(value.toInt());
+    else if (widgetName == "usePassiveDcc")
+        _localConfig.setUsePassiveDcc(value.toBool());
+    else if (widgetName == "useFastSend")
+        _localConfig.setUseFastSend(value.toBool());
+    else if (widgetName == "outgoingIp") {
+        QHostAddress address {QHostAddress::LocalHost};
+        if (!address.setAddress(value.toString())) {
+            qWarning() << "Invalid IP address!";
+            address = QHostAddress{QHostAddress::LocalHost};
+        }
+        _localConfig.setOutgoingIp(std::move(address));
+    }
+    else {
+        qWarning() << "Unknown auto widget" << widgetName;
+    }
+}
+
+
+void DccSettingsPage::widgetHasChanged()
+{
+    bool same = isClientConfigValid() && (_localConfig == *_clientConfig);
+    setChangedState(!same);
+}
+
+
+void DccSettingsPage::updateWidgetStates()
+{
+    ui.outgoingIp->setEnabled(ui.ipDetectionMode->currentIndex() != 0);
+    bool enablePorts = ui.portSelectionMode->currentIndex() != 0;
+    ui.minPort->setEnabled(enablePorts);
+    ui.maxPort->setEnabled(enablePorts);
+    ui.portsToLabel->setEnabled(enablePorts);
+}
diff --git a/src/qtui/settingspages/dccsettingspage.h b/src/qtui/settingspages/dccsettingspage.h
new file mode 100644 (file)
index 0000000..b5fabbc
--- /dev/null
@@ -0,0 +1,90 @@
+/***************************************************************************
+ *   Copyright (C) 2005-2016 by the Quassel Project                        *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) version 3.                                           *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
+ ***************************************************************************/
+
+#pragma once
+
+#include "dccconfig.h"
+#include "settingspage.h"
+#include "ui_dccsettingspage.h"
+
+/**
+ * A settingspage for configuring DCC.
+ */
+class DccSettingsPage : public SettingsPage
+{
+    Q_OBJECT
+
+public:
+    /**
+     * Constructor.
+     *
+     * @param[in] parent QObject parent
+     */
+    DccSettingsPage(QWidget *parent = nullptr);
+
+    /// See base class docs
+    bool hasDefaults() const override;
+
+public slots:
+    // See base class docs
+    void save() override;
+    void load() override;
+    void defaults() override;
+
+private:
+    /**
+     * Whether the client's DccConfig is valid
+     *
+     * @returns true if the client is connected and its DccConfig instance synchronized
+     */
+    bool isClientConfigValid() const;
+
+    /**
+     * Set the client config
+     *
+     * @param[in] config The client's config. Must be be valid or a nullptr.
+     */
+    void setClientConfig(DccConfig *config);
+
+    // See base class docs
+    QVariant loadAutoWidgetValue(const QString &widgetName) override;
+    void saveAutoWidgetValue(const QString &widgetName, const QVariant &value) override;
+
+private slots:
+    /**
+     * Updates the enabled state according to the current config.
+     */
+    void updateWidgetStates();
+
+    /**
+     * Checks if the current unsaved config differs from the client's and sets state accordingly.
+     */
+    void widgetHasChanged();
+
+    /**
+     * Called if the client's config was changed (e.g. if the connection state changed).
+     */
+    void onClientConfigChanged();
+
+private:
+    Ui::DccSettingsPage ui;              ///< The UI object
+    DccConfig *_clientConfig {nullptr};  ///< Pointer to the client's config (nullptr if not synchronized/available)
+    DccConfig _localConfig;              ///< Local config reflecting the widget states
+};
diff --git a/src/qtui/settingspages/dccsettingspage.ui b/src/qtui/settingspages/dccsettingspage.ui
new file mode 100644 (file)
index 0000000..acd5a9d
--- /dev/null
@@ -0,0 +1,369 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DccSettingsPage</class>
+ <widget class="QWidget" name="DccSettingsPage">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>736</width>
+    <height>559</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_3">
+   <item>
+    <widget class="QGroupBox" name="dccEnabled">
+     <property name="title">
+      <string>Enable DCC</string>
+     </property>
+     <property name="checkable">
+      <bool>true</bool>
+     </property>
+     <property name="settingsKey" stdset="0">
+      <string notr="true"/>
+     </property>
+     <property name="defaultValue" stdset="0">
+      <bool>false</bool>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <layout class="QGridLayout" name="gridLayout">
+        <item row="1" column="0">
+         <widget class="QLabel" name="label_2">
+          <property name="text">
+           <string>Ports:</string>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="1">
+         <widget class="QComboBox" name="portSelectionMode">
+          <property name="settingsKey" stdset="0">
+           <string notr="true"/>
+          </property>
+          <property name="defaultValue" stdset="0">
+           <number>0</number>
+          </property>
+          <item>
+           <property name="text">
+            <string>Automatic</string>
+           </property>
+          </item>
+          <item>
+           <property name="text">
+            <string>Manual</string>
+           </property>
+          </item>
+         </widget>
+        </item>
+        <item row="1" column="2">
+         <layout class="QHBoxLayout" name="horizontalLayout">
+          <item>
+           <widget class="QSpinBox" name="minPort">
+            <property name="minimum">
+             <number>1024</number>
+            </property>
+            <property name="maximum">
+             <number>65535</number>
+            </property>
+            <property name="settingsKey" stdset="0">
+             <string notr="true"/>
+            </property>
+            <property name="defaultValue" stdset="0">
+             <number>1024</number>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="portsToLabel">
+            <property name="text">
+             <string>to</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QSpinBox" name="maxPort">
+            <property name="minimum">
+             <number>1024</number>
+            </property>
+            <property name="maximum">
+             <number>65535</number>
+            </property>
+            <property name="value">
+             <number>65535</number>
+            </property>
+            <property name="settingsKey" stdset="0">
+             <string notr="true"/>
+            </property>
+            <property name="defaultValue" stdset="0">
+             <number>32767</number>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="0" column="0">
+         <widget class="QLabel" name="label">
+          <property name="text">
+           <string>Outgoing IP:</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="2">
+         <widget class="QLineEdit" name="outgoingIp">
+          <property name="settingsKey" stdset="0">
+           <string notr="true"/>
+          </property>
+          <property name="defaultValue" stdset="0">
+           <string notr="true">localhost</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="1">
+         <widget class="QComboBox" name="ipDetectionMode">
+          <property name="settingsKey" stdset="0">
+           <string notr="true"/>
+          </property>
+          <property name="defaultValue" stdset="0">
+           <number>0</number>
+          </property>
+          <item>
+           <property name="text">
+            <string>Automatic</string>
+           </property>
+          </item>
+          <item>
+           <property name="text">
+            <string>Manual</string>
+           </property>
+          </item>
+         </widget>
+        </item>
+        <item row="0" column="3">
+         <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>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_2">
+        <item>
+         <widget class="QLabel" name="label_4">
+          <property name="text">
+           <string>DCC send timeout:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSpinBox" name="sendTimeout">
+          <property name="suffix">
+           <string> seconds</string>
+          </property>
+          <property name="minimum">
+           <number>10</number>
+          </property>
+          <property name="maximum">
+           <number>3600</number>
+          </property>
+          <property name="singleStep">
+           <number>10</number>
+          </property>
+          <property name="value">
+           <number>180</number>
+          </property>
+          <property name="settingsKey" stdset="0">
+           <string/>
+          </property>
+          <property name="defaultValue" stdset="0">
+           <number>180</number>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_4">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_3">
+        <item>
+         <widget class="QLabel" name="label_5">
+          <property name="text">
+           <string>Chunk size:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSpinBox" name="chunkSize">
+          <property name="suffix">
+           <string> KiB</string>
+          </property>
+          <property name="prefix">
+           <string/>
+          </property>
+          <property name="minimum">
+           <number>1</number>
+          </property>
+          <property name="maximum">
+           <number>1024</number>
+          </property>
+          <property name="singleStep">
+           <number>16</number>
+          </property>
+          <property name="value">
+           <number>16</number>
+          </property>
+          <property name="settingsKey" stdset="0">
+           <string notr="true"/>
+          </property>
+          <property name="defaultValue" stdset="0">
+           <number>16</number>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_3">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="usePassiveDcc">
+        <property name="text">
+         <string>Use passive/reverse DCC</string>
+        </property>
+        <property name="settingsKey" stdset="0">
+         <string notr="true"/>
+        </property>
+        <property name="defaultValue" stdset="0">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="useFastSend">
+        <property name="text">
+         <string>Use fast sending (might not work with all peers)</string>
+        </property>
+        <property name="settingsKey" stdset="0">
+         <string notr="true"/>
+        </property>
+        <property name="defaultValue" stdset="0">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="enableFileTransfers">
+     <property name="enabled">
+      <bool>false</bool>
+     </property>
+     <property name="title">
+      <string>File transfers</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_4">
+        <item>
+         <widget class="QLabel" name="label_6">
+          <property name="text">
+           <string>Default download folder:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="downloadPath"/>
+        </item>
+        <item>
+         <widget class="QToolButton" name="browseButton">
+          <property name="text">
+           <string>...</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="createSenderDirectory">
+        <property name="text">
+         <string>Create folder per sender</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="prefixFilenames">
+        <property name="text">
+         <string>Prefix filenames with sender</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>ipDetectionMode</tabstop>
+  <tabstop>outgoingIp</tabstop>
+  <tabstop>portSelectionMode</tabstop>
+  <tabstop>minPort</tabstop>
+  <tabstop>maxPort</tabstop>
+  <tabstop>sendTimeout</tabstop>
+  <tabstop>chunkSize</tabstop>
+  <tabstop>usePassiveDcc</tabstop>
+  <tabstop>useFastSend</tabstop>
+  <tabstop>downloadPath</tabstop>
+  <tabstop>browseButton</tabstop>
+  <tabstop>createSenderDirectory</tabstop>
+  <tabstop>prefixFilenames</tabstop>
+  <tabstop>dccEnabled</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
index c2705cb..e061241 100644 (file)
@@ -12,6 +12,7 @@ set(SETTINGSPAGES
     connection
     coreconnection
     coreaccount
+    dcc
     highlight
     identities
     ignorelist