X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fqtui%2Fsettingspages%2Fcorehighlightsettingspage.cpp;h=a413b59d02d63ef269a666c3b95a1fd4e01d04e4;hp=fba21eb24333f082d032e9cfb8448ddf41af3b18;hb=0182f0e3977026de65be1edb6ca1e8d7ea0184fd;hpb=71d3d0d705a853fa8fea3729e13dbddf52363417 diff --git a/src/qtui/settingspages/corehighlightsettingspage.cpp b/src/qtui/settingspages/corehighlightsettingspage.cpp index fba21eb2..a413b59d 100644 --- a/src/qtui/settingspages/corehighlightsettingspage.cpp +++ b/src/qtui/settingspages/corehighlightsettingspage.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2016 by the Quassel Project * + * Copyright (C) 2005-2018 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -19,6 +19,7 @@ ***************************************************************************/ #include +#include #include #include "client.h" @@ -26,7 +27,11 @@ #include "qtui.h" CoreHighlightSettingsPage::CoreHighlightSettingsPage(QWidget *parent) - : SettingsPage(tr("Interface"), tr("Core-Side Highlights"), parent) + : SettingsPage(tr("Interface"), + // In Monolithic mode, local highlights are replaced by remote highlights + Quassel::runMode() == Quassel::Monolithic ? + tr("Highlights") : tr("Remote Highlights"), + parent) { ui.setupUi(this); @@ -37,8 +42,12 @@ CoreHighlightSettingsPage::CoreHighlightSettingsPage(QWidget *parent) ui.highlightNicksComboBox->addItem(tr("Current Nick"), QVariant(HighlightRuleManager::CurrentNick)); ui.highlightNicksComboBox->addItem(tr("None"), QVariant(HighlightRuleManager::NoNick)); + coreConnectionStateChanged(Client::isConnected()); // need a core connection! + connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool))); + connect(ui.highlightAdd, SIGNAL(clicked(bool)), this, SLOT(addNewHighlightRow())); connect(ui.highlightRemove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedHighlightRows())); + connect(ui.highlightImport, SIGNAL(clicked(bool)), this, SLOT(importRules())); connect(ui.ignoredAdd, SIGNAL(clicked(bool)), this, SLOT(addNewIgnoredRow())); connect(ui.ignoredRemove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedIgnoredRows())); @@ -53,6 +62,11 @@ CoreHighlightSettingsPage::CoreHighlightSettingsPage(QWidget *parent) this, SLOT(selectIgnoredRow(QTableWidgetItem * ))); + // Update the "Case sensitive" checkbox + connect(ui.highlightNicksComboBox, + SIGNAL(currentIndexChanged(int)), + this, + SLOT(highlightNicksChanged(int))); connect(ui.highlightNicksComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); connect(ui.nicksCaseSensitive, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); @@ -74,6 +88,20 @@ CoreHighlightSettingsPage::CoreHighlightSettingsPage(QWidget *parent) SLOT(ignoredTableChanged(QTableWidgetItem * ))); connect(Client::instance(), SIGNAL(connected()), this, SLOT(clientConnected())); + + // Warning icon + ui.coreUnsupportedIcon->setPixmap(QIcon::fromTheme("dialog-warning").pixmap(16)); +} + +void CoreHighlightSettingsPage::coreConnectionStateChanged(bool state) +{ + updateCoreSupportStatus(state); + setEnabled(state); + if (state) { + load(); + } else { + revert(); + } } void CoreHighlightSettingsPage::setupRuleTable(QTableWidget *table) const @@ -81,20 +109,60 @@ void CoreHighlightSettingsPage::setupRuleTable(QTableWidget *table) const table->verticalHeader()->hide(); table->setShowGrid(false); + table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn)->setToolTip( + tr("Enable/disable this rule")); + table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn)->setWhatsThis( + table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn)->toolTip()); + + table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn)->setToolTip( + tr("Phrase to match")); + table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn)->setWhatsThis( + table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn)->toolTip()); + table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setToolTip( - tr("RegEx: This option determines if the highlight rule should be interpreted as a regular expression or just as a keyword.")); + tr("RegEx: This option determines if the highlight rule, Sender, and " + "Channel should be interpreted as regular expressions or just as " + "keywords.")); table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setWhatsThis( - tr("RegEx: This option determines if the highlight rule should be interpreted as a regular expression or just as a keyword.")); + table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->toolTip()); table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setToolTip( - tr("CS: This option determines if the highlight rule should be interpreted case sensitive.")); + tr("CS: This option determines if the highlight rule, Sender, and " + "Channel should be interpreted case sensitive.")); table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setWhatsThis( - tr("CS: This option determines if the highlight rule should be interpreted case sensitive.")); + table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->toolTip()); + + table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn)->setToolTip( + tr("

Sender: Semicolon separated list of nick!ident@host names, " + "leave blank to match any nickname.

" + "

Example:
" + "Alice!*; Bob!*@example.com; Carol*!*; !Caroline!*
" + "would match on Alice, Bob with hostmask example.com, and " + "any nickname starting with Carol except for Caroline
" + "

