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
114 void CoreHighlightSettingsPage::coreConnectionStateChanged(bool state)
116 updateCoreSupportStatus(state);
125 void CoreHighlightSettingsPage::setupRuleTable(QTableWidget *table) const
127 table->verticalHeader()->hide();
128 table->setShowGrid(false);
130 table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn)->setToolTip(
131 tr("Enable/disable this rule"));
132 table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn)->setWhatsThis(
133 table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn)->toolTip());
135 table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn)->setToolTip(
136 tr("Phrase to match"));
137 table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn)->setWhatsThis(
138 table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn)->toolTip());
140 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setToolTip(
141 tr("<b>RegEx</b>: This option determines if the highlight rule, <i>Sender</i>, and "
142 "<i>Channel</i> should be interpreted as <b>regular expressions</b> or just as "
144 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setWhatsThis(
145 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->toolTip());
147 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setToolTip(
148 tr("<b>CS</b>: This option determines if the highlight rule, <i>Sender</i>, and "
149 "<i>Channel</i> should be interpreted <b>case sensitive</b>."));
150 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setWhatsThis(
151 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->toolTip());
153 table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn)->setToolTip(
154 tr("<p><b>Sender</b>: Semicolon separated list of <i>nick!ident@host</i> names, "
155 "leave blank to match any nickname.</p>"
156 "<p><i>Example:</i><br />"
157 "<i>Alice!*; Bob!*@example.com; Carol*!*; !Caroline!*</i><br />"
158 "would match on <i>Alice</i>, <i>Bob</i> with hostmask <i>example.com</i>, and "
159 "any nickname starting with <i>Carol</i> except for <i>Caroline</i><br />"
160 "<p>If only inverted names are specified, it will match anything except for "
161 "what's specified (implicit wildcard).</p>"
162 "<p><i>Example:</i><br />"
163 "<i>!Announce*!*; !Wheatley!aperture@*</i><br />"
164 "would match anything except for <i>Wheatley</i> with ident <i>aperture</i> or "
165 "any nickname starting with <i>Announce</i></p>"));
166 table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn)->setWhatsThis(
167 table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn)->toolTip());
169 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setToolTip(
170 tr("<p><b>Channel</b>: Semicolon separated list of channel names, leave blank to "
171 "match any name.</p>"
172 "<p><i>Example:</i><br />"
173 "<i>#quassel*; #foobar; !#quasseldroid</i><br />"
174 "would match on <i>#foobar</i> and any channel starting with <i>#quassel</i> "
175 "except for <i>#quasseldroid</i><br />"
176 "<p>If only inverted names are specified, it will match anything except for "
177 "what's specified (implicit wildcard).</p>"
178 "<p><i>Example:</i><br />"
179 "<i>!#quassel*; !#foobar</i><br />"
180 "would match anything except for <i>#foobar</i> or any channel starting with "
181 "<i>#quassel</i></p>"));
182 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setWhatsThis(
183 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->toolTip());
185 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
186 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents);
187 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::NameColumn, QHeaderView::Stretch);
188 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents);
189 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents);
190 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents);
192 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents);
193 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::NameColumn, QHeaderView::Stretch);
194 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents);
195 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents);
196 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents);
200 void CoreHighlightSettingsPage::updateCoreSupportStatus(bool state)
202 // Assume connected state as enforced by the settings page UI
203 if (!state || Client::isCoreFeatureEnabled(Quassel::Feature::CoreSideHighlights)) {
204 // Either disconnected or core supports highlights, enable highlight configuration and hide
205 // warning. Don't show the warning needlessly when disconnected.
206 ui.highlightsConfigWidget->setEnabled(true);
207 ui.coreUnsupportedWidget->setVisible(false);
209 // Core does not support highlights, show warning and disable highlight configuration
210 ui.highlightsConfigWidget->setEnabled(false);
211 ui.coreUnsupportedWidget->setVisible(true);
215 void CoreHighlightSettingsPage::clientConnected()
217 connect(Client::highlightRuleManager(), SIGNAL(updated()), SLOT(revert()));
220 void CoreHighlightSettingsPage::revert()
225 setChangedState(false);
229 bool CoreHighlightSettingsPage::hasDefaults() const
234 void CoreHighlightSettingsPage::defaults()
236 int highlightNickType = HighlightRuleManager::HighlightNickType::CurrentNick;
237 int defaultIndex = ui.highlightNicksComboBox->findData(QVariant(highlightNickType));
238 ui.highlightNicksComboBox->setCurrentIndex(defaultIndex);
239 ui.nicksCaseSensitive->setChecked(false);
240 emptyHighlightTable();
246 void CoreHighlightSettingsPage::addNewHighlightRow(bool enable, const QString &name, bool regex, bool cs,
247 const QString &sender, const QString &chanName, bool self)
249 ui.highlightTable->setRowCount(ui.highlightTable->rowCount() + 1);
251 auto *nameItem = new QTableWidgetItem(name);
253 auto *regexItem = new QTableWidgetItem("");
255 regexItem->setCheckState(Qt::Checked);
257 regexItem->setCheckState(Qt::Unchecked);
258 regexItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
260 auto *csItem = new QTableWidgetItem("");
262 csItem->setCheckState(Qt::Checked);
264 csItem->setCheckState(Qt::Unchecked);
265 csItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
267 auto *enableItem = new QTableWidgetItem("");
269 enableItem->setCheckState(Qt::Checked);
271 enableItem->setCheckState(Qt::Unchecked);
272 enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
274 auto *senderItem = new QTableWidgetItem(sender);
276 auto *chanNameItem = new QTableWidgetItem(chanName);
278 enableItem->setToolTip(tr("Enable/disable this rule"));
279 nameItem->setToolTip(tr("Phrase to match"));
280 regexItem->setToolTip(
281 tr("<b>RegEx</b>: This option determines if the highlight rule, <i>Sender</i>, and "
282 "<i>Channel</i> should be interpreted as <b>regular expressions</b> or just as "
285 tr("<b>CS</b>: This option determines if the highlight rule, <i>Sender</i>, and "
286 "<i>Channel</i> should be interpreted <b>case sensitive</b>."));
287 senderItem->setToolTip(
288 tr("<p><b>Sender</b>: Semicolon separated list of <i>nick!ident@host</i> names, "
289 "leave blank to match any nickname.</p>"
290 "<p><i>Example:</i><br />"
291 "<i>Alice!*; Bob!*@example.com; Carol*!*; !Caroline!*</i><br />"
292 "would match on <i>Alice</i>, <i>Bob</i> with hostmask <i>example.com</i>, and "
293 "any nickname starting with <i>Carol</i> except for <i>Caroline</i><br />"
294 "<p>If only inverted names are specified, it will match anything except for "
295 "what's specified (implicit wildcard).</p>"
296 "<p><i>Example:</i><br />"
297 "<i>!Announce*!*; !Wheatley!aperture@*</i><br />"
298 "would match anything except for <i>Wheatley</i> with ident <i>aperture</i> or "
299 "any nickname starting with <i>Announce</i></p>"));
300 chanNameItem->setToolTip(
301 tr("<p><b>Channel</b>: Semicolon separated list of channel names, leave blank to "
302 "match any name.</p>"
303 "<p><i>Example:</i><br />"
304 "<i>#quassel*; #foobar; !#quasseldroid</i><br />"
305 "would match on <i>#foobar</i> and any channel starting with <i>#quassel</i> "
306 "except for <i>#quasseldroid</i><br />"
307 "<p>If only inverted names are specified, it will match anything except for "
308 "what's specified (implicit wildcard).</p>"
309 "<p><i>Example:</i><br />"
310 "<i>!#quassel*; !#foobar</i><br />"
311 "would match anything except for <i>#foobar</i> or any channel starting with "
312 "<i>#quassel</i></p>"));
314 int lastRow = ui.highlightTable->rowCount() - 1;
315 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem);
316 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::RegExColumn, regexItem);
317 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::CsColumn, csItem);
318 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::EnableColumn, enableItem);
319 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::SenderColumn, senderItem);
320 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::ChanColumn, chanNameItem);
323 ui.highlightTable->setCurrentItem(nameItem);
325 highlightList << HighlightRuleManager::HighlightRule(name, regex, cs, enable, false, sender, chanName);
328 void CoreHighlightSettingsPage::addNewIgnoredRow(bool enable, const QString &name, bool regex, bool cs,
329 const QString &sender, const QString &chanName, bool self)
331 ui.ignoredTable->setRowCount(ui.ignoredTable->rowCount() + 1);
333 auto *nameItem = new QTableWidgetItem(name);
335 auto *regexItem = new QTableWidgetItem("");
337 regexItem->setCheckState(Qt::Checked);
339 regexItem->setCheckState(Qt::Unchecked);
340 regexItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
342 auto *csItem = new QTableWidgetItem("");
344 csItem->setCheckState(Qt::Checked);
346 csItem->setCheckState(Qt::Unchecked);
347 csItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
349 auto *enableItem = new QTableWidgetItem("");
351 enableItem->setCheckState(Qt::Checked);
353 enableItem->setCheckState(Qt::Unchecked);
354 enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
356 auto *chanNameItem = new QTableWidgetItem(chanName);
358 auto *senderItem = new QTableWidgetItem(sender);
360 enableItem->setToolTip(tr("Enable/disable this rule"));
361 nameItem->setToolTip(tr("Phrase to match"));
362 regexItem->setToolTip(
363 tr("<b>RegEx</b>: This option determines if the highlight rule should be "
364 "interpreted as a <b>regular expression</b> or just as a keyword."));
366 tr("<b>CS</b>: This option determines if the highlight rule should be interpreted "
367 "<b>case sensitive</b>."));
368 senderItem->setToolTip(
369 tr("<b>Sender</b>: This option specifies which sender nicknames match. Leave "
370 "blank to match any nickname."));
371 chanNameItem->setToolTip(
372 tr("<p><b>Channel</b>: Semicolon separated list of channel names.</p>"
373 "<p><i>Example:</i><br />"
374 "<i>#quassel*; #foobar; !#quasseldroid</i><br />"
375 "would match on #foobar and any channel starting with <i>#quassel</i> except "
376 "for <i>#quasseldroid</i><br />"
377 "<p>If only inverted names are specified, it will match anything except for "
378 "what's specified (implicit wildcard).</p>"
379 "<p><i>Example:</i><br />"
380 "<i>!#quassel*; !#foobar</i><br />"
381 "would match anything except for #foobar or any channel starting with "
382 "<i>#quassel</i></p>"));
384 int lastRow = ui.ignoredTable->rowCount() - 1;
385 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem);
386 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::RegExColumn, regexItem);
387 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::CsColumn, csItem);
388 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::EnableColumn, enableItem);
389 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::SenderColumn, senderItem);
390 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::ChanColumn, chanNameItem);
393 ui.ignoredTable->setCurrentItem(nameItem);
395 ignoredList << HighlightRuleManager::HighlightRule(name, regex, cs, enable, true, sender, chanName);
398 void CoreHighlightSettingsPage::removeSelectedHighlightRows()
400 QList<int> selectedRows;
401 QList<QTableWidgetItem *> selectedItemList = ui.highlightTable->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.highlightTable->removeRow(row);
410 highlightList.removeAt(row);
416 void CoreHighlightSettingsPage::removeSelectedIgnoredRows()
418 QList<int> selectedRows;
419 QList<QTableWidgetItem *> selectedItemList = ui.ignoredTable->selectedItems();
420 for (auto selectedItem : selectedItemList) {
421 selectedRows.append(selectedItem->row());
423 qSort(selectedRows.begin(), selectedRows.end(), qGreater<int>());
425 for (auto row : selectedRows) {
426 if (row != lastRow) {
427 ui.ignoredTable->removeRow(row);
428 ignoredList.removeAt(row);
434 void CoreHighlightSettingsPage::highlightNicksChanged(const int index) {
435 // Only allow toggling "Case sensitive" when a nickname will be highlighted
436 auto highlightNickType = ui.highlightNicksComboBox->itemData(index).value<int>();
437 ui.nicksCaseSensitive->setEnabled(highlightNickType != HighlightRuleManager::NoNick);
440 void CoreHighlightSettingsPage::selectHighlightRow(QTableWidgetItem *item)
442 int row = item->row();
443 bool selected = item->isSelected();
445 ->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, CoreHighlightSettingsPage::ColumnCount - 1),
449 void CoreHighlightSettingsPage::selectIgnoredRow(QTableWidgetItem *item)
451 int row = item->row();
452 bool selected = item->isSelected();
454 ->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, CoreHighlightSettingsPage::ColumnCount - 1),
458 void CoreHighlightSettingsPage::emptyHighlightTable()
460 // ui.highlight and highlightList should have the same size, but just to make sure.
461 if (ui.highlightTable->rowCount() != highlightList.size()) {
462 qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!";
464 while (ui.highlightTable->rowCount()) {
465 ui.highlightTable->removeRow(0);
467 highlightList.clear();
470 void CoreHighlightSettingsPage::emptyIgnoredTable()
472 // ui.highlight and highlightList should have the same size, but just to make sure.
473 if (ui.ignoredTable->rowCount() != ignoredList.size()) {
474 qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!";
476 while (ui.ignoredTable->rowCount()) {
477 ui.ignoredTable->removeRow(0);
482 void CoreHighlightSettingsPage::highlightTableChanged(QTableWidgetItem *item)
484 if (item->row() + 1 > highlightList.size())
487 auto highlightRule = highlightList.value(item->row());
490 switch (item->column()) {
491 case CoreHighlightSettingsPage::EnableColumn:
492 highlightRule.isEnabled = (item->checkState() == Qt::Checked);
494 case CoreHighlightSettingsPage::NameColumn:
495 if (item->text() == "")
496 item->setText(tr("this shouldn't be empty"));
497 highlightRule.name = item->text();
499 case CoreHighlightSettingsPage::RegExColumn:
500 highlightRule.isRegEx = (item->checkState() == Qt::Checked);
502 case CoreHighlightSettingsPage::CsColumn:
503 highlightRule.isCaseSensitive = (item->checkState() == Qt::Checked);
505 case CoreHighlightSettingsPage::SenderColumn:
506 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
508 highlightRule.sender = item->text();
510 case CoreHighlightSettingsPage::ChanColumn:
511 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
513 highlightRule.chanName = item->text();
516 highlightList[item->row()] = highlightRule;
517 emit widgetHasChanged();
520 void CoreHighlightSettingsPage::ignoredTableChanged(QTableWidgetItem *item)
522 if (item->row() + 1 > ignoredList.size())
525 auto ignoredRule = ignoredList.value(item->row());
528 switch (item->column()) {
529 case CoreHighlightSettingsPage::EnableColumn:
530 ignoredRule.isEnabled = (item->checkState() == Qt::Checked);
532 case CoreHighlightSettingsPage::NameColumn:
533 if (item->text() == "")
534 item->setText(tr("this shouldn't be empty"));
535 ignoredRule.name = item->text();
537 case CoreHighlightSettingsPage::RegExColumn:
538 ignoredRule.isRegEx = (item->checkState() == Qt::Checked);
540 case CoreHighlightSettingsPage::CsColumn:
541 ignoredRule.isCaseSensitive = (item->checkState() == Qt::Checked);
543 case CoreHighlightSettingsPage::SenderColumn:
544 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
546 ignoredRule.sender = item->text();
548 case CoreHighlightSettingsPage::ChanColumn:
549 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
551 ignoredRule.chanName = item->text();
554 ignoredList[item->row()] = ignoredRule;
555 emit widgetHasChanged();
558 void CoreHighlightSettingsPage::load()
560 emptyHighlightTable();
563 auto ruleManager = Client::highlightRuleManager();
565 for (auto &rule : ruleManager->highlightRuleList()) {
566 if (rule.isInverse) {
567 addNewIgnoredRow(rule.isEnabled,
570 rule.isCaseSensitive,
575 addNewHighlightRow(rule.isEnabled, rule.name, rule.isRegEx, rule.isCaseSensitive, rule.sender,
580 int highlightNickType = ruleManager->highlightNick();
581 ui.highlightNicksComboBox->setCurrentIndex(ui.highlightNicksComboBox->findData(QVariant(highlightNickType)));
582 // Trigger the initial update of nicksCaseSensitive being enabled or not
583 highlightNicksChanged(ui.highlightNicksComboBox->currentIndex());
584 ui.nicksCaseSensitive->setChecked(ruleManager->nicksCaseSensitive());
586 setChangedState(false);
593 void CoreHighlightSettingsPage::save()
601 auto ruleManager = Client::highlightRuleManager();
602 if (ruleManager == nullptr)
605 auto clonedManager = HighlightRuleManager();
606 clonedManager.fromVariantMap(ruleManager->toVariantMap());
607 clonedManager.clear();
609 for (auto &rule : highlightList) {
610 clonedManager.addHighlightRule(rule.name, rule.isRegEx, rule.isCaseSensitive, rule.isEnabled, false,
611 rule.sender, rule.chanName);
614 for (auto &rule : ignoredList) {
615 clonedManager.addHighlightRule(rule.name, rule.isRegEx, rule.isCaseSensitive, rule.isEnabled, true,
616 rule.sender, rule.chanName);
619 auto highlightNickType = ui.highlightNicksComboBox->itemData(ui.highlightNicksComboBox->currentIndex()).value<int>();
621 clonedManager.setHighlightNick(HighlightRuleManager::HighlightNickType(highlightNickType));
622 clonedManager.setNicksCaseSensitive(ui.nicksCaseSensitive->isChecked());
624 ruleManager->requestUpdate(clonedManager.toVariantMap());
625 setChangedState(false);
629 void CoreHighlightSettingsPage::widgetHasChanged()
631 setChangedState(true);
634 void CoreHighlightSettingsPage::on_coreUnsupportedDetails_clicked()
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 const QString remoteHighlightsMsgText =
641 QString("<p><b>%1</b></p></br><p>%2</p></br><p>%3</p>"
642 ).arg(tr("Your Quassel core is too old to support remote highlights"),
643 tr("You need a Quassel core v0.13.0 or newer to configure remote "
645 tr("You can still configure highlights for this device only in "
646 "<i>%1</i>.").arg(localHighlightsName));
648 QMessageBox::warning(this,
649 tr("Remote Highlights unsupported"),
650 remoteHighlightsMsgText);
653 void CoreHighlightSettingsPage::importRules() {
654 NotificationSettings notificationSettings;
656 const auto localHighlightList = notificationSettings.highlightList();
658 // Re-use translations of "Legacy/Local Highlights" as this is a word-for-word reference,
659 // forcing all spaces to non-breaking
660 QString localHighlightsName;
661 if (Quassel::runMode() == Quassel::Monolithic) {
662 localHighlightsName = tr("Legacy Highlights").replace(" ", " ");
664 localHighlightsName = tr("Local Highlights").replace(" ", " ");
667 if (localHighlightList.count() == 0) {
668 // No highlight rules exist to import, do nothing
669 QMessageBox::information(this,
670 tr("No highlights to import"),
671 tr("No highlight rules in <i>%1</i>."
672 ).arg(localHighlightsName));
676 int ret = QMessageBox::question(this,
677 tr("Import highlights?"),
678 tr("Import all highlight rules from <i>%1</i>?"
679 ).arg(localHighlightsName),
680 QMessageBox::Yes|QMessageBox::No,
683 if (ret != QMessageBox::Yes) {
684 // Only two options, Yes or No, return if not Yes
688 auto clonedManager = HighlightRuleManager();
689 clonedManager.fromVariantMap(Client::highlightRuleManager()->toVariantMap());
691 for (const auto &variant : notificationSettings.highlightList()) {
692 auto highlightRule = variant.toMap();
694 clonedManager.addHighlightRule(
695 highlightRule["Name"].toString(),
696 highlightRule["RegEx"].toBool(),
697 highlightRule["CS"].toBool(),
698 highlightRule["Enable"].toBool(),
701 highlightRule["Channel"].toString()
705 Client::highlightRuleManager()->requestUpdate(clonedManager.toVariantMap());
706 setChangedState(false);
709 // Give a heads-up that all succeeded
710 QMessageBox::information(this,
711 tr("Imported highlights"),
712 tr("%1 highlight rules successfully imported."
713 ).arg(QString::number(localHighlightList.count())));
716 bool CoreHighlightSettingsPage::isSelectable() const {
717 return Client::isConnected();
718 // We check for Quassel::Feature::CoreSideHighlights when loading this page, allowing us to show
719 // a friendly error message.