1 /***************************************************************************
2 * Copyright (C) 2005-2018 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
21 #include <QHeaderView>
22 #include <QMessageBox>
23 #include <QTableWidget>
26 #include "corehighlightsettingspage.h"
29 CoreHighlightSettingsPage::CoreHighlightSettingsPage(QWidget *parent)
30 : SettingsPage(tr("Interface"),
31 // In Monolithic mode, local highlights are replaced by remote highlights
32 Quassel::runMode() == Quassel::Monolithic ?
33 tr("Highlights") : tr("Remote Highlights"),
38 setupRuleTable(ui.highlightTable);
39 setupRuleTable(ui.ignoredTable);
41 ui.highlightNicksComboBox->addItem(tr("All Nicks from Identity"), QVariant(HighlightRuleManager::AllNicks));
42 ui.highlightNicksComboBox->addItem(tr("Current Nick"), QVariant(HighlightRuleManager::CurrentNick));
43 ui.highlightNicksComboBox->addItem(tr("None"), QVariant(HighlightRuleManager::NoNick));
45 coreConnectionStateChanged(Client::isConnected()); // need a core connection!
46 connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool)));
48 connect(ui.highlightAdd, SIGNAL(clicked(bool)), this, SLOT(addNewHighlightRow()));
49 connect(ui.highlightRemove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedHighlightRows()));
50 connect(ui.highlightImport, SIGNAL(clicked(bool)), this, SLOT(importRules()));
52 connect(ui.ignoredAdd, SIGNAL(clicked(bool)), this, SLOT(addNewIgnoredRow()));
53 connect(ui.ignoredRemove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedIgnoredRows()));
55 // TODO: search for a better signal (one that emits everytime a selection has been changed for one item)
56 connect(ui.highlightTable,
57 SIGNAL(itemClicked(QTableWidgetItem * )),
59 SLOT(selectHighlightRow(QTableWidgetItem * )));
60 connect(ui.ignoredTable,
61 SIGNAL(itemClicked(QTableWidgetItem * )),
63 SLOT(selectIgnoredRow(QTableWidgetItem * )));
65 // Update the "Case sensitive" checkbox
66 connect(ui.highlightNicksComboBox,
67 SIGNAL(currentIndexChanged(int)),
69 SLOT(highlightNicksChanged(int)));
71 connect(ui.highlightNicksComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
72 connect(ui.nicksCaseSensitive, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
74 connect(ui.highlightAdd, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
75 connect(ui.highlightRemove, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
77 connect(ui.ignoredAdd, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
78 connect(ui.ignoredRemove, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
80 connect(ui.highlightTable,
81 SIGNAL(itemChanged(QTableWidgetItem * )),
83 SLOT(highlightTableChanged(QTableWidgetItem * )));
85 connect(ui.ignoredTable,
86 SIGNAL(itemChanged(QTableWidgetItem * )),
88 SLOT(ignoredTableChanged(QTableWidgetItem * )));
90 connect(Client::instance(), SIGNAL(connected()), this, SLOT(clientConnected()));
93 ui.coreUnsupportedIcon->setPixmap(QIcon::fromTheme("dialog-warning").pixmap(16));
96 void CoreHighlightSettingsPage::coreConnectionStateChanged(bool state)
98 updateCoreSupportStatus(state);
107 void CoreHighlightSettingsPage::setupRuleTable(QTableWidget *table) const
109 table->verticalHeader()->hide();
110 table->setShowGrid(false);
112 table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn)->setToolTip(
113 tr("Enable/disable this rule"));
114 table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn)->setWhatsThis(
115 table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn)->toolTip());
117 table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn)->setToolTip(
118 tr("Phrase to match"));
119 table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn)->setWhatsThis(
120 table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn)->toolTip());
122 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setToolTip(
123 tr("<b>RegEx</b>: This option determines if the highlight rule, <i>Sender</i>, and "
124 "<i>Channel</i> should be interpreted as <b>regular expressions</b> or just as "
126 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setWhatsThis(
127 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->toolTip());
129 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setToolTip(
130 tr("<b>CS</b>: This option determines if the highlight rule, <i>Sender</i>, and "
131 "<i>Channel</i> should be interpreted <b>case sensitive</b>."));
132 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setWhatsThis(
133 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->toolTip());
135 table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn)->setToolTip(
136 tr("<p><b>Sender</b>: Semicolon separated list of <i>nick!ident@host</i> names, "
137 "leave blank to match any nickname.</p>"
138 "<p><i>Example:</i><br />"
139 "<i>Alice!*; Bob!*@example.com; Carol*!*; !Caroline!*</i><br />"
140 "would match on <i>Alice</i>, <i>Bob</i> with hostmask <i>example.com</i>, and "
141 "any nickname starting with <i>Carol</i> except for <i>Caroline</i><br />"
142 "<p>If only inverted names are specified, it will match anything except for "
143 "what's specified (implicit wildcard).</p>"
144 "<p><i>Example:</i><br />"
145 "<i>!Announce*!*; !Wheatley!aperture@*</i><br />"
146 "would match anything except for <i>Wheatley</i> with ident <i>aperture</i> or "
147 "any nickname starting with <i>Announce</i></p>"));
148 table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn)->setWhatsThis(
149 table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn)->toolTip());
151 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setToolTip(
152 tr("<p><b>Channel</b>: Semicolon separated list of channel names, leave blank to "
153 "match any name.</p>"
154 "<p><i>Example:</i><br />"
155 "<i>#quassel*; #foobar; !#quasseldroid</i><br />"
156 "would match on <i>#foobar</i> and any channel starting with <i>#quassel</i> "
157 "except for <i>#quasseldroid</i><br />"
158 "<p>If only inverted names are specified, it will match anything except for "
159 "what's specified (implicit wildcard).</p>"
160 "<p><i>Example:</i><br />"
161 "<i>!#quassel*; !#foobar</i><br />"
162 "would match anything except for <i>#foobar</i> or any channel starting with "
163 "<i>#quassel</i></p>"));
164 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setWhatsThis(
165 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->toolTip());
167 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
168 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents);
169 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::NameColumn, QHeaderView::Stretch);
170 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents);
171 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents);
172 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents);
174 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents);
175 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::NameColumn, QHeaderView::Stretch);
176 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents);
177 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents);
178 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents);
182 void CoreHighlightSettingsPage::updateCoreSupportStatus(bool state)
184 // Assume connected state as enforced by the settings page UI
185 if (!state || Client::isCoreFeatureEnabled(Quassel::Feature::CoreSideHighlights)) {
186 // Either disconnected or core supports highlights, enable highlight configuration and hide
187 // warning. Don't show the warning needlessly when disconnected.
188 ui.highlightsConfigWidget->setEnabled(true);
189 ui.coreUnsupportedWidget->setVisible(false);
191 // Core does not support highlights, show warning and disable highlight configuration
192 ui.highlightsConfigWidget->setEnabled(false);
193 ui.coreUnsupportedWidget->setVisible(true);
197 void CoreHighlightSettingsPage::clientConnected()
199 connect(Client::highlightRuleManager(), SIGNAL(updated()), SLOT(revert()));
202 void CoreHighlightSettingsPage::revert()
207 setChangedState(false);
211 bool CoreHighlightSettingsPage::hasDefaults() const
216 void CoreHighlightSettingsPage::defaults()
218 int highlightNickType = HighlightRuleManager::HighlightNickType::CurrentNick;
219 int defaultIndex = ui.highlightNicksComboBox->findData(QVariant(highlightNickType));
220 ui.highlightNicksComboBox->setCurrentIndex(defaultIndex);
221 ui.nicksCaseSensitive->setChecked(false);
222 emptyHighlightTable();
228 void CoreHighlightSettingsPage::addNewHighlightRow(bool enable, const QString &name, bool regex, bool cs,
229 const QString &sender, const QString &chanName, bool self)
231 ui.highlightTable->setRowCount(ui.highlightTable->rowCount() + 1);
233 auto *nameItem = new QTableWidgetItem(name);
235 auto *regexItem = new QTableWidgetItem("");
237 regexItem->setCheckState(Qt::Checked);
239 regexItem->setCheckState(Qt::Unchecked);
240 regexItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
242 auto *csItem = new QTableWidgetItem("");
244 csItem->setCheckState(Qt::Checked);
246 csItem->setCheckState(Qt::Unchecked);
247 csItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
249 auto *enableItem = new QTableWidgetItem("");
251 enableItem->setCheckState(Qt::Checked);
253 enableItem->setCheckState(Qt::Unchecked);
254 enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
256 auto *senderItem = new QTableWidgetItem(sender);
258 auto *chanNameItem = new QTableWidgetItem(chanName);
260 enableItem->setToolTip(tr("Enable/disable this rule"));
261 nameItem->setToolTip(tr("Phrase to match"));
262 regexItem->setToolTip(
263 tr("<b>RegEx</b>: This option determines if the highlight rule, <i>Sender</i>, and "
264 "<i>Channel</i> should be interpreted as <b>regular expressions</b> or just as "
267 tr("<b>CS</b>: This option determines if the highlight rule, <i>Sender</i>, and "
268 "<i>Channel</i> should be interpreted <b>case sensitive</b>."));
269 senderItem->setToolTip(
270 tr("<p><b>Sender</b>: Semicolon separated list of <i>nick!ident@host</i> names, "
271 "leave blank to match any nickname.</p>"
272 "<p><i>Example:</i><br />"
273 "<i>Alice!*; Bob!*@example.com; Carol*!*; !Caroline!*</i><br />"
274 "would match on <i>Alice</i>, <i>Bob</i> with hostmask <i>example.com</i>, and "
275 "any nickname starting with <i>Carol</i> except for <i>Caroline</i><br />"
276 "<p>If only inverted names are specified, it will match anything except for "
277 "what's specified (implicit wildcard).</p>"
278 "<p><i>Example:</i><br />"
279 "<i>!Announce*!*; !Wheatley!aperture@*</i><br />"
280 "would match anything except for <i>Wheatley</i> with ident <i>aperture</i> or "
281 "any nickname starting with <i>Announce</i></p>"));
282 chanNameItem->setToolTip(
283 tr("<p><b>Channel</b>: Semicolon separated list of channel names, leave blank to "
284 "match any name.</p>"
285 "<p><i>Example:</i><br />"
286 "<i>#quassel*; #foobar; !#quasseldroid</i><br />"
287 "would match on <i>#foobar</i> and any channel starting with <i>#quassel</i> "
288 "except for <i>#quasseldroid</i><br />"
289 "<p>If only inverted names are specified, it will match anything except for "
290 "what's specified (implicit wildcard).</p>"
291 "<p><i>Example:</i><br />"
292 "<i>!#quassel*; !#foobar</i><br />"
293 "would match anything except for <i>#foobar</i> or any channel starting with "
294 "<i>#quassel</i></p>"));
296 int lastRow = ui.highlightTable->rowCount() - 1;
297 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem);
298 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::RegExColumn, regexItem);
299 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::CsColumn, csItem);
300 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::EnableColumn, enableItem);
301 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::SenderColumn, senderItem);
302 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::ChanColumn, chanNameItem);
305 ui.highlightTable->setCurrentItem(nameItem);
307 highlightList << HighlightRuleManager::HighlightRule(name, regex, cs, enable, false, sender, chanName);
310 void CoreHighlightSettingsPage::addNewIgnoredRow(bool enable, const QString &name, bool regex, bool cs,
311 const QString &sender, const QString &chanName, bool self)
313 ui.ignoredTable->setRowCount(ui.ignoredTable->rowCount() + 1);
315 auto *nameItem = new QTableWidgetItem(name);
317 auto *regexItem = new QTableWidgetItem("");
319 regexItem->setCheckState(Qt::Checked);
321 regexItem->setCheckState(Qt::Unchecked);
322 regexItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
324 auto *csItem = new QTableWidgetItem("");
326 csItem->setCheckState(Qt::Checked);
328 csItem->setCheckState(Qt::Unchecked);
329 csItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
331 auto *enableItem = new QTableWidgetItem("");
333 enableItem->setCheckState(Qt::Checked);
335 enableItem->setCheckState(Qt::Unchecked);
336 enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
338 auto *chanNameItem = new QTableWidgetItem(chanName);
340 auto *senderItem = new QTableWidgetItem(sender);
342 enableItem->setToolTip(tr("Enable/disable this rule"));
343 nameItem->setToolTip(tr("Phrase to match"));
344 regexItem->setToolTip(
345 tr("<b>RegEx</b>: This option determines if the highlight rule should be "
346 "interpreted as a <b>regular expression</b> or just as a keyword."));
348 tr("<b>CS</b>: This option determines if the highlight rule should be interpreted "
349 "<b>case sensitive</b>."));
350 senderItem->setToolTip(
351 tr("<b>Sender</b>: This option specifies which sender nicknames match. Leave "
352 "blank to match any nickname."));
353 chanNameItem->setToolTip(
354 tr("<p><b>Channel</b>: Semicolon separated list of channel names.</p>"
355 "<p><i>Example:</i><br />"
356 "<i>#quassel*; #foobar; !#quasseldroid</i><br />"
357 "would match on #foobar and any channel starting with <i>#quassel</i> except "
358 "for <i>#quasseldroid</i><br />"
359 "<p>If only inverted names are specified, it will match anything except for "
360 "what's specified (implicit wildcard).</p>"
361 "<p><i>Example:</i><br />"
362 "<i>!#quassel*; !#foobar</i><br />"
363 "would match anything except for #foobar or any channel starting with "
364 "<i>#quassel</i></p>"));
366 int lastRow = ui.ignoredTable->rowCount() - 1;
367 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem);
368 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::RegExColumn, regexItem);
369 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::CsColumn, csItem);
370 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::EnableColumn, enableItem);
371 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::SenderColumn, senderItem);
372 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::ChanColumn, chanNameItem);
375 ui.ignoredTable->setCurrentItem(nameItem);
377 ignoredList << HighlightRuleManager::HighlightRule(name, regex, cs, enable, true, sender, chanName);
380 void CoreHighlightSettingsPage::removeSelectedHighlightRows()
382 QList<int> selectedRows;
383 QList<QTableWidgetItem *> selectedItemList = ui.highlightTable->selectedItems();
384 for (auto selectedItem : selectedItemList) {
385 selectedRows.append(selectedItem->row());
387 qSort(selectedRows.begin(), selectedRows.end(), qGreater<int>());
389 for (auto row : selectedRows) {
390 if (row != lastRow) {
391 ui.highlightTable->removeRow(row);
392 highlightList.removeAt(row);
398 void CoreHighlightSettingsPage::removeSelectedIgnoredRows()
400 QList<int> selectedRows;
401 QList<QTableWidgetItem *> selectedItemList = ui.ignoredTable->selectedItems();
402 for (auto selectedItem : selectedItemList) {
403 selectedRows.append(selectedItem->row());
405 qSort(selectedRows.begin(), selectedRows.end(), qGreater<int>());
407 for (auto row : selectedRows) {
408 if (row != lastRow) {
409 ui.ignoredTable->removeRow(row);
410 ignoredList.removeAt(row);
416 void CoreHighlightSettingsPage::highlightNicksChanged(const int index) {
417 // Only allow toggling "Case sensitive" when a nickname will be highlighted
418 auto highlightNickType = ui.highlightNicksComboBox->itemData(index).value<int>();
419 ui.nicksCaseSensitive->setEnabled(highlightNickType != HighlightRuleManager::NoNick);
422 void CoreHighlightSettingsPage::selectHighlightRow(QTableWidgetItem *item)
424 int row = item->row();
425 bool selected = item->isSelected();
427 ->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, CoreHighlightSettingsPage::ColumnCount - 1),
431 void CoreHighlightSettingsPage::selectIgnoredRow(QTableWidgetItem *item)
433 int row = item->row();
434 bool selected = item->isSelected();
436 ->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, CoreHighlightSettingsPage::ColumnCount - 1),
440 void CoreHighlightSettingsPage::emptyHighlightTable()
442 // ui.highlight and highlightList should have the same size, but just to make sure.
443 if (ui.highlightTable->rowCount() != highlightList.size()) {
444 qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!";
446 while (ui.highlightTable->rowCount()) {
447 ui.highlightTable->removeRow(0);
449 highlightList.clear();
452 void CoreHighlightSettingsPage::emptyIgnoredTable()
454 // ui.highlight and highlightList should have the same size, but just to make sure.
455 if (ui.ignoredTable->rowCount() != ignoredList.size()) {
456 qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!";
458 while (ui.ignoredTable->rowCount()) {
459 ui.ignoredTable->removeRow(0);
464 void CoreHighlightSettingsPage::highlightTableChanged(QTableWidgetItem *item)
466 if (item->row() + 1 > highlightList.size())
469 auto highlightRule = highlightList.value(item->row());
472 switch (item->column()) {
473 case CoreHighlightSettingsPage::EnableColumn:
474 highlightRule.isEnabled = (item->checkState() == Qt::Checked);
476 case CoreHighlightSettingsPage::NameColumn:
477 if (item->text() == "")
478 item->setText(tr("this shouldn't be empty"));
479 highlightRule.name = item->text();
481 case CoreHighlightSettingsPage::RegExColumn:
482 highlightRule.isRegEx = (item->checkState() == Qt::Checked);
484 case CoreHighlightSettingsPage::CsColumn:
485 highlightRule.isCaseSensitive = (item->checkState() == Qt::Checked);
487 case CoreHighlightSettingsPage::SenderColumn:
488 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
490 highlightRule.sender = item->text();
492 case CoreHighlightSettingsPage::ChanColumn:
493 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
495 highlightRule.chanName = item->text();
498 highlightList[item->row()] = highlightRule;
499 emit widgetHasChanged();
502 void CoreHighlightSettingsPage::ignoredTableChanged(QTableWidgetItem *item)
504 if (item->row() + 1 > ignoredList.size())
507 auto ignoredRule = ignoredList.value(item->row());
510 switch (item->column()) {
511 case CoreHighlightSettingsPage::EnableColumn:
512 ignoredRule.isEnabled = (item->checkState() == Qt::Checked);
514 case CoreHighlightSettingsPage::NameColumn:
515 if (item->text() == "")
516 item->setText(tr("this shouldn't be empty"));
517 ignoredRule.name = item->text();
519 case CoreHighlightSettingsPage::RegExColumn:
520 ignoredRule.isRegEx = (item->checkState() == Qt::Checked);
522 case CoreHighlightSettingsPage::CsColumn:
523 ignoredRule.isCaseSensitive = (item->checkState() == Qt::Checked);
525 case CoreHighlightSettingsPage::SenderColumn:
526 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
528 ignoredRule.sender = item->text();
530 case CoreHighlightSettingsPage::ChanColumn:
531 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
533 ignoredRule.chanName = item->text();
536 ignoredList[item->row()] = ignoredRule;
537 emit widgetHasChanged();
540 void CoreHighlightSettingsPage::load()
542 emptyHighlightTable();
545 auto ruleManager = Client::highlightRuleManager();
547 for (auto &rule : ruleManager->highlightRuleList()) {
548 if (rule.isInverse) {
549 addNewIgnoredRow(rule.isEnabled,
552 rule.isCaseSensitive,
557 addNewHighlightRow(rule.isEnabled, rule.name, rule.isRegEx, rule.isCaseSensitive, rule.sender,
562 int highlightNickType = ruleManager->highlightNick();
563 ui.highlightNicksComboBox->setCurrentIndex(ui.highlightNicksComboBox->findData(QVariant(highlightNickType)));
564 // Trigger the initial update of nicksCaseSensitive being enabled or not
565 highlightNicksChanged(ui.highlightNicksComboBox->currentIndex());
566 ui.nicksCaseSensitive->setChecked(ruleManager->nicksCaseSensitive());
568 setChangedState(false);
575 void CoreHighlightSettingsPage::save()
583 auto ruleManager = Client::highlightRuleManager();
584 if (ruleManager == nullptr)
587 auto clonedManager = HighlightRuleManager();
588 clonedManager.fromVariantMap(ruleManager->toVariantMap());
589 clonedManager.clear();
591 for (auto &rule : highlightList) {
592 clonedManager.addHighlightRule(rule.name, rule.isRegEx, rule.isCaseSensitive, rule.isEnabled, false,
593 rule.sender, rule.chanName);
596 for (auto &rule : ignoredList) {
597 clonedManager.addHighlightRule(rule.name, rule.isRegEx, rule.isCaseSensitive, rule.isEnabled, true,
598 rule.sender, rule.chanName);
601 auto highlightNickType = ui.highlightNicksComboBox->itemData(ui.highlightNicksComboBox->currentIndex()).value<int>();
603 clonedManager.setHighlightNick(HighlightRuleManager::HighlightNickType(highlightNickType));
604 clonedManager.setNicksCaseSensitive(ui.nicksCaseSensitive->isChecked());
606 ruleManager->requestUpdate(clonedManager.toVariantMap());
607 setChangedState(false);
611 void CoreHighlightSettingsPage::widgetHasChanged()
613 setChangedState(true);
616 void CoreHighlightSettingsPage::on_coreUnsupportedDetails_clicked()
618 // Re-use translations of "Local Highlights" as this is a word-for-word reference, forcing all
619 // spaces to non-breaking
620 const QString localHighlightsName = tr("Local Highlights").replace(" ", " ");
622 const QString remoteHighlightsMsgText =
623 QString("<p><b>%1</b></p></br><p>%2</p></br><p>%3</p>"
624 ).arg(tr("Your Quassel core is too old to support remote highlights"),
625 tr("You need a Quassel core v0.13.0 or newer to configure remote "
627 tr("You can still configure highlights for this device only in "
628 "<i>%1</i>.").arg(localHighlightsName));
630 QMessageBox::warning(this,
631 tr("Remote Highlights unsupported"),
632 remoteHighlightsMsgText);
635 void CoreHighlightSettingsPage::importRules() {
636 NotificationSettings notificationSettings;
638 const auto localHighlightList = notificationSettings.highlightList();
640 // Re-use translations of "Local Highlights" as this is a word-for-word reference, forcing all
641 // spaces to non-breaking
642 const QString localHighlightsName = tr("Local Highlights").replace(" ", " ");
644 if (localHighlightList.count() == 0) {
645 // No highlight rules exist to import, do nothing
646 QMessageBox::information(this,
647 tr("No local highlights"),
648 tr("No highlight rules in <i>%1</i>."
649 ).arg(localHighlightsName));
653 int ret = QMessageBox::question(this,
654 tr("Import local highlights?"),
655 tr("Import all highlight rules from <i>%1</i>?"
656 ).arg(localHighlightsName),
657 QMessageBox::Yes|QMessageBox::No,
660 if (ret == QMessageBox::No) {
661 // Only two options, Yes or No, just return if No
665 auto clonedManager = HighlightRuleManager();
666 clonedManager.fromVariantMap(Client::highlightRuleManager()->toVariantMap());
668 for (const auto &variant : notificationSettings.highlightList()) {
669 auto highlightRule = variant.toMap();
671 clonedManager.addHighlightRule(
672 highlightRule["Name"].toString(),
673 highlightRule["RegEx"].toBool(),
674 highlightRule["CS"].toBool(),
675 highlightRule["Enable"].toBool(),
678 highlightRule["Channel"].toString()
682 Client::highlightRuleManager()->requestUpdate(clonedManager.toVariantMap());
683 setChangedState(false);
686 // Give a heads-up that all succeeded
687 QMessageBox::information(this,
688 tr("Imported local highlights"),
689 tr("%1 highlight rules successfully imported."
690 ).arg(QString::number(localHighlightList.count())));
693 bool CoreHighlightSettingsPage::isSelectable() const {
694 return Client::isConnected();
695 // We check for Quassel::Feature::CoreSideHighlights when loading this page, allowing us to show
696 // a friendly error message.