If only inverted names are specified, it will match anything except for " + "what's specified (implicit wildcard).

" + "

Example:
" + "!Announce*!*; !Wheatley!aperture@*
" + "would match anything except for Wheatley with ident aperture or " + "any nickname starting with Announce

")); + table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn)->setWhatsThis( + table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn)->toolTip()); table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setToolTip( - tr("Channel: This regular expression determines for which channels the highlight rule works. Leave blank to match any channel. Put ! in the beginning to negate. Case insensitive.")); + tr("

Channel: Semicolon separated list of channel names, leave blank to " + "match any name.

" + "

Example:
" + "#quassel*; #foobar; !#quasseldroid
" + "would match on #foobar and any channel starting with #quassel " + "except for #quasseldroid
" + "

If only inverted names are specified, it will match anything except for " + "what's specified (implicit wildcard).

" + "

Example:
" + "!#quassel*; !#foobar
" + "would match anything except for #foobar or any channel starting with " + "#quassel

")); table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setWhatsThis( - tr("Channel: This regular expression determines for which channels the highlight rule works. Leave blank to match any channel. Put ! in the beginning to negate. Case insensitive.")); + table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->toolTip()); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents); @@ -111,6 +179,21 @@ void CoreHighlightSettingsPage::setupRuleTable(QTableWidget *table) const #endif } +void CoreHighlightSettingsPage::updateCoreSupportStatus(bool state) +{ + // Assume connected state as enforced by the settings page UI + if (!state || Client::isCoreFeatureEnabled(Quassel::Feature::CoreSideHighlights)) { + // Either disconnected or core supports highlights, enable highlight configuration and hide + // warning. Don't show the warning needlessly when disconnected. + ui.highlightsConfigWidget->setEnabled(true); + ui.coreUnsupportedWidget->setVisible(false); + } else { + // Core does not support highlights, show warning and disable highlight configuration + ui.highlightsConfigWidget->setEnabled(false); + ui.coreUnsupportedWidget->setVisible(true); + } +} + void CoreHighlightSettingsPage::clientConnected() { connect(Client::highlightRuleManager(), SIGNAL(updated()), SLOT(revert())); @@ -170,9 +253,45 @@ void CoreHighlightSettingsPage::addNewHighlightRow(bool enable, const QString &n enableItem->setCheckState(Qt::Unchecked); enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); + auto *senderItem = new QTableWidgetItem(sender); + auto *chanNameItem = new QTableWidgetItem(chanName); - auto *senderItem = new QTableWidgetItem(sender); + enableItem->setToolTip(tr("Enable/disable this rule")); + nameItem->setToolTip(tr("Phrase to match")); + regexItem->setToolTip( + tr("RegEx: This option determines if the highlight rule, Sender, and " + "Channel should be interpreted as regular expressions or just as " + "keywords.")); + csItem->setToolTip( + tr("CS: This option determines if the highlight rule, Sender, and " + "Channel should be interpreted case sensitive.")); + senderItem->setToolTip( + tr("

Sender: Semicolon separated list of nick!ident@host names, " + "leave blank to match any nickname.

" + "

Example:
" + "Alice!*; Bob!*@example.com; Carol*!*; !Caroline!*
" + "would match on Alice, Bob with hostmask example.com, and " + "any nickname starting with Carol except for Caroline
" + "

If only inverted names are specified, it will match anything except for " + "what's specified (implicit wildcard).

" + "

Example:
" + "!Announce*!*; !Wheatley!aperture@*
" + "would match anything except for Wheatley with ident aperture or " + "any nickname starting with Announce

")); + chanNameItem->setToolTip( + tr("

Channel: Semicolon separated list of channel names, leave blank to " + "match any name.

" + "

Example:
" + "#quassel*; #foobar; !#quasseldroid
" + "would match on #foobar and any channel starting with #quassel " + "except for #quasseldroid
" + "

If only inverted names are specified, it will match anything except for " + "what's specified (implicit wildcard).

" + "

Example:
" + "!#quassel*; !#foobar
" + "would match anything except for #foobar or any channel starting with " + "#quassel

")); int lastRow = ui.highlightTable->rowCount() - 1; ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem); @@ -220,6 +339,30 @@ void CoreHighlightSettingsPage::addNewIgnoredRow(bool enable, const QString &nam auto *senderItem = new QTableWidgetItem(sender); + enableItem->setToolTip(tr("Enable/disable this rule")); + nameItem->setToolTip(tr("Phrase to match")); + regexItem->setToolTip( + tr("RegEx: This option determines if the highlight rule should be " + "interpreted as a regular expression or just as a keyword.")); + csItem->setToolTip( + tr("CS: This option determines if the highlight rule should be interpreted " + "case sensitive.")); + senderItem->setToolTip( + tr("Sender: This option specifies which sender nicknames match. Leave " + "blank to match any nickname.")); + chanNameItem->setToolTip( + tr("

Channel: Semicolon separated list of channel names.

" + "

