--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CapsEditDlg</class>
+ <widget class="QDialog" name="CapsEditDlg">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>475</width>
+ <height>154</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Edit Network Features</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string><p>Enter a space-separated list of IRCv3 capabilities to ignore:</p></string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="skipCapsEdit"/>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string><p>A list of capabilities may be found at <a href="https://ircv3.net/irc/">https://ircv3.net/irc/</a>.</p></string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>270</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>CapsEditDlg</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>CapsEditDlg</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>
disconnectedIcon = icon::get("network-disconnect");
// Status icons
+ infoIcon = icon::get({"emblem-information", "dialog-information"});
successIcon = icon::get({"emblem-success", "dialog-information"});
unavailableIcon = icon::get({"emblem-unavailable", "dialog-warning"});
questionIcon = icon::get({"emblem-question", "dialog-question", "dialog-information"});
"modify message rate limits.")));
}
+ if (!Client::isConnected() || Client::isCoreFeatureEnabled(Quassel::Feature::SkipIrcCaps)) {
+ // Either disconnected or IRCv3 capability skippping supported, enable configuration and
+ // hide warning. Don't show the warning needlessly when disconnected.
+ ui.enableCapsConfigWidget->setEnabled(true);
+ ui.enableCapsStatusLabel->setText(tr("These features require support from the network"));
+ ui.enableCapsStatusIcon->setPixmap(infoIcon.pixmap(16));
+ }
+ else {
+ // Core does not IRCv3 capability skipping, show warning and disable configuration
+ ui.enableCapsConfigWidget->setEnabled(false);
+ ui.enableCapsStatusLabel->setText(tr("Your Quassel core is too old to configure IRCv3 features"));
+ ui.enableCapsStatusIcon->setPixmap(unavailableIcon.pixmap(16));
+ }
+
// Hide the SASL EXTERNAL notice until a network's shown. Stops it from showing while loading
// backlog from the core.
sslUpdated();
}
}
+void NetworksSettingsPage::on_enableCapsStatusDetails_clicked()
+{
+ if (!Client::isConnected() || Client::isCoreFeatureEnabled(Quassel::Feature::SkipIrcCaps)) {
+ // Either disconnected or IRCv3 capability skippping supported
+
+ // Try to get a list of currently enabled features
+ QStringList sortedCapsEnabled;
+ // Check if a network is selected
+ if (ui.networkList->selectedItems().count()) {
+ // Get the underlying Network from the selected network
+ NetworkId netid = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value<NetworkId>();
+ const Network* net = Client::network(netid);
+ if (net && Client::isCoreFeatureEnabled(Quassel::Feature::CapNegotiation)) {
+ // Capability negotiation is supported, network exists.
+ // If the network is disconnected, the list of enabled capabilities will be empty,
+ // no need to check for that specifically.
+ // Sorting isn't required, but it looks nicer.
+ sortedCapsEnabled = net->capsEnabled();
+ sortedCapsEnabled.sort();
+ }
+ }
+
+ // Try to explain IRCv3 network features in a friendly way, including showing the currently
+ // enabled features if available
+ auto messageText = QString("<p>%1</p></br><p>%2</p>")
+ .arg(tr("Quassel makes use of newer IRC features when supported by the IRC network."
+ " If desired, you can disable unwanted or problematic features here."),
+ tr("The <a href=\"https://ircv3.net/irc/\">IRCv3 website</a> provides more "
+ "technical details on the IRCv3 capabilities powering these features."));
+
+ if (!sortedCapsEnabled.isEmpty()) {
+ // Format the capabilities within <code></code> blocks
+ auto formattedCaps = QString("<code>%1</code>")
+ .arg(sortedCapsEnabled.join("</code>, <code>"));
+
+ // Add the currently enabled capabilities to the list
+ // This creates a new QString, but this code is not performance-critical.
+ messageText = messageText.append(QString("<p><i>%1</i></p>").arg(
+ tr("Currently enabled IRCv3 capabilities for this "
+ "network: %1").arg(formattedCaps)));
+ }
+
+ QMessageBox::information(this, tr("Configuring network features"), messageText);
+ }
+ else {
+ // Core does not IRCv3 capability skipping, show warning
+ QMessageBox::warning(this, tr("Configuring network features unsupported"),
+ QString("<p><b>%1</b></p></br><p>%2</p>")
+ .arg(tr("Your Quassel core is too old to configure IRCv3 network features"),
+ tr("You need a Quassel core v0.14.0 or newer to control what network "
+ "features Quassel will use.")));
+ }
+}
+
+void NetworksSettingsPage::on_enableCapsAdvanced_clicked()
+{
+ if (currentId == 0)
+ return;
+
+ CapsEditDlg dlg(networkInfos[currentId].skipCapsToString(), this);
+ if (dlg.exec() == QDialog::Accepted) {
+ networkInfos[currentId].skipCapsFromString(dlg.skipCapsString());
+ displayNetwork(currentId);
+ widgetHasChanged();
+ }
+}
+
IdentityId NetworksSettingsPage::defaultIdentity() const
{
IdentityId defaultId = 0;
}
}
+/**************************************************************************
+ * CapsEditDlg
+ *************************************************************************/
+
+CapsEditDlg::CapsEditDlg(const QString& oldSkipCapsString, QWidget* parent)
+ : QDialog(parent)
+ , oldSkipCapsString(oldSkipCapsString)
+{
+ ui.setupUi(this);
+
+ // Connect to the reset button to reset the text
+ // This provides an explicit way to "get back to defaults" in case someone changes settings to
+ // experiment
+ QPushButton* defaultsButton = ui.buttonBox->button(QDialogButtonBox::RestoreDefaults);
+ connect(defaultsButton, &QPushButton::clicked, this, &CapsEditDlg::defaultSkipCaps);
+
+ if (oldSkipCapsString.isEmpty()) {
+ // Disable Reset button
+ on_skipCapsEdit_textChanged("");
+ }
+ else {
+ ui.skipCapsEdit->setText(oldSkipCapsString);
+ }
+}
+
+
+QString CapsEditDlg::skipCapsString() const
+{
+ return ui.skipCapsEdit->text();
+}
+
+void CapsEditDlg::defaultSkipCaps()
+{
+ ui.skipCapsEdit->setText("");
+}
+
+void CapsEditDlg::on_skipCapsEdit_textChanged(const QString& text)
+{
+ ui.buttonBox->button(QDialogButtonBox::RestoreDefaults)->setDisabled(text.isEmpty());
+}
+
/**************************************************************************
* SaveNetworksDlg
*************************************************************************/
#include "network.h"
#include "settingspage.h"
+#include "ui_capseditdlg.h"
#include "ui_networkadddlg.h"
#include "ui_networkeditdlg.h"
#include "ui_networkssettingspage.h"
*/
void on_saslStatusDetails_clicked();
+ /**
+ * Event handler for Features status Details button
+ */
+ void on_enableCapsStatusDetails_clicked();
+
+ /**
+ * Event handler for Features Advanced edit button
+ */
+ void on_enableCapsAdvanced_clicked();
+
private:
/**
* Status of capability support
QIcon connectedIcon, connectingIcon, disconnectedIcon;
// Status icons
- QIcon successIcon, unavailableIcon, questionIcon;
+ QIcon infoIcon, successIcon, unavailableIcon, questionIcon;
CapSupportStatus _saslStatusSelected; /// Status of SASL support for currently-selected network
Ui::ServerEditDlg ui;
};
+class CapsEditDlg : public QDialog
+{
+ Q_OBJECT
+
+public:
+ CapsEditDlg(const QString& oldSkipCapsString, QWidget* parent = nullptr);
+
+ QString skipCapsString() const;
+
+private slots:
+ void defaultSkipCaps();
+ void on_skipCapsEdit_textChanged(const QString&);
+
+private:
+ Ui::CapsEditDlg ui;
+
+ QString oldSkipCapsString;
+};
+
class SaveNetworksDlg : public QDialog
{
Q_OBJECT
<bool>true</bool>
</property>
<property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</item>
</layout>
</widget>
- <widget class="QWidget" name="tab">
+ <widget class="QWidget" name="connectionTab">
<attribute name="title">
<string>Connection</string>
</attribute>
</item>
</layout>
</widget>
- <widget class="QWidget" name="tab_2">
+ <widget class="QWidget" name="autoIdentifyTab">
<attribute name="title">
<string>Auto Identify</string>
</attribute>
</item>
</layout>
</widget>
- <widget class="QWidget" name="advancedTab">
+ <widget class="QWidget" name="featuresTab">
+ <attribute name="title">
+ <string>Features</string>
+ </attribute>
+ <attribute name="toolTip">
+ <string>Configure the modern IRC messaging features Quassel supports</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_14">
+ <item>
+ <widget class="QWidget" name="enableCapsStatusWidget" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout_8">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="enableCapsStatusIcon">
+ <property name="text">
+ <string notr="true">[icon]</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="enableCapsStatusLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>These features require support from the network</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="enableCapsStatusDetails">
+ <property name="text">
+ <string>Details...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QWidget" name="enableCapsConfigWidget" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_9">
+ <item>
+ <widget class="QPushButton" name="enableCapsAdvanced">
+ <property name="toolTip">
+ <string>Configure which IRC capabilities Quassel will ignore during negotiation</string>
+ </property>
+ <property name="text">
+ <string>Advanced...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>13</width>
+ <height>35</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QLabel" name="enableCapsReconnectNotice">
+ <property name="text">
+ <string><i>Changes apply after reconnecting to the network</i></string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>178</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="encodingsTab">
<attribute name="title">
<string>Encodings</string>
</attribute>
<attribute name="toolTip">
- <string>Configure advanced settings such as message encodings and automatic reconnect</string>
+ <string>Configure advanced settings such as message encodings</string>
</attribute>
- <layout class="QVBoxLayout" name="verticalLayout_6">
+ <layout class="QVBoxLayout" name="verticalLayout_13">
<item>
<widget class="QGroupBox" name="useCustomEncodings">
<property name="enabled">
<tabstop>autoIdentify</tabstop>
<tabstop>autoIdentifyService</tabstop>
<tabstop>autoIdentifyPassword</tabstop>
+ <tabstop>enableCapsStatusDetails</tabstop>
+ <tabstop>enableCapsAdvanced</tabstop>
<tabstop>useCustomEncodings</tabstop>
<tabstop>sendEncoding</tabstop>
<tabstop>recvEncoding</tabstop>
set(SP_FORMS
buffervieweditdlg.ui
+ capseditdlg.ui
coreaccounteditdlg.ui
createidentitydlg.ui
identityeditwidget.ui