From 84b764f48c2bdfb2cd9c3efea689eaf8a9dfca31 Mon Sep 17 00:00:00 2001 From: Shane Synan Date: Mon, 20 Jul 2020 01:33:35 -0400 Subject: [PATCH] settings: Add Features tab to Network for skipCaps Add new "Features" tab to the Network settings page, allowing configuring which IRCv3 capabilities to skip during negotiation. This initial list is empty; individual IRCv3 capabilities will be added in future commits. When the core doesn't support skipping capabilities, show an upgrade warning banner at the top. When skipping capabilities is supported, show an info banner noting that the network must support these features. The details button tries to explain IRCv3 capabilities and shows the currently enabled features. Add an "Advanced..." button which directly configures the "skipCaps" list as a space-separated list of IRCv3 capabilities. This provides an escape hatch in case misbehaving servers are found or if Quassel's implementation of an IRCv3 feature is faulty. It also allows older clients (with this change) to clear the capability skip list set by newer clients. A "Defaults" button makes it clear how to restore the list to Quassel's normal behavior. Clean up the settings page UI, including fixing the Commands tab "perform" list of commands to fill the available space. --- src/qtui/settingspages/capseditdlg.ui | 112 ++++++++++++++ .../settingspages/networkssettingspage.cpp | 123 ++++++++++++++++ src/qtui/settingspages/networkssettingspage.h | 32 +++- .../settingspages/networkssettingspage.ui | 137 +++++++++++++++++- src/qtui/settingspages/settingspages.cmake | 1 + 5 files changed, 398 insertions(+), 7 deletions(-) create mode 100644 src/qtui/settingspages/capseditdlg.ui diff --git a/src/qtui/settingspages/capseditdlg.ui b/src/qtui/settingspages/capseditdlg.ui new file mode 100644 index 00000000..23284eb2 --- /dev/null +++ b/src/qtui/settingspages/capseditdlg.ui @@ -0,0 +1,112 @@ + + + CapsEditDlg + + + + 0 + 0 + 475 + 154 + + + + Edit Network Features + + + + + + <p>Enter a space-separated list of IRCv3 capabilities to ignore:</p> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + + + + <p>A list of capabilities may be found at <a href="https://ircv3.net/irc/">https://ircv3.net/irc/</a>.</p> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + true + + + Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse + + + + + + + Qt::Vertical + + + + 270 + 0 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults + + + + + + + + + buttonBox + accepted() + CapsEditDlg + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + CapsEditDlg + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/qtui/settingspages/networkssettingspage.cpp b/src/qtui/settingspages/networkssettingspage.cpp index 468f2b57..c9de1acc 100644 --- a/src/qtui/settingspages/networkssettingspage.cpp +++ b/src/qtui/settingspages/networkssettingspage.cpp @@ -67,6 +67,7 @@ NetworksSettingsPage::NetworksSettingsPage(QWidget* parent) 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"}); @@ -178,6 +179,20 @@ void NetworksSettingsPage::load() "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(); @@ -982,6 +997,73 @@ void NetworksSettingsPage::on_saslStatusDetails_clicked() } } +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(); + 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("

%1


%2

") + .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 IRCv3 website provides more " + "technical details on the IRCv3 capabilities powering these features.")); + + if (!sortedCapsEnabled.isEmpty()) { + // Format the capabilities within blocks + auto formattedCaps = QString("%1") + .arg(sortedCapsEnabled.join(", ")); + + // Add the currently enabled capabilities to the list + // This creates a new QString, but this code is not performance-critical. + messageText = messageText.append(QString("

%1

").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("

%1


%2

") + .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; @@ -1213,6 +1295,47 @@ void ServerEditDlg::updateSslPort(bool isChecked) } } +/************************************************************************** + * 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 *************************************************************************/ diff --git a/src/qtui/settingspages/networkssettingspage.h b/src/qtui/settingspages/networkssettingspage.h index 5c9efca0..73bee52c 100644 --- a/src/qtui/settingspages/networkssettingspage.h +++ b/src/qtui/settingspages/networkssettingspage.h @@ -27,6 +27,7 @@ #include "network.h" #include "settingspage.h" +#include "ui_capseditdlg.h" #include "ui_networkadddlg.h" #include "ui_networkeditdlg.h" #include "ui_networkssettingspage.h" @@ -114,6 +115,16 @@ private slots: */ 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 @@ -137,7 +148,7 @@ private: 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 @@ -229,6 +240,25 @@ private: 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 diff --git a/src/qtui/settingspages/networkssettingspage.ui b/src/qtui/settingspages/networkssettingspage.ui index 7e6ad135..e56a7fc1 100644 --- a/src/qtui/settingspages/networkssettingspage.ui +++ b/src/qtui/settingspages/networkssettingspage.ui @@ -352,7 +352,7 @@ true - + 0 0 @@ -368,7 +368,7 @@ Note that Quassel IRC automatically rejoins channels, so /join will rarely be ne - + Connection @@ -658,7 +658,7 @@ Note that Quassel IRC automatically rejoins channels, so /join will rarely be ne - + Auto Identify @@ -881,14 +881,137 @@ Note that Quassel IRC automatically rejoins channels, so /join will rarely be ne - + + + Features + + + Configure the modern IRC messaging features Quassel supports + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + [icon] + + + + + + + + 0 + 0 + + + + These features require support from the network + + + true + + + + + + + Details... + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Configure which IRC capabilities Quassel will ignore during negotiation + + + Advanced... + + + + + + + Qt::Horizontal + + + + 13 + 35 + + + + + + + + + + <i>Changes apply after reconnecting to the network</i> + + + + + + + + + + Qt::Vertical + + + + 20 + 178 + + + + + + + Encodings - Configure advanced settings such as message encodings and automatic reconnect + Configure advanced settings such as message encodings - + @@ -1046,6 +1169,8 @@ This setting defines the encoding for messages that are not UTF-8. autoIdentify autoIdentifyService autoIdentifyPassword + enableCapsStatusDetails + enableCapsAdvanced useCustomEncodings sendEncoding recvEncoding diff --git a/src/qtui/settingspages/settingspages.cmake b/src/qtui/settingspages/settingspages.cmake index 3a72fc59..e04bea4b 100644 --- a/src/qtui/settingspages/settingspages.cmake +++ b/src/qtui/settingspages/settingspages.cmake @@ -36,6 +36,7 @@ set(SP_SOURCES set(SP_FORMS buffervieweditdlg.ui + capseditdlg.ui coreaccounteditdlg.ui createidentitydlg.ui identityeditwidget.ui -- 2.20.1