Use label and Details button, check if connected
authorShane Synan <digitalcircuit36939@gmail.com>
Sat, 7 Jan 2017 02:40:22 +0000 (20:40 -0600)
committerManuel Nickschas <sputnick@quassel-irc.org>
Wed, 12 Apr 2017 21:30:16 +0000 (23:30 +0200)
Keep "Use SASL Authentication" static, to avoid confusion and
concerns with longer languages.

Add another row with an icon, text, and "Details..." button to show
current SASL availability.

Check if disconnected separately from network existing and capability
negotiation support.  Show a different message when disconnected from
the network.  This should help reduce confusion.

Move SASL status UI updates to separate function to avoid cluttering
general capability updates handling function.

src/qtui/settingspages/networkssettingspage.cpp
src/qtui/settingspages/networkssettingspage.h
src/qtui/settingspages/networkssettingspage.ui

index 52f062f..db51da3 100644 (file)
@@ -71,6 +71,10 @@ NetworksSettingsPage::NetworksSettingsPage(QWidget *parent)
     connectingIcon = QIcon::fromTheme("network-wired"); // FIXME network-connecting
     disconnectedIcon = QIcon::fromTheme("network-disconnect");
 
+    // Status icons
+    infoIcon = QIcon::fromTheme("dialog-information");
+    warningIcon = QIcon::fromTheme("dialog-warning");
+
     foreach(int mib, QTextCodec::availableMibs()) {
         QByteArray codec = QTextCodec::codecForMib(mib)->name();
         ui.sendEncoding->addItem(codec);
@@ -354,34 +358,32 @@ void NetworksSettingsPage::setItemState(NetworkId id, QListWidgetItem *item)
 void NetworksSettingsPage::setNetworkCapStates(NetworkId id)
 {
     const Network *net = Client::network(id);
-    if ((Client::coreFeatures() & Quassel::CapNegotiation)
-            && net && net->connectionState() != Network::Disconnected) {
-        // If Capability Negotiation isn't supported by the core, no capabilities are active.
-        // If we're here, the network exists and is connected, check available capabilities...
-        // Don't use net->isConnected() as that won't be true during capability negotiation when
-        // capabilities are added and removed.
+    if ((Client::coreFeatures() & Quassel::CapNegotiation) && net) {
+        // Capability negotiation is supported, network exists.
+        // Check if the network is connected.  Don't use net->isConnected() as that won't be true
+        // during capability negotiation when capabilities are added and removed.
+        if (net->connectionState() != Network::Disconnected) {
+            // Network exists and is connected, check available capabilities...
+            // [SASL]
+            if (net->saslMaybeSupports(IrcCap::SaslMech::PLAIN)) {
+                setSASLStatus(CapSupportStatus::MaybeSupported);
+            } else {
+                setSASLStatus(CapSupportStatus::MaybeUnsupported);
+            }
 
-        // [SASL]
-        if (net->saslMaybeSupports(IrcCap::SaslMech::PLAIN)) {
-            // The network advertises support for SASL PLAIN.  Encourage using it!  Unfortunately we
-            // don't know for sure if it's desired or functional.
-            ui.sasl->setTitle(QString("%1 (%2)").arg(tr("Use SASL Authentication"),
-                                                     tr("preferred")));
+            // Add additional capability-dependent interface updates here
         } else {
-            // The network doesn't advertise support for SASL PLAIN.  Here be dragons.
-            ui.sasl->setTitle(QString("%1 (%2)").arg(tr("Use SASL Authentication"),
-                                                     tr("might not work")));
-        }
-        // Split up the messages to ease translation and re-use existing "Use SASL Authentication"
-        // translations.  If some languages rearrange phrases such that this would not make sense,
-        // these strings can be merged into one.
+            // Network is disconnected
+            // [SASL]
+            setSASLStatus(CapSupportStatus::Disconnected);
 
-        // Add additional capability-dependent interface updates here
+            // Add additional capability-dependent interface updates here
+        }
     } else {
-        // We're not connected or the network doesn't yet exist.  Don't assume anything and reset
-        // all capability-dependent interface elements to neutral.
+        // Capability negotiation is not supported and/or network doesn't exist.
+        // Don't assume anything and reset all capability-dependent interface elements to neutral.
         // [SASL]
-        ui.sasl->setTitle(tr("Use SASL Authentication"));
+        setSASLStatus(CapSupportStatus::Unknown);
 
         // Add additional capability-dependent interface updates here
     }
@@ -702,6 +704,44 @@ void NetworksSettingsPage::clientNetworkCapsUpdated()
 }
 
 
+void NetworksSettingsPage::setSASLStatus(const CapSupportStatus saslStatus)
+{
+    if (_saslStatusSelected != saslStatus) {
+        // Update the cached copy of SASL status used with the Details dialog
+        _saslStatusSelected = saslStatus;
+
+        // Update the user interface
+        switch (saslStatus) {
+            case CapSupportStatus::Unknown:
+                // There's no capability negotiation or network doesn't exist.  Don't assume
+                // anything.
+                ui.saslStatusLabel->setText(QString("<i>%1</i>").arg(
+                                            tr("Could not check if supported by network")));
+                ui.saslStatusIcon->setPixmap(infoIcon.pixmap(16));
+                break;
+            case CapSupportStatus::Disconnected:
+                // Disconnected from network, no way to check.
+                ui.saslStatusLabel->setText(QString("<i>%1</i>").arg(
+                                                tr("Cannot check if supported when disconnected")));
+                ui.saslStatusIcon->setPixmap(infoIcon.pixmap(16));
+                break;
+            case CapSupportStatus::MaybeUnsupported:
+                // The network doesn't advertise support for SASL PLAIN.  Here be dragons.
+                ui.saslStatusLabel->setText(QString("<i>%1</i>").arg(
+                                                tr("Not currently supported by network")));
+                ui.saslStatusIcon->setPixmap(warningIcon.pixmap(16));
+                break;
+            case CapSupportStatus::MaybeSupported:
+                // The network advertises support for SASL PLAIN.  Encourage using it!
+                // Unfortunately we don't know for sure if it's desired or functional.
+                ui.saslStatusLabel->setText(QString("<i>%1</i>").arg(tr("Supported by network")));
+                ui.saslStatusIcon->setPixmap(infoIcon.pixmap(16));
+                break;
+        }
+    }
+}
+
+
 #ifdef HAVE_SSL
 void NetworksSettingsPage::sslUpdated()
 {
@@ -889,6 +929,67 @@ void NetworksSettingsPage::on_editIdentities_clicked()
 }
 
 
+void NetworksSettingsPage::on_saslStatusDetails_clicked()
+{
+    if (ui.networkList->selectedItems().count()) {
+        NetworkId netid = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value<NetworkId>();
+        QString &netName = networkInfos[netid].networkName;
+
+        // If these strings are visible, one of the status messages wasn't detected below.
+        QString saslStatusHeader = "[header unintentionally left blank]";
+        QString saslStatusExplanation = "[explanation unintentionally left blank]";
+
+        // If true, show a warning icon instead of an information icon
+        bool useWarningIcon = false;
+
+        // Determine which explanation to show
+        switch (_saslStatusSelected) {
+        case CapSupportStatus::Unknown:
+            saslStatusHeader = tr("Could not check if SASL supported by network");
+            saslStatusExplanation = tr("Quassel could not check if \"%1\" supports SASL.  This may "
+                                       "be due to unsaved changes or an older Quassel core.  You "
+                                       "can still try using SASL.").arg(netName);
+            break;
+        case CapSupportStatus::Disconnected:
+            saslStatusHeader = tr("Cannot check if SASL supported when disconnected");
+            saslStatusExplanation = tr("Quassel cannot check if \"%1\" supports SASL when "
+                                       "disconnected.  Connect to the network, or try using SASL "
+                                       "anyways.").arg(netName);
+            break;
+        case CapSupportStatus::MaybeUnsupported:
+            saslStatusHeader = tr("SASL not currently supported by network");
+            saslStatusExplanation = tr("The network \"%1\" does not currently support SASL.  "
+                                       "However, support might be added later on.").arg(netName);
+            useWarningIcon = true;
+            break;
+        case CapSupportStatus::MaybeSupported:
+            saslStatusHeader = tr("SASL supported by network");
+            saslStatusExplanation = tr("The network \"%1\" supports SASL.  In most cases, you "
+                                       "should use SASL instead of NickServ identification."
+                                       ).arg(netName);
+            break;
+        }
+
+        // Process this in advance for reusability below
+        const QString saslStatusMsgTitle = tr("SASL support for \"%1\"").arg(netName);
+        const QString saslStatusMsgText =
+                QString("<p><b>%1</b></p></br><p>%2</p></br><p><i>%3</i></p>"
+                        ).arg(saslStatusHeader,
+                              saslStatusExplanation,
+                              tr("SASL is a standardized way to log in and identify yourself to "
+                                 "IRC servers."));
+
+        if (useWarningIcon) {
+            // Show as a warning dialog box
+            QMessageBox::warning(this, saslStatusMsgTitle, saslStatusMsgText);
+        } else {
+            // Show as an information dialog box
+            QMessageBox::information(this, saslStatusMsgTitle, saslStatusMsgText);
+        }
+    }
+}
+
+
 IdentityId NetworksSettingsPage::defaultIdentity() const
 {
     IdentityId defaultId = 0;
index e88f281..b255793 100644 (file)
@@ -100,7 +100,23 @@ private slots:
     void on_upServer_clicked();
     void on_downServer_clicked();
 
+    /**
+     * Event handler for SASL status Details button
+     */
+    void on_saslStatusDetails_clicked();
+
 private:
+    /**
+     * Status of capability support
+     */
+    enum CapSupportStatus {
+        Unknown,           ///< Old core, or otherwise unknown, can't make assumptions
+        Disconnected,      ///< Disconnected from network, can't determine
+        MaybeUnsupported,  ///< Server does not advertise support at this moment
+        MaybeSupported     ///< Server advertises support at this moment
+    };
+    // Keep in mind networks can add, change, and remove capabilities at any time.
+
     Ui::NetworksSettingsPage ui;
 
     NetworkId currentId;
@@ -112,6 +128,11 @@ private:
 
     QIcon connectedIcon, connectingIcon, disconnectedIcon;
 
+    // Status icons
+    QIcon infoIcon, warningIcon;
+
+    CapSupportStatus _saslStatusSelected;  /// Status of SASL support for currently-selected network
+
     void reset();
     bool testHasChanged();
     QListWidgetItem *insertNetwork(NetworkId);
@@ -119,6 +140,13 @@ private:
     QListWidgetItem *networkItem(NetworkId) const;
     void saveToNetworkInfo(NetworkInfo &);
     IdentityId defaultIdentity() const;
+
+    /**
+     * Update the SASL settings interface according to the given SASL state
+     *
+     * @param[in] saslStatus Current status of SASL support.
+     */
+    void setSASLStatus(const CapSupportStatus saslStatus);
 };
 
 
index 160c6b3..5598e9a 100644 (file)
@@ -680,52 +680,87 @@ Note that Quassel IRC automatically rejoins channels, so /join will rarely be ne
             <property name="checked">
              <bool>true</bool>
             </property>
-            <layout class="QGridLayout" name="gridLayout_2">
-             <item row="1" column="1">
-              <widget class="QLineEdit" name="saslPassword">
-               <property name="enabled">
-                <bool>true</bool>
-               </property>
-               <property name="toolTip">
-                <string>Account password</string>
-               </property>
-               <property name="echoMode">
-                <enum>QLineEdit::Password</enum>
-               </property>
-              </widget>
-             </item>
-             <item row="1" column="0">
-              <widget class="QLabel" name="saslPasswordLabel">
-               <property name="enabled">
-                <bool>true</bool>
-               </property>
-               <property name="text">
-                <string>Password:</string>
-               </property>
-              </widget>
-             </item>
-             <item row="0" column="0">
-              <widget class="QLabel" name="saslAccountLabel">
-               <property name="enabled">
-                <bool>true</bool>
-               </property>
-               <property name="text">
-                <string>Account:</string>
-               </property>
-              </widget>
+            <layout class="QVBoxLayout" name="verticalLayout_11">
+             <item>
+              <layout class="QGridLayout" name="gridLayout_2">
+               <item row="0" column="1">
+                <widget class="QLineEdit" name="saslAccount">
+                 <property name="enabled">
+                  <bool>true</bool>
+                 </property>
+                 <property name="toolTip">
+                  <string>Account name, often the same as your nickname</string>
+                 </property>
+                 <property name="text">
+                  <string/>
+                 </property>
+                </widget>
+               </item>
+               <item row="0" column="0">
+                <widget class="QLabel" name="saslAccountLabel">
+                 <property name="enabled">
+                  <bool>true</bool>
+                 </property>
+                 <property name="text">
+                  <string>Account:</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="1" column="1">
+                <widget class="QLineEdit" name="saslPassword">
+                 <property name="enabled">
+                  <bool>true</bool>
+                 </property>
+                 <property name="toolTip">
+                  <string>Account password</string>
+                 </property>
+                 <property name="echoMode">
+                  <enum>QLineEdit::Password</enum>
+                 </property>
+                </widget>
+               </item>
+               <item row="1" column="0">
+                <widget class="QLabel" name="saslPasswordLabel">
+                 <property name="enabled">
+                  <bool>true</bool>
+                 </property>
+                 <property name="text">
+                  <string>Password:</string>
+                 </property>
+                </widget>
+               </item>
+              </layout>
              </item>
-             <item row="0" column="1">
-              <widget class="QLineEdit" name="saslAccount">
-               <property name="enabled">
-                <bool>true</bool>
-               </property>
-               <property name="toolTip">
-                <string>Account name, often the same as your nickname</string>
-               </property>
-               <property name="text">
-                <string/>
-               </property>
-              </widget>
+             <item>
+              <layout class="QHBoxLayout" name="horizontalLayout_7">
+               <item>
+                <widget class="QLabel" name="saslStatusIcon">
+                 <property name="text">
+                  <string notr="true">[icon]</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QLabel" name="saslStatusLabel">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="text">
+                  <string>Could not detect if supported by server</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QPushButton" name="saslStatusDetails">
+                 <property name="text">
+                  <string>Details...</string>
+                 </property>
+                </widget>
+               </item>
+              </layout>
              </item>
             </layout>
            </widget>
@@ -982,6 +1017,7 @@ Unless you *really* know what you do, leave this as ISO-8859-1!</string>
   <tabstop>sasl</tabstop>
   <tabstop>saslAccount</tabstop>
   <tabstop>saslPassword</tabstop>
+  <tabstop>saslStatusDetails</tabstop>
   <tabstop>autoIdentify</tabstop>
   <tabstop>autoIdentifyService</tabstop>
   <tabstop>autoIdentifyPassword</tabstop>