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"
30 CoreHighlightSettingsPage::CoreHighlightSettingsPage(QWidget *parent)
31 : SettingsPage(tr("Interface"),
32 // In Monolithic mode, local highlights are replaced by remote highlights
33 Quassel::runMode() == Quassel::Monolithic ?
34 tr("Highlights") : tr("Remote Highlights"),
39 setupRuleTable(ui.highlightTable);
40 setupRuleTable(ui.ignoredTable);
42 ui.highlightNicksComboBox->addItem(tr("All Nicks from Identity"), QVariant(HighlightRuleManager::AllNicks));
43 ui.highlightNicksComboBox->addItem(tr("Current Nick"), QVariant(HighlightRuleManager::CurrentNick));
44 ui.highlightNicksComboBox->addItem(tr("None"), QVariant(HighlightRuleManager::NoNick));
46 coreConnectionStateChanged(Client::isConnected()); // need a core connection!
47 connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool)));
49 connect(ui.highlightAdd, SIGNAL(clicked(bool)), this, SLOT(addNewHighlightRow()));
50 connect(ui.highlightRemove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedHighlightRows()));
51 connect(ui.highlightImport, SIGNAL(clicked(bool)), this, SLOT(importRules()));
53 connect(ui.ignoredAdd, SIGNAL(clicked(bool)), this, SLOT(addNewIgnoredRow()));
54 connect(ui.ignoredRemove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedIgnoredRows()));
56 // TODO: search for a better signal (one that emits everytime a selection has been changed for one item)
57 connect(ui.highlightTable,
58 SIGNAL(itemClicked(QTableWidgetItem * )),
60 SLOT(selectHighlightRow(QTableWidgetItem * )));
61 connect(ui.ignoredTable,
62 SIGNAL(itemClicked(QTableWidgetItem * )),
64 SLOT(selectIgnoredRow(QTableWidgetItem * )));
66 // Update the "Case sensitive" checkbox
67 connect(ui.highlightNicksComboBox,
68 SIGNAL(currentIndexChanged(int)),
70 SLOT(highlightNicksChanged(int)));
72 connect(ui.highlightNicksComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
73 connect(ui.nicksCaseSensitive, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
75 connect(ui.highlightAdd, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
76 connect(ui.highlightRemove, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
78 connect(ui.ignoredAdd, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
79 connect(ui.ignoredRemove, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
81 connect(ui.highlightTable,
82 SIGNAL(itemChanged(QTableWidgetItem * )),
84 SLOT(highlightTableChanged(QTableWidgetItem * )));
86 connect(ui.ignoredTable,
87 SIGNAL(itemChanged(QTableWidgetItem * )),
89 SLOT(ignoredTableChanged(QTableWidgetItem * )));
91 connect(Client::instance(), SIGNAL(connected()), this, SLOT(clientConnected()));
94 ui.coreUnsupportedIcon->setPixmap(icon::get("dialog-warning").pixmap(16));
96 // Set up client/monolithic remote highlights information
97 if (Quassel::runMode() == Quassel::Monolithic) {
98 // We're running in Monolithic mode, local highlights are considered legacy
99 ui.highlightImport->setText(tr("Import Legacy"));
100 ui.highlightImport->setToolTip(tr("Import highlight rules configured in <i>%1</i>.")
101 .arg(tr("Legacy Highlights").replace(" ", " ")));
102 // Re-use translations of "Legacy Highlights" as this is a word-for-word reference, forcing
103 // all spaces to be non-breaking
105 // We're running in client/split mode, local highlights are distinguished from remote
106 ui.highlightImport->setText(tr("Import Local"));
107 ui.highlightImport->setToolTip(tr("Import highlight rules configured in <i>%1</i>.")
108 .arg(tr("Local Highlights").replace(" ", " ")));
109 // Re-use translations of "Local Highlights" as this is a word-for-word reference, forcing
110 // all spaces to be non-breaking
115 void CoreHighlightSettingsPage::coreConnectionStateChanged(bool state)
117 updateCoreSupportStatus(state);
127 void CoreHighlightSettingsPage::setupRuleTable(QTableWidget *table) const
129 table->verticalHeader()->hide();
130 table->setShowGrid(false);
132 setupTableTooltips(table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn),
133 table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn),
134 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn),
135 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn),
136 table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn),
137 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn));
139 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents);
140 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::NameColumn, QHeaderView::Stretch);
141 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents);
142 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents);
143 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::SenderColumn, QHeaderView::ResizeToContents);
144 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents);
148 QString CoreHighlightSettingsPage::getTableTooltip(column tableColumn) const
150 switch (tableColumn) {
151 case CoreHighlightSettingsPage::EnableColumn:
152 return tr("Enable/disable this rule");
154 case CoreHighlightSettingsPage::NameColumn:
155 return tr("Phrase to match, leave blank to match any message");
157 case CoreHighlightSettingsPage::RegExColumn:
158 return tr("<b>RegEx</b>: This option determines if the highlight rule, <i>Sender</i>, and "
159 "<i>Channel</i> should be interpreted as <b>regular expressions</b> or just as "
162 case CoreHighlightSettingsPage::CsColumn:
163 return tr("<b>CS</b>: This option determines if the highlight rule, <i>Sender</i>, and "
164 "<i>Channel</i> should be interpreted <b>case sensitive</b>.");
166 case CoreHighlightSettingsPage::SenderColumn:
167 return tr("<p><b>Sender</b>: Semicolon separated list of <i>nick!ident@host</i> names, "
168 "leave blank to match any nickname.</p>"
169 "<p><i>Example:</i><br />"
170 "<i>Alice!*; Bob!*@example.com; Carol*!*; !Caroline!*</i><br />"
171 "would match on <i>Alice</i>, <i>Bob</i> with hostmask <i>example.com</i>, and "
172 "any nickname starting with <i>Carol</i> except for <i>Caroline</i><br />"
173 "<p>If only inverted names are specified, it will match anything except for "
174 "what's specified (implicit wildcard).</p>"
175 "<p><i>Example:</i><br />"
176 "<i>!Announce*!*; !Wheatley!aperture@*</i><br />"
177 "would match anything except for <i>Wheatley</i> with ident <i>aperture</i> or "
178 "any nickname starting with <i>Announce</i></p>");
180 case CoreHighlightSettingsPage::ChanColumn:
181 return tr("<p><b>Channel</b>: Semicolon separated list of channel/query names, leave blank "
182 "to match any name.</p>"
183 "<p><i>Example:</i><br />"
184 "<i>#quassel*; #foobar; !#quasseldroid</i><br />"
185 "would match on <i>#foobar</i> and any channel starting with <i>#quassel</i> "
186 "except for <i>#quasseldroid</i><br />"
187 "<p>If only inverted names are specified, it will match anything except for "
188 "what's specified (implicit wildcard).</p>"
189 "<p><i>Example:</i><br />"
190 "<i>!#quassel*; !#foobar</i><br />"
191 "would match anything except for <i>#foobar</i> or any channel starting with "
192 "<i>#quassel</i></p>");
195 // This shouldn't happen
196 return "Invalid column type in CoreHighlightSettingsPage::getTableTooltip()";
201 void CoreHighlightSettingsPage::setupTableTooltips(QWidget *enableWidget, QWidget *nameWidget,
202 QWidget *regExWidget, QWidget *csWidget,
203 QWidget *senderWidget, QWidget *chanWidget) const
205 // Make sure everything's valid
206 Q_ASSERT(enableWidget);
207 Q_ASSERT(nameWidget);
208 Q_ASSERT(regExWidget);
210 Q_ASSERT(senderWidget);
211 Q_ASSERT(chanWidget);
213 // Set tooltips and "What's this?" prompts
215 enableWidget->setToolTip(getTableTooltip(CoreHighlightSettingsPage::EnableColumn));
216 enableWidget->setWhatsThis(enableWidget->toolTip());
219 nameWidget->setToolTip(getTableTooltip(CoreHighlightSettingsPage::NameColumn));
220 nameWidget->setWhatsThis(nameWidget->toolTip());
223 regExWidget->setToolTip(getTableTooltip(CoreHighlightSettingsPage::RegExColumn));
224 regExWidget->setWhatsThis(regExWidget->toolTip());
227 csWidget->setToolTip(getTableTooltip(CoreHighlightSettingsPage::CsColumn));
228 csWidget->setWhatsThis(csWidget->toolTip());
231 senderWidget->setToolTip(getTableTooltip(CoreHighlightSettingsPage::SenderColumn));
232 senderWidget->setWhatsThis(senderWidget->toolTip());
234 // Channel/buffer name
235 chanWidget->setToolTip(getTableTooltip(CoreHighlightSettingsPage::ChanColumn));
236 chanWidget->setWhatsThis(chanWidget->toolTip());
240 void CoreHighlightSettingsPage::setupTableTooltips(QTableWidgetItem *enableWidget,
241 QTableWidgetItem *nameWidget,
242 QTableWidgetItem *regExWidget,
243 QTableWidgetItem *csWidget,
244 QTableWidgetItem *senderWidget,
245 QTableWidgetItem *chanWidget) const
247 // Make sure everything's valid
248 Q_ASSERT(enableWidget);
249 Q_ASSERT(nameWidget);
250 Q_ASSERT(regExWidget);
252 Q_ASSERT(senderWidget);
253 Q_ASSERT(chanWidget);
255 // Set tooltips and "What's this?" prompts
257 enableWidget->setToolTip(getTableTooltip(CoreHighlightSettingsPage::EnableColumn));
258 enableWidget->setWhatsThis(enableWidget->toolTip());
261 nameWidget->setToolTip(getTableTooltip(CoreHighlightSettingsPage::NameColumn));
262 nameWidget->setWhatsThis(nameWidget->toolTip());
265 regExWidget->setToolTip(getTableTooltip(CoreHighlightSettingsPage::RegExColumn));
266 regExWidget->setWhatsThis(regExWidget->toolTip());
269 csWidget->setToolTip(getTableTooltip(CoreHighlightSettingsPage::CsColumn));
270 csWidget->setWhatsThis(csWidget->toolTip());
273 senderWidget->setToolTip(getTableTooltip(CoreHighlightSettingsPage::SenderColumn));
274 senderWidget->setWhatsThis(senderWidget->toolTip());
276 // Channel/buffer name
277 chanWidget->setToolTip(getTableTooltip(CoreHighlightSettingsPage::ChanColumn));
278 chanWidget->setWhatsThis(chanWidget->toolTip());
282 void CoreHighlightSettingsPage::updateCoreSupportStatus(bool state)
284 // Assume connected state as enforced by the settings page UI
285 if (!state || Client::isCoreFeatureEnabled(Quassel::Feature::CoreSideHighlights)) {
286 // Either disconnected or core supports highlights, enable highlight configuration and hide
287 // warning. Don't show the warning needlessly when disconnected.
288 ui.highlightsConfigWidget->setEnabled(true);
289 ui.coreUnsupportedWidget->setVisible(false);
291 // Core does not support highlights, show warning and disable highlight configuration
292 ui.highlightsConfigWidget->setEnabled(false);
293 ui.coreUnsupportedWidget->setVisible(true);
298 void CoreHighlightSettingsPage::clientConnected()
300 connect(Client::highlightRuleManager(), SIGNAL(updated()), SLOT(revert()));
304 void CoreHighlightSettingsPage::revert()
309 setChangedState(false);
314 bool CoreHighlightSettingsPage::hasDefaults() const
320 void CoreHighlightSettingsPage::defaults()
322 int highlightNickType = HighlightRuleManager::HighlightNickType::CurrentNick;
323 int defaultIndex = ui.highlightNicksComboBox->findData(QVariant(highlightNickType));
324 ui.highlightNicksComboBox->setCurrentIndex(defaultIndex);
325 ui.nicksCaseSensitive->setChecked(false);
326 emptyHighlightTable();
333 void CoreHighlightSettingsPage::addNewHighlightRow(bool enable, int id, const QString &name, bool regex, bool cs,
334 const QString &sender, const QString &chanName, bool self)
336 ui.highlightTable->setRowCount(ui.highlightTable->rowCount() + 1);
342 auto *nameItem = new QTableWidgetItem(name);
344 auto *regexItem = new QTableWidgetItem("");
346 regexItem->setCheckState(Qt::Checked);
348 regexItem->setCheckState(Qt::Unchecked);
349 regexItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
351 auto *csItem = new QTableWidgetItem("");
353 csItem->setCheckState(Qt::Checked);
355 csItem->setCheckState(Qt::Unchecked);
356 csItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
358 auto *enableItem = new QTableWidgetItem("");
360 enableItem->setCheckState(Qt::Checked);
362 enableItem->setCheckState(Qt::Unchecked);
363 enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
365 auto *senderItem = new QTableWidgetItem(sender);
367 auto *chanNameItem = new QTableWidgetItem(chanName);
369 setupTableTooltips(enableItem, nameItem, regexItem, csItem, senderItem, chanNameItem);
371 int lastRow = ui.highlightTable->rowCount() - 1;
372 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem);
373 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::RegExColumn, regexItem);
374 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::CsColumn, csItem);
375 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::EnableColumn, enableItem);
376 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::SenderColumn, senderItem);
377 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::ChanColumn, chanNameItem);
380 ui.highlightTable->setCurrentItem(nameItem);
382 highlightList << HighlightRuleManager::HighlightRule(id, name, regex, cs, enable, false, sender, chanName);
386 void CoreHighlightSettingsPage::addNewIgnoredRow(bool enable, int id, const QString &name, bool regex, bool cs,
387 const QString &sender, const QString &chanName, bool self)
389 ui.ignoredTable->setRowCount(ui.ignoredTable->rowCount() + 1);
395 auto *nameItem = new QTableWidgetItem(name);
397 auto *regexItem = new QTableWidgetItem("");
399 regexItem->setCheckState(Qt::Checked);
401 regexItem->setCheckState(Qt::Unchecked);
402 regexItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
404 auto *csItem = new QTableWidgetItem("");
406 csItem->setCheckState(Qt::Checked);
408 csItem->setCheckState(Qt::Unchecked);
409 csItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
411 auto *enableItem = new QTableWidgetItem("");
413 enableItem->setCheckState(Qt::Checked);
415 enableItem->setCheckState(Qt::Unchecked);
416 enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
418 auto *chanNameItem = new QTableWidgetItem(chanName);
420 auto *senderItem = new QTableWidgetItem(sender);
422 setupTableTooltips(enableItem, nameItem, regexItem, csItem, senderItem, chanNameItem);
424 int lastRow = ui.ignoredTable->rowCount() - 1;
425 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem);
426 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::RegExColumn, regexItem);
427 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::CsColumn, csItem);
428 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::EnableColumn, enableItem);
429 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::SenderColumn, senderItem);
430 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::ChanColumn, chanNameItem);
433 ui.ignoredTable->setCurrentItem(nameItem);
435 ignoredList << HighlightRuleManager::HighlightRule(id, name, regex, cs, enable, true, sender, chanName);
439 void CoreHighlightSettingsPage::removeSelectedHighlightRows()
441 QList<int> selectedRows;
442 QList<QTableWidgetItem *> selectedItemList = ui.highlightTable->selectedItems();
443 for (auto selectedItem : selectedItemList) {
444 selectedRows.append(selectedItem->row());
446 qSort(selectedRows.begin(), selectedRows.end(), qGreater<int>());
448 for (auto row : selectedRows) {
449 if (row != lastRow) {
450 ui.highlightTable->removeRow(row);
451 highlightList.removeAt(row);
458 void CoreHighlightSettingsPage::removeSelectedIgnoredRows()
460 QList<int> selectedRows;
461 QList<QTableWidgetItem *> selectedItemList = ui.ignoredTable->selectedItems();
462 for (auto selectedItem : selectedItemList) {
463 selectedRows.append(selectedItem->row());
465 qSort(selectedRows.begin(), selectedRows.end(), qGreater<int>());
467 for (auto row : selectedRows) {
468 if (row != lastRow) {
469 ui.ignoredTable->removeRow(row);
470 ignoredList.removeAt(row);
477 void CoreHighlightSettingsPage::highlightNicksChanged(const int index)
479 // Only allow toggling "Case sensitive" when a nickname will be highlighted
480 auto highlightNickType = ui.highlightNicksComboBox->itemData(index).value<int>();
481 ui.nicksCaseSensitive->setEnabled(highlightNickType != HighlightRuleManager::NoNick);
485 void CoreHighlightSettingsPage::selectHighlightRow(QTableWidgetItem *item)
487 int row = item->row();
488 bool selected = item->isSelected();
490 ->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, CoreHighlightSettingsPage::ColumnCount - 1),
495 void CoreHighlightSettingsPage::selectIgnoredRow(QTableWidgetItem *item)
497 int row = item->row();
498 bool selected = item->isSelected();
500 ->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, CoreHighlightSettingsPage::ColumnCount - 1),
505 void CoreHighlightSettingsPage::emptyHighlightTable()
507 // ui.highlight and highlightList should have the same size, but just to make sure.
508 if (ui.highlightTable->rowCount() != highlightList.size()) {
509 qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!";
511 while (ui.highlightTable->rowCount()) {
512 ui.highlightTable->removeRow(0);
514 highlightList.clear();
518 void CoreHighlightSettingsPage::emptyIgnoredTable()
520 // ui.highlight and highlightList should have the same size, but just to make sure.
521 if (ui.ignoredTable->rowCount() != ignoredList.size()) {
522 qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!";
524 while (ui.ignoredTable->rowCount()) {
525 ui.ignoredTable->removeRow(0);
531 void CoreHighlightSettingsPage::highlightTableChanged(QTableWidgetItem *item)
533 if (item->row() + 1 > highlightList.size())
536 auto highlightRule = highlightList.value(item->row());
539 switch (item->column()) {
540 case CoreHighlightSettingsPage::EnableColumn:
541 highlightRule.setIsEnabled(item->checkState() == Qt::Checked);
543 case CoreHighlightSettingsPage::NameColumn:
544 highlightRule.setContents(item->text());
546 case CoreHighlightSettingsPage::RegExColumn:
547 highlightRule.setIsRegEx(item->checkState() == Qt::Checked);
549 case CoreHighlightSettingsPage::CsColumn:
550 highlightRule.setIsCaseSensitive(item->checkState() == Qt::Checked);
552 case CoreHighlightSettingsPage::SenderColumn:
553 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
555 highlightRule.setSender(item->text());
557 case CoreHighlightSettingsPage::ChanColumn:
558 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
560 highlightRule.setChanName(item->text());
563 highlightList[item->row()] = highlightRule;
564 emit widgetHasChanged();
568 void CoreHighlightSettingsPage::ignoredTableChanged(QTableWidgetItem *item)
570 if (item->row() + 1 > ignoredList.size())
573 auto ignoredRule = ignoredList.value(item->row());
576 switch (item->column()) {
577 case CoreHighlightSettingsPage::EnableColumn:
578 ignoredRule.setIsEnabled(item->checkState() == Qt::Checked);
580 case CoreHighlightSettingsPage::NameColumn:
581 ignoredRule.setContents(item->text());
583 case CoreHighlightSettingsPage::RegExColumn:
584 ignoredRule.setIsRegEx(item->checkState() == Qt::Checked);
586 case CoreHighlightSettingsPage::CsColumn:
587 ignoredRule.setIsCaseSensitive(item->checkState() == Qt::Checked);
589 case CoreHighlightSettingsPage::SenderColumn:
590 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
592 ignoredRule.setSender(item->text());
594 case CoreHighlightSettingsPage::ChanColumn:
595 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
597 ignoredRule.setChanName(item->text());
600 ignoredList[item->row()] = ignoredRule;
601 emit widgetHasChanged();
605 void CoreHighlightSettingsPage::load()
607 emptyHighlightTable();
610 auto ruleManager = Client::highlightRuleManager();
612 for (auto &rule : ruleManager->highlightRuleList()) {
613 if (rule.isInverse()) {
614 addNewIgnoredRow(rule.isEnabled(), rule.id(), rule.contents(), rule.isRegEx(),
615 rule.isCaseSensitive(), rule.sender(), rule.chanName());
618 addNewHighlightRow(rule.isEnabled(), rule.id(), rule.contents(), rule.isRegEx(),
619 rule.isCaseSensitive(), rule.sender(), rule.chanName());
623 int highlightNickType = ruleManager->highlightNick();
624 ui.highlightNicksComboBox->setCurrentIndex(ui.highlightNicksComboBox->findData(QVariant(highlightNickType)));
625 // Trigger the initial update of nicksCaseSensitive being enabled or not
626 highlightNicksChanged(ui.highlightNicksComboBox->currentIndex());
627 ui.nicksCaseSensitive->setChecked(ruleManager->nicksCaseSensitive());
629 setChangedState(false);
637 void CoreHighlightSettingsPage::save()
645 auto ruleManager = Client::highlightRuleManager();
646 if (ruleManager == nullptr)
649 auto clonedManager = HighlightRuleManager();
650 clonedManager.fromVariantMap(ruleManager->toVariantMap());
651 clonedManager.clear();
653 for (auto &rule : highlightList) {
654 clonedManager.addHighlightRule(rule.id(), rule.contents(), rule.isRegEx(),
655 rule.isCaseSensitive(), rule.isEnabled(), false,
656 rule.sender(), rule.chanName());
659 for (auto &rule : ignoredList) {
660 clonedManager.addHighlightRule(rule.id(), rule.contents(), rule.isRegEx(),
661 rule.isCaseSensitive (), rule.isEnabled(), true,
662 rule.sender(), rule.chanName());
665 auto highlightNickType = ui.highlightNicksComboBox->itemData(ui.highlightNicksComboBox->currentIndex()).value<int>();
667 clonedManager.setHighlightNick(HighlightRuleManager::HighlightNickType(highlightNickType));
668 clonedManager.setNicksCaseSensitive(ui.nicksCaseSensitive->isChecked());
670 ruleManager->requestUpdate(clonedManager.toVariantMap());
671 setChangedState(false);
676 int CoreHighlightSettingsPage::nextId()
679 for (int i = 0; i < highlightList.count(); i++) {
680 int id = highlightList[i].id();
685 for (int i = 0; i < ignoredList.count(); i++) {
686 int id = ignoredList[i].id();
695 void CoreHighlightSettingsPage::widgetHasChanged()
697 setChangedState(true);
701 void CoreHighlightSettingsPage::on_coreUnsupportedDetails_clicked()
703 // Re-use translations of "Local Highlights" as this is a word-for-word reference, forcing all
704 // spaces to non-breaking
705 const QString localHighlightsName = tr("Local Highlights").replace(" ", " ");
707 const QString remoteHighlightsMsgText =
708 QString("<p><b>%1</b></p></br><p>%2</p></br><p>%3</p>"
709 ).arg(tr("Your Quassel core is too old to support remote highlights"),
710 tr("You need a Quassel core v0.13.0 or newer to configure remote "
712 tr("You can still configure highlights for this device only in "
713 "<i>%1</i>.").arg(localHighlightsName));
715 QMessageBox::warning(this,
716 tr("Remote Highlights unsupported"),
717 remoteHighlightsMsgText);
721 void CoreHighlightSettingsPage::importRules()
723 NotificationSettings notificationSettings;
725 const auto localHighlightList = notificationSettings.highlightList();
727 // Re-use translations of "Legacy/Local Highlights" as this is a word-for-word reference,
728 // forcing all spaces to non-breaking
729 QString localHighlightsName;
730 if (Quassel::runMode() == Quassel::Monolithic) {
731 localHighlightsName = tr("Legacy Highlights").replace(" ", " ");
733 localHighlightsName = tr("Local Highlights").replace(" ", " ");
736 if (localHighlightList.count() == 0) {
737 // No highlight rules exist to import, do nothing
738 QMessageBox::information(this,
739 tr("No highlights to import"),
740 tr("No highlight rules in <i>%1</i>."
741 ).arg(localHighlightsName));
745 int ret = QMessageBox::question(this,
746 tr("Import highlights?"),
747 tr("Import all highlight rules from <i>%1</i>?"
748 ).arg(localHighlightsName),
749 QMessageBox::Yes|QMessageBox::No,
752 if (ret != QMessageBox::Yes) {
753 // Only two options, Yes or No, return if not Yes
758 // Save existing changes first to avoid overwriting them
762 auto clonedManager = HighlightRuleManager();
763 clonedManager.fromVariantMap(Client::highlightRuleManager()->toVariantMap());
765 for (const auto &variant : notificationSettings.highlightList()) {
766 auto highlightRule = variant.toMap();
768 clonedManager.addHighlightRule(
769 clonedManager.nextId(),
770 highlightRule["Name"].toString(),
771 highlightRule["RegEx"].toBool(),
772 highlightRule["CS"].toBool(),
773 highlightRule["Enable"].toBool(),
776 highlightRule["Channel"].toString()
780 Client::highlightRuleManager()->requestUpdate(clonedManager.toVariantMap());
781 setChangedState(false);
784 // Give a heads-up that all succeeded
785 QMessageBox::information(this,
786 tr("Imported highlights"),
787 tr("%1 highlight rules successfully imported."
788 ).arg(QString::number(localHighlightList.count())));
792 bool CoreHighlightSettingsPage::isSelectable() const
794 return Client::isConnected();
795 // We check for Quassel::Feature::CoreSideHighlights when loading this page, allowing us to show
796 // a friendly error message.