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"), tr("Remote Highlights"), parent)
34 setupRuleTable(ui.highlightTable);
35 setupRuleTable(ui.ignoredTable);
37 ui.highlightNicksComboBox->addItem(tr("All Nicks from Identity"), QVariant(HighlightRuleManager::AllNicks));
38 ui.highlightNicksComboBox->addItem(tr("Current Nick"), QVariant(HighlightRuleManager::CurrentNick));
39 ui.highlightNicksComboBox->addItem(tr("None"), QVariant(HighlightRuleManager::NoNick));
41 coreConnectionStateChanged(Client::isConnected()); // need a core connection!
42 connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool)));
44 connect(ui.highlightAdd, SIGNAL(clicked(bool)), this, SLOT(addNewHighlightRow()));
45 connect(ui.highlightRemove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedHighlightRows()));
46 connect(ui.highlightImport, SIGNAL(clicked(bool)), this, SLOT(importRules()));
48 connect(ui.ignoredAdd, SIGNAL(clicked(bool)), this, SLOT(addNewIgnoredRow()));
49 connect(ui.ignoredRemove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedIgnoredRows()));
51 // TODO: search for a better signal (one that emits everytime a selection has been changed for one item)
52 connect(ui.highlightTable,
53 SIGNAL(itemClicked(QTableWidgetItem * )),
55 SLOT(selectHighlightRow(QTableWidgetItem * )));
56 connect(ui.ignoredTable,
57 SIGNAL(itemClicked(QTableWidgetItem * )),
59 SLOT(selectIgnoredRow(QTableWidgetItem * )));
61 // Update the "Case sensitive" checkbox
62 connect(ui.highlightNicksComboBox,
63 SIGNAL(currentIndexChanged(int)),
65 SLOT(highlightNicksChanged(int)));
67 connect(ui.highlightNicksComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
68 connect(ui.nicksCaseSensitive, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
70 connect(ui.highlightAdd, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
71 connect(ui.highlightRemove, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
73 connect(ui.ignoredAdd, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
74 connect(ui.ignoredRemove, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
76 connect(ui.highlightTable,
77 SIGNAL(itemChanged(QTableWidgetItem * )),
79 SLOT(highlightTableChanged(QTableWidgetItem * )));
81 connect(ui.ignoredTable,
82 SIGNAL(itemChanged(QTableWidgetItem * )),
84 SLOT(ignoredTableChanged(QTableWidgetItem * )));
86 connect(Client::instance(), SIGNAL(connected()), this, SLOT(clientConnected()));
89 ui.coreUnsupportedIcon->setPixmap(QIcon::fromTheme("dialog-warning").pixmap(16));
92 void CoreHighlightSettingsPage::coreConnectionStateChanged(bool state)
94 updateCoreSupportStatus(state);
103 void CoreHighlightSettingsPage::setupRuleTable(QTableWidget *table) const
105 table->verticalHeader()->hide();
106 table->setShowGrid(false);
108 table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn)->setToolTip(
109 tr("Enable/disable this rule"));
110 table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn)->setWhatsThis(
111 table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn)->toolTip());
113 table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn)->setToolTip(
114 tr("Phrase to match"));
115 table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn)->setWhatsThis(
116 table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn)->toolTip());
118 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setToolTip(
119 tr("<b>RegEx</b>: This option determines if the highlight rule, <i>Sender</i>, and "
120 "<i>Channel</i> should be interpreted as <b>regular expressions</b> or just as "
122 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setWhatsThis(
123 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->toolTip());
125 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setToolTip(
126 tr("<b>CS</b>: This option determines if the highlight rule, <i>Sender</i>, and "
127 "<i>Channel</i> should be interpreted <b>case sensitive</b>."));
128 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setWhatsThis(
129 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->toolTip());
131 table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn)->setToolTip(
132 tr("<p><b>Sender</b>: Semicolon separated list of <i>nick!ident@host</i> names, "
133 "leave blank to match any nickname.</p>"
134 "<p><i>Example:</i><br />"
135 "<i>Alice!*; Bob!*@example.com; Carol*!*; !Caroline!*</i><br />"
136 "would match on <i>Alice</i>, <i>Bob</i> with hostmask <i>example.com</i>, and "
137 "any nickname starting with <i>Carol</i> except for <i>Caroline</i><br />"
138 "<p>If only inverted names are specified, it will match anything except for "
139 "what's specified (implicit wildcard).</p>"
140 "<p><i>Example:</i><br />"
141 "<i>!Announce*!*; !Wheatley!aperture@*</i><br />"
142 "would match anything except for <i>Wheatley</i> with ident <i>aperture</i> or "
143 "any nickname starting with <i>Announce</i></p>"));
144 table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn)->setWhatsThis(
145 table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn)->toolTip());
147 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setToolTip(
148 tr("<p><b>Channel</b>: Semicolon separated list of channel names, leave blank to "
149 "match any name.</p>"
150 "<p><i>Example:</i><br />"
151 "<i>#quassel*; #foobar; !#quasseldroid</i><br />"
152 "would match on <i>#foobar</i> and any channel starting with <i>#quassel</i> "
153 "except for <i>#quasseldroid</i><br />"
154 "<p>If only inverted names are specified, it will match anything except for "
155 "what's specified (implicit wildcard).</p>"
156 "<p><i>Example:</i><br />"
157 "<i>!#quassel*; !#foobar</i><br />"
158 "would match anything except for <i>#foobar</i> or any channel starting with "
159 "<i>#quassel</i></p>"));
160 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setWhatsThis(
161 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->toolTip());
163 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
164 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents);
165 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::NameColumn, QHeaderView::Stretch);
166 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents);
167 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents);
168 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents);
170 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents);
171 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::NameColumn, QHeaderView::Stretch);
172 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents);
173 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents);
174 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents);
178 void CoreHighlightSettingsPage::updateCoreSupportStatus(bool state)
180 // Assume connected state as enforced by the settings page UI
181 if (!state || Client::isCoreFeatureEnabled(Quassel::Feature::CoreSideHighlights)) {
182 // Either disconnected or core supports highlights, enable highlight configuration and hide
183 // warning. Don't show the warning needlessly when disconnected.
184 ui.highlightsConfigWidget->setEnabled(true);
185 ui.coreUnsupportedWidget->setVisible(false);
187 // Core does not support highlights, show warning and disable highlight configuration
188 ui.highlightsConfigWidget->setEnabled(false);
189 ui.coreUnsupportedWidget->setVisible(true);
193 void CoreHighlightSettingsPage::clientConnected()
195 connect(Client::highlightRuleManager(), SIGNAL(updated()), SLOT(revert()));
198 void CoreHighlightSettingsPage::revert()
203 setChangedState(false);
207 bool CoreHighlightSettingsPage::hasDefaults() const
212 void CoreHighlightSettingsPage::defaults()
214 int highlightNickType = HighlightRuleManager::HighlightNickType::CurrentNick;
215 int defaultIndex = ui.highlightNicksComboBox->findData(QVariant(highlightNickType));
216 ui.highlightNicksComboBox->setCurrentIndex(defaultIndex);
217 ui.nicksCaseSensitive->setChecked(false);
218 emptyHighlightTable();
224 void CoreHighlightSettingsPage::addNewHighlightRow(bool enable, const QString &name, bool regex, bool cs,
225 const QString &sender, const QString &chanName, bool self)
227 ui.highlightTable->setRowCount(ui.highlightTable->rowCount() + 1);
229 auto *nameItem = new QTableWidgetItem(name);
231 auto *regexItem = new QTableWidgetItem("");
233 regexItem->setCheckState(Qt::Checked);
235 regexItem->setCheckState(Qt::Unchecked);
236 regexItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
238 auto *csItem = new QTableWidgetItem("");
240 csItem->setCheckState(Qt::Checked);
242 csItem->setCheckState(Qt::Unchecked);
243 csItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
245 auto *enableItem = new QTableWidgetItem("");
247 enableItem->setCheckState(Qt::Checked);
249 enableItem->setCheckState(Qt::Unchecked);
250 enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
252 auto *senderItem = new QTableWidgetItem(sender);
254 auto *chanNameItem = new QTableWidgetItem(chanName);
256 enableItem->setToolTip(tr("Enable/disable this rule"));
257 nameItem->setToolTip(tr("Phrase to match"));
258 regexItem->setToolTip(
259 tr("<b>RegEx</b>: This option determines if the highlight rule, <i>Sender</i>, and "
260 "<i>Channel</i> should be interpreted as <b>regular expressions</b> or just as "
263 tr("<b>CS</b>: This option determines if the highlight rule, <i>Sender</i>, and "
264 "<i>Channel</i> should be interpreted <b>case sensitive</b>."));
265 senderItem->setToolTip(
266 tr("<p><b>Sender</b>: Semicolon separated list of <i>nick!ident@host</i> names, "
267 "leave blank to match any nickname.</p>"
268 "<p><i>Example:</i><br />"
269 "<i>Alice!*; Bob!*@example.com; Carol*!*; !Caroline!*</i><br />"
270 "would match on <i>Alice</i>, <i>Bob</i> with hostmask <i>example.com</i>, and "
271 "any nickname starting with <i>Carol</i> except for <i>Caroline</i><br />"
272 "<p>If only inverted names are specified, it will match anything except for "
273 "what's specified (implicit wildcard).</p>"
274 "<p><i>Example:</i><br />"
275 "<i>!Announce*!*; !Wheatley!aperture@*</i><br />"
276 "would match anything except for <i>Wheatley</i> with ident <i>aperture</i> or "
277 "any nickname starting with <i>Announce</i></p>"));
278 chanNameItem->setToolTip(
279 tr("<p><b>Channel</b>: Semicolon separated list of channel names, leave blank to "
280 "match any name.</p>"
281 "<p><i>Example:</i><br />"
282 "<i>#quassel*; #foobar; !#quasseldroid</i><br />"
283 "would match on <i>#foobar</i> and any channel starting with <i>#quassel</i> "
284 "except for <i>#quasseldroid</i><br />"
285 "<p>If only inverted names are specified, it will match anything except for "
286 "what's specified (implicit wildcard).</p>"
287 "<p><i>Example:</i><br />"
288 "<i>!#quassel*; !#foobar</i><br />"
289 "would match anything except for <i>#foobar</i> or any channel starting with "
290 "<i>#quassel</i></p>"));
292 int lastRow = ui.highlightTable->rowCount() - 1;
293 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem);
294 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::RegExColumn, regexItem);
295 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::CsColumn, csItem);
296 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::EnableColumn, enableItem);
297 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::SenderColumn, senderItem);
298 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::ChanColumn, chanNameItem);
301 ui.highlightTable->setCurrentItem(nameItem);
303 highlightList << HighlightRuleManager::HighlightRule(name, regex, cs, enable, false, sender, chanName);
306 void CoreHighlightSettingsPage::addNewIgnoredRow(bool enable, const QString &name, bool regex, bool cs,
307 const QString &sender, const QString &chanName, bool self)
309 ui.ignoredTable->setRowCount(ui.ignoredTable->rowCount() + 1);
311 auto *nameItem = new QTableWidgetItem(name);
313 auto *regexItem = new QTableWidgetItem("");
315 regexItem->setCheckState(Qt::Checked);
317 regexItem->setCheckState(Qt::Unchecked);
318 regexItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
320 auto *csItem = new QTableWidgetItem("");
322 csItem->setCheckState(Qt::Checked);
324 csItem->setCheckState(Qt::Unchecked);
325 csItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
327 auto *enableItem = new QTableWidgetItem("");
329 enableItem->setCheckState(Qt::Checked);
331 enableItem->setCheckState(Qt::Unchecked);
332 enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
334 auto *chanNameItem = new QTableWidgetItem(chanName);
336 auto *senderItem = new QTableWidgetItem(sender);
338 enableItem->setToolTip(tr("Enable/disable this rule"));
339 nameItem->setToolTip(tr("Phrase to match"));
340 regexItem->setToolTip(
341 tr("<b>RegEx</b>: This option determines if the highlight rule should be "
342 "interpreted as a <b>regular expression</b> or just as a keyword."));
344 tr("<b>CS</b>: This option determines if the highlight rule should be interpreted "
345 "<b>case sensitive</b>."));
346 senderItem->setToolTip(
347 tr("<b>Sender</b>: This option specifies which sender nicknames match. Leave "
348 "blank to match any nickname."));
349 chanNameItem->setToolTip(
350 tr("<p><b>Channel</b>: Semicolon separated list of channel names.</p>"
351 "<p><i>Example:</i><br />"
352 "<i>#quassel*; #foobar; !#quasseldroid</i><br />"
353 "would match on #foobar and any channel starting with <i>#quassel</i> except "
354 "for <i>#quasseldroid</i><br />"
355 "<p>If only inverted names are specified, it will match anything except for "
356 "what's specified (implicit wildcard).</p>"
357 "<p><i>Example:</i><br />"
358 "<i>!#quassel*; !#foobar</i><br />"
359 "would match anything except for #foobar or any channel starting with "
360 "<i>#quassel</i></p>"));
362 int lastRow = ui.ignoredTable->rowCount() - 1;
363 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem);
364 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::RegExColumn, regexItem);
365 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::CsColumn, csItem);
366 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::EnableColumn, enableItem);
367 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::SenderColumn, senderItem);
368 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::ChanColumn, chanNameItem);
371 ui.ignoredTable->setCurrentItem(nameItem);
373 ignoredList << HighlightRuleManager::HighlightRule(name, regex, cs, enable, true, sender, chanName);
376 void CoreHighlightSettingsPage::removeSelectedHighlightRows()
378 QList<int> selectedRows;
379 QList<QTableWidgetItem *> selectedItemList = ui.highlightTable->selectedItems();
380 for (auto selectedItem : selectedItemList) {
381 selectedRows.append(selectedItem->row());
383 qSort(selectedRows.begin(), selectedRows.end(), qGreater<int>());
385 for (auto row : selectedRows) {
386 if (row != lastRow) {
387 ui.highlightTable->removeRow(row);
388 highlightList.removeAt(row);
394 void CoreHighlightSettingsPage::removeSelectedIgnoredRows()
396 QList<int> selectedRows;
397 QList<QTableWidgetItem *> selectedItemList = ui.ignoredTable->selectedItems();
398 for (auto selectedItem : selectedItemList) {
399 selectedRows.append(selectedItem->row());
401 qSort(selectedRows.begin(), selectedRows.end(), qGreater<int>());
403 for (auto row : selectedRows) {
404 if (row != lastRow) {
405 ui.ignoredTable->removeRow(row);
406 ignoredList.removeAt(row);
412 void CoreHighlightSettingsPage::highlightNicksChanged(const int index) {
413 // Only allow toggling "Case sensitive" when a nickname will be highlighted
414 auto highlightNickType = ui.highlightNicksComboBox->itemData(index).value<int>();
415 ui.nicksCaseSensitive->setEnabled(highlightNickType != HighlightRuleManager::NoNick);
418 void CoreHighlightSettingsPage::selectHighlightRow(QTableWidgetItem *item)
420 int row = item->row();
421 bool selected = item->isSelected();
423 ->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, CoreHighlightSettingsPage::ColumnCount - 1),
427 void CoreHighlightSettingsPage::selectIgnoredRow(QTableWidgetItem *item)
429 int row = item->row();
430 bool selected = item->isSelected();
432 ->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, CoreHighlightSettingsPage::ColumnCount - 1),
436 void CoreHighlightSettingsPage::emptyHighlightTable()
438 // ui.highlight and highlightList should have the same size, but just to make sure.
439 if (ui.highlightTable->rowCount() != highlightList.size()) {
440 qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!";
442 while (ui.highlightTable->rowCount()) {
443 ui.highlightTable->removeRow(0);
445 highlightList.clear();
448 void CoreHighlightSettingsPage::emptyIgnoredTable()
450 // ui.highlight and highlightList should have the same size, but just to make sure.
451 if (ui.ignoredTable->rowCount() != ignoredList.size()) {
452 qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!";
454 while (ui.ignoredTable->rowCount()) {
455 ui.ignoredTable->removeRow(0);
460 void CoreHighlightSettingsPage::highlightTableChanged(QTableWidgetItem *item)
462 if (item->row() + 1 > highlightList.size())
465 auto highlightRule = highlightList.value(item->row());
468 switch (item->column()) {
469 case CoreHighlightSettingsPage::EnableColumn:
470 highlightRule.isEnabled = (item->checkState() == Qt::Checked);
472 case CoreHighlightSettingsPage::NameColumn:
473 if (item->text() == "")
474 item->setText(tr("this shouldn't be empty"));
475 highlightRule.name = item->text();
477 case CoreHighlightSettingsPage::RegExColumn:
478 highlightRule.isRegEx = (item->checkState() == Qt::Checked);
480 case CoreHighlightSettingsPage::CsColumn:
481 highlightRule.isCaseSensitive = (item->checkState() == Qt::Checked);
483 case CoreHighlightSettingsPage::SenderColumn:
484 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
486 highlightRule.sender = item->text();
488 case CoreHighlightSettingsPage::ChanColumn:
489 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
491 highlightRule.chanName = item->text();
494 highlightList[item->row()] = highlightRule;
495 emit widgetHasChanged();
498 void CoreHighlightSettingsPage::ignoredTableChanged(QTableWidgetItem *item)
500 if (item->row() + 1 > ignoredList.size())
503 auto ignoredRule = ignoredList.value(item->row());
506 switch (item->column()) {
507 case CoreHighlightSettingsPage::EnableColumn:
508 ignoredRule.isEnabled = (item->checkState() == Qt::Checked);
510 case CoreHighlightSettingsPage::NameColumn:
511 if (item->text() == "")
512 item->setText(tr("this shouldn't be empty"));
513 ignoredRule.name = item->text();
515 case CoreHighlightSettingsPage::RegExColumn:
516 ignoredRule.isRegEx = (item->checkState() == Qt::Checked);
518 case CoreHighlightSettingsPage::CsColumn:
519 ignoredRule.isCaseSensitive = (item->checkState() == Qt::Checked);
521 case CoreHighlightSettingsPage::SenderColumn:
522 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
524 ignoredRule.sender = item->text();
526 case CoreHighlightSettingsPage::ChanColumn:
527 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
529 ignoredRule.chanName = item->text();
532 ignoredList[item->row()] = ignoredRule;
533 emit widgetHasChanged();
536 void CoreHighlightSettingsPage::load()
538 emptyHighlightTable();
541 auto ruleManager = Client::highlightRuleManager();
543 for (auto &rule : ruleManager->highlightRuleList()) {
544 if (rule.isInverse) {
545 addNewIgnoredRow(rule.isEnabled,
548 rule.isCaseSensitive,
553 addNewHighlightRow(rule.isEnabled, rule.name, rule.isRegEx, rule.isCaseSensitive, rule.sender,
558 int highlightNickType = ruleManager->highlightNick();
559 ui.highlightNicksComboBox->setCurrentIndex(ui.highlightNicksComboBox->findData(QVariant(highlightNickType)));
560 // Trigger the initial update of nicksCaseSensitive being enabled or not
561 highlightNicksChanged(ui.highlightNicksComboBox->currentIndex());
562 ui.nicksCaseSensitive->setChecked(ruleManager->nicksCaseSensitive());
564 setChangedState(false);
571 void CoreHighlightSettingsPage::save()
579 auto ruleManager = Client::highlightRuleManager();
580 if (ruleManager == nullptr)
583 auto clonedManager = HighlightRuleManager();
584 clonedManager.fromVariantMap(ruleManager->toVariantMap());
585 clonedManager.clear();
587 for (auto &rule : highlightList) {
588 clonedManager.addHighlightRule(rule.name, rule.isRegEx, rule.isCaseSensitive, rule.isEnabled, false,
589 rule.sender, rule.chanName);
592 for (auto &rule : ignoredList) {
593 clonedManager.addHighlightRule(rule.name, rule.isRegEx, rule.isCaseSensitive, rule.isEnabled, true,
594 rule.sender, rule.chanName);
597 auto highlightNickType = ui.highlightNicksComboBox->itemData(ui.highlightNicksComboBox->currentIndex()).value<int>();
599 clonedManager.setHighlightNick(HighlightRuleManager::HighlightNickType(highlightNickType));
600 clonedManager.setNicksCaseSensitive(ui.nicksCaseSensitive->isChecked());
602 ruleManager->requestUpdate(clonedManager.toVariantMap());
603 setChangedState(false);
607 void CoreHighlightSettingsPage::widgetHasChanged()
609 setChangedState(true);
612 void CoreHighlightSettingsPage::on_coreUnsupportedDetails_clicked()
614 // Re-use translations of "Local Highlights" as this is a word-for-word reference, forcing all
615 // spaces to non-breaking
616 const QString localHighlightsName = tr("Local Highlights").replace(" ", " ");
618 const QString remoteHighlightsMsgText =
619 QString("<p><b>%1</b></p></br><p>%2</p></br><p>%3</p>"
620 ).arg(tr("Your Quassel core is too old to support remote highlights"),
621 tr("You need a Quassel core v0.13.0 or newer to configure remote "
623 tr("You can still configure highlights for this device only in "
624 "<i>%1</i>.").arg(localHighlightsName));
626 QMessageBox::warning(this,
627 tr("Remote Highlights unsupported"),
628 remoteHighlightsMsgText);
631 void CoreHighlightSettingsPage::importRules() {
632 NotificationSettings notificationSettings;
634 const auto localHighlightList = notificationSettings.highlightList();
636 // Re-use translations of "Local Highlights" as this is a word-for-word reference, forcing all
637 // spaces to non-breaking
638 const QString localHighlightsName = tr("Local Highlights").replace(" ", " ");
640 if (localHighlightList.count() == 0) {
641 // No highlight rules exist to import, do nothing
642 QMessageBox::information(this,
643 tr("No local highlights"),
644 tr("No highlight rules in <i>%1</i>."
645 ).arg(localHighlightsName));
649 int ret = QMessageBox::question(this,
650 tr("Import local highlights?"),
651 tr("Import all highlight rules from <i>%1</i>?"
652 ).arg(localHighlightsName),
653 QMessageBox::Yes|QMessageBox::No,
656 if (ret == QMessageBox::No) {
657 // Only two options, Yes or No, just return if No
661 auto clonedManager = HighlightRuleManager();
662 clonedManager.fromVariantMap(Client::highlightRuleManager()->toVariantMap());
664 for (const auto &variant : notificationSettings.highlightList()) {
665 auto highlightRule = variant.toMap();
667 clonedManager.addHighlightRule(
668 highlightRule["Name"].toString(),
669 highlightRule["RegEx"].toBool(),
670 highlightRule["CS"].toBool(),
671 highlightRule["Enable"].toBool(),
674 highlightRule["Channel"].toString()
678 Client::highlightRuleManager()->requestUpdate(clonedManager.toVariantMap());
679 setChangedState(false);
682 // Give a heads-up that all succeeded
683 QMessageBox::information(this,
684 tr("Imported local highlights"),
685 tr("%1 highlight rules successfully imported."
686 ).arg(QString::number(localHighlightList.count())));
689 bool CoreHighlightSettingsPage::isSelectable() const {
690 return Client::isConnected();
691 // We check for Quassel::Feature::CoreSideHighlights when loading this page, allowing us to show
692 // a friendly error message.