X-Git-Url: https://git.quassel-irc.org/?a=blobdiff_plain;f=src%2Fqtui%2Fsettingspages%2Fnetworkssettingspage.cpp;h=cc8dda2a533fdcf1c9e2287afbee7db2e57128de;hb=4c5b4bf5355413e3f3df3704512ff350fa062961;hp=bcdc6cfd897d42145a4b96fe5c1868ae727c6af3;hpb=6793871295193890d2a3d8ec90d3f9a387dd8331;p=quassel.git diff --git a/src/qtui/settingspages/networkssettingspage.cpp b/src/qtui/settingspages/networkssettingspage.cpp index bcdc6cfd..cc8dda2a 100644 --- a/src/qtui/settingspages/networkssettingspage.cpp +++ b/src/qtui/settingspages/networkssettingspage.cpp @@ -32,6 +32,9 @@ #include "settingspagedlg.h" #include "util.h" +// IRCv3 capabilities +#include "irccap.h" + #include "settingspages/identitiessettingspage.h" NetworksSettingsPage::NetworksSettingsPage(QWidget *parent) @@ -68,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); @@ -89,12 +96,12 @@ NetworksSettingsPage::NetworksSettingsPage(QWidget *parent) connect(ui.identityList, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); //connect(ui.randomServer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); connect(ui.performEdit, SIGNAL(textChanged()), this, SLOT(widgetHasChanged())); - connect(ui.autoIdentify, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); - connect(ui.autoIdentifyService, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged())); - connect(ui.autoIdentifyPassword, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged())); connect(ui.sasl, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); connect(ui.saslAccount, SIGNAL(textEdited(QString)), this, SLOT(widgetHasChanged())); connect(ui.saslPassword, SIGNAL(textEdited(QString)), this, SLOT(widgetHasChanged())); + connect(ui.autoIdentify, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); + connect(ui.autoIdentifyService, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged())); + connect(ui.autoIdentifyPassword, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged())); connect(ui.useCustomEncodings, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); connect(ui.sendEncoding, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); connect(ui.recvEncoding, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); @@ -348,6 +355,41 @@ void NetworksSettingsPage::setItemState(NetworkId id, QListWidgetItem *item) } +void NetworksSettingsPage::setNetworkCapStates(NetworkId id) +{ + const Network *net = Client::network(id); + 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); + } + + // Add additional capability-dependent interface updates here + } else { + // Network is disconnected + // [SASL] + setSASLStatus(CapSupportStatus::Disconnected); + + // Add additional capability-dependent interface updates here + } + } else { + // 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] + setSASLStatus(CapSupportStatus::Unknown); + + // Add additional capability-dependent interface updates here + } +} + + void NetworksSettingsPage::coreConnectionStateChanged(bool state) { this->setEnabled(state); @@ -434,6 +476,10 @@ void NetworksSettingsPage::clientNetworkAdded(NetworkId id) connect(Client::network(id), SIGNAL(connectionStateSet(Network::ConnectionState)), this, SLOT(networkConnectionStateChanged(Network::ConnectionState))); connect(Client::network(id), SIGNAL(connectionError(const QString &)), this, SLOT(networkConnectionError(const QString &))); + + // Handle capability changes in case a server dis/connects with the settings window open. + connect(Client::network(id), SIGNAL(capAdded(const QString &)), this, SLOT(clientNetworkCapsUpdated())); + connect(Client::network(id), SIGNAL(capRemoved(const QString &)), this, SLOT(clientNetworkCapsUpdated())); } @@ -478,6 +524,11 @@ void NetworksSettingsPage::networkConnectionStateChanged(Network::ConnectionStat } */ setItemState(net->networkId()); + if (net->networkId() == currentId) { + // Network is currently shown. Update the capability-dependent UI in case capabilities have + // changed. + setNetworkCapStates(currentId); + } setWidgetStates(); } @@ -545,6 +596,8 @@ void NetworksSettingsPage::displayNetwork(NetworkId id) } //setItemState(id); //ui.randomServer->setChecked(info.useRandomServer); + // Update the capability-dependent UI in case capabilities have changed. + setNetworkCapStates(id); ui.performEdit->setPlainText(info.perform.join("\n")); ui.autoIdentify->setChecked(info.useAutoIdentify); ui.autoIdentifyService->setText(info.autoIdentifyService); @@ -635,20 +688,79 @@ void NetworksSettingsPage::saveToNetworkInfo(NetworkInfo &info) } +void NetworksSettingsPage::clientNetworkCapsUpdated() +{ + // Grab the updated network + const Network *net = qobject_cast(sender()); + if (!net) { + qWarning() << "Update request for unknown network received!"; + return; + } + if (net->networkId() == currentId) { + // Network is currently shown. Update the capability-dependent UI in case capabilities have + // changed. + setNetworkCapStates(currentId); + } +} + + +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("%1").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("%1").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("%1").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("%1").arg(tr("Supported by network"))); + ui.saslStatusIcon->setPixmap(infoIcon.pixmap(16)); + break; + } + } +} + + #ifdef HAVE_SSL void NetworksSettingsPage::sslUpdated() { if (_cid && !_cid->sslKey().isNull()) { - ui.saslAccount->setDisabled(true); - ui.saslAccountLabel->setDisabled(true); - ui.saslPassword->setDisabled(true); - ui.saslPasswordLabel->setDisabled(true); + ui.saslContents->setDisabled(true); ui.saslExtInfo->setHidden(false); } else { - ui.saslAccount->setDisabled(false); - ui.saslAccountLabel->setDisabled(false); - ui.saslPassword->setDisabled(false); - ui.saslPasswordLabel->setDisabled(false); + ui.saslContents->setDisabled(false); + // Directly re-enabling causes the widgets to ignore the parent "Use SASL Authentication" + // state to indicate whether or not it's disabled. To workaround this, keep track of + // whether or not "Use SASL Authentication" is enabled, then quickly uncheck/recheck the + // group box. + if (!ui.sasl->isChecked()) { + // SASL is not enabled, uncheck/recheck the group box to re-disable saslContents. + // Leaving saslContents disabled doesn't work as that prevents it from re-enabling if + // sasl is later checked. + ui.sasl->setChecked(true); + ui.sasl->setChecked(false); + } ui.saslExtInfo->setHidden(true); } } @@ -822,6 +934,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(); + 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("

%1


%2


%3

" + ).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;