Example:
" + "#quassel*; #foobar; !#quasseldroid
" + "would match on #foobar and any channel starting with #quassel except " + "for #quasseldroid
" + "

If only inverted names are specified, it will match anything except for " + "what's specified (implicit wildcard).

" + "

Example:
" + "!#quassel*; !#foobar
" + "would match anything except for #foobar or any channel starting with " + "#quassel

")); + int lastRow = ui.ignoredTable->rowCount() - 1; ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem); ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::RegExColumn, regexItem); @@ -270,6 +413,12 @@ void CoreHighlightSettingsPage::removeSelectedIgnoredRows() } } +void CoreHighlightSettingsPage::highlightNicksChanged(const int index) { + // Only allow toggling "Case sensitive" when a nickname will be highlighted + auto highlightNickType = ui.highlightNicksComboBox->itemData(index).value(); + ui.nicksCaseSensitive->setEnabled(highlightNickType != HighlightRuleManager::NoNick); +} + void CoreHighlightSettingsPage::selectHighlightRow(QTableWidgetItem *item) { int row = item->row(); @@ -294,7 +443,9 @@ void CoreHighlightSettingsPage::emptyHighlightTable() if (ui.highlightTable->rowCount() != highlightList.size()) { qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!"; } - ui.highlightTable->clearContents(); + while (ui.highlightTable->rowCount()) { + ui.highlightTable->removeRow(0); + } highlightList.clear(); } @@ -304,7 +455,9 @@ void CoreHighlightSettingsPage::emptyIgnoredTable() if (ui.ignoredTable->rowCount() != ignoredList.size()) { qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!"; } - ui.ignoredTable->clearContents(); + while (ui.ignoredTable->rowCount()) { + ui.ignoredTable->removeRow(0); + } ignoredList.clear(); } @@ -408,6 +561,8 @@ void CoreHighlightSettingsPage::load() int highlightNickType = ruleManager->highlightNick(); ui.highlightNicksComboBox->setCurrentIndex(ui.highlightNicksComboBox->findData(QVariant(highlightNickType))); + // Trigger the initial update of nicksCaseSensitive being enabled or not + highlightNicksChanged(ui.highlightNicksComboBox->currentIndex()); ui.nicksCaseSensitive->setChecked(ruleManager->nicksCaseSensitive()); setChangedState(false); @@ -457,3 +612,86 @@ void CoreHighlightSettingsPage::widgetHasChanged() { setChangedState(true); } + +void CoreHighlightSettingsPage::on_coreUnsupportedDetails_clicked() +{ + // Re-use translations of "Local Highlights" as this is a word-for-word reference, forcing all + // spaces to non-breaking + const QString localHighlightsName = tr("Local Highlights").replace(" ", " "); + + const QString remoteHighlightsMsgText = + QString("

%1


%2


%3

" + ).arg(tr("Your Quassel core is too old to support remote highlights"), + tr("You need a Quassel core v0.13.0 or newer to configure remote " + "highlights."), + tr("You can still configure highlights for this device only in " + "%1.").arg(localHighlightsName)); + + QMessageBox::warning(this, + tr("Remote Highlights unsupported"), + remoteHighlightsMsgText); +} + +void CoreHighlightSettingsPage::importRules() { + NotificationSettings notificationSettings; + + const auto localHighlightList = notificationSettings.highlightList(); + + // Re-use translations of "Local Highlights" as this is a word-for-word reference, forcing all + // spaces to non-breaking + const QString localHighlightsName = tr("Local Highlights").replace(" ", " "); + + if (localHighlightList.count() == 0) { + // No highlight rules exist to import, do nothing + QMessageBox::information(this, + tr("No local highlights"), + tr("No highlight rules in %1." + ).arg(localHighlightsName)); + return; + } + + int ret = QMessageBox::question(this, + tr("Import local highlights?"), + tr("Import all highlight rules from %1?" + ).arg(localHighlightsName), + QMessageBox::Yes|QMessageBox::No, + QMessageBox::No); + + if (ret == QMessageBox::No) { + // Only two options, Yes or No, just return if No + return; + } + + auto clonedManager = HighlightRuleManager(); + clonedManager.fromVariantMap(Client::highlightRuleManager()->toVariantMap()); + + for (const auto &variant : notificationSettings.highlightList()) { + auto highlightRule = variant.toMap(); + + clonedManager.addHighlightRule( + highlightRule["Name"].toString(), + highlightRule["RegEx"].toBool(), + highlightRule["CS"].toBool(), + highlightRule["Enable"].toBool(), + false, + "", + highlightRule["Channel"].toString() + ); + } + + Client::highlightRuleManager()->requestUpdate(clonedManager.toVariantMap()); + setChangedState(false); + load(); + + // Give a heads-up that all succeeded + QMessageBox::information(this, + tr("Imported local highlights"), + tr("%1 highlight rules successfully imported." + ).arg(QString::number(localHighlightList.count()))); +} + +bool CoreHighlightSettingsPage::isSelectable() const { + return Client::isConnected(); + // We check for Quassel::Feature::CoreSideHighlights when loading this page, allowing us to show + // a friendly error message. +}