1 /***************************************************************************
2 * Copyright (C) 2005-2016 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 <QTableWidget>
22 #include <QtWidgets/QHeaderView>
24 #include "corehighlightsettingspage.h"
28 CoreHighlightSettingsPage::CoreHighlightSettingsPage(QWidget *parent)
29 : SettingsPage(tr("Interface"), tr("Core-Side Highlights"), parent)
33 setupRuleTable(ui.highlightTable);
34 setupRuleTable(ui.ignoredTable);
36 ui.highlightNicksComboBox->addItem(tr("All Nicks from Identity"), QVariant(HighlightRuleManager::AllNicks));
37 ui.highlightNicksComboBox->addItem(tr("Current Nick"), QVariant(HighlightRuleManager::CurrentNick));
38 ui.highlightNicksComboBox->addItem(tr("None"), QVariant(HighlightRuleManager::NoNick));
40 connect(ui.highlightAdd, SIGNAL(clicked(bool)), this, SLOT(addNewHighlightRow()));
41 connect(ui.highlightRemove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedHighlightRows()));
43 connect(ui.ignoredAdd, SIGNAL(clicked(bool)), this, SLOT(addNewIgnoredRow()));
44 connect(ui.ignoredRemove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedIgnoredRows()));
46 // TODO: search for a better signal (one that emits everytime a selection has been changed for one item)
47 connect(ui.highlightTable,
48 SIGNAL(itemClicked(QTableWidgetItem * )),
50 SLOT(selectHighlightRow(QTableWidgetItem * )));
51 connect(ui.ignoredTable,
52 SIGNAL(itemClicked(QTableWidgetItem * )),
54 SLOT(selectIgnoredRow(QTableWidgetItem * )));
57 connect(ui.highlightNicksComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
58 connect(ui.nicksCaseSensitive, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
60 connect(ui.highlightAdd, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
61 connect(ui.highlightRemove, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
63 connect(ui.ignoredAdd, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
64 connect(ui.ignoredRemove, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
66 connect(ui.highlightTable,
67 SIGNAL(itemChanged(QTableWidgetItem * )),
69 SLOT(highlightTableChanged(QTableWidgetItem * )));
71 connect(ui.ignoredTable,
72 SIGNAL(itemChanged(QTableWidgetItem * )),
74 SLOT(ignoredTableChanged(QTableWidgetItem * )));
76 connect(Client::instance(), SIGNAL(connected()), this, SLOT(clientConnected()));
78 void CoreHighlightSettingsPage::setupRuleTable(QTableWidget *table) const
80 table->verticalHeader()->hide();
81 table->setShowGrid(false);
83 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setToolTip(
84 tr("<b>RegEx</b>: This option determines if the highlight rule should be interpreted as a <b>regular expression</b> or just as a keyword."));
85 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setWhatsThis(
86 tr("<b>RegEx</b>: This option determines if the highlight rule should be interpreted as a <b>regular expression</b> or just as a keyword."));
88 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setToolTip(
89 tr("<b>CS</b>: This option determines if the highlight rule should be interpreted <b>case sensitive</b>."));
90 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setWhatsThis(
91 tr("<b>CS</b>: This option determines if the highlight rule should be interpreted <b>case sensitive</b>."));
93 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setToolTip(
94 tr("<b>Channel</b>: This regular expression determines for which <b>channels</b> the highlight rule works. Leave blank to match any channel. Put <b>!</b> in the beginning to negate. Case insensitive."));
95 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setWhatsThis(
96 tr("<b>Channel</b>: This regular expression determines for which <b>channels</b> the highlight rule works. Leave blank to match any channel. Put <b>!</b> in the beginning to negate. Case insensitive."));
98 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
99 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents);
100 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::NameColumn, QHeaderView::Stretch);
101 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents);
102 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents);
103 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents);
105 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents);
106 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::NameColumn, QHeaderView::Stretch);
107 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents);
108 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents);
109 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents);
113 void CoreHighlightSettingsPage::clientConnected()
115 connect(Client::highlightRuleManager(), SIGNAL(updated()), SLOT(revert()));
118 void CoreHighlightSettingsPage::revert()
123 setChangedState(false);
127 bool CoreHighlightSettingsPage::hasDefaults() const
132 void CoreHighlightSettingsPage::defaults()
134 int highlightNickType = HighlightRuleManager::HighlightNickType::CurrentNick;
135 int defaultIndex = ui.highlightNicksComboBox->findData(QVariant(highlightNickType));
136 ui.highlightNicksComboBox->setCurrentIndex(defaultIndex);
137 ui.nicksCaseSensitive->setChecked(false);
138 emptyHighlightTable();
144 void CoreHighlightSettingsPage::addNewHighlightRow(bool enable, const QString &name, bool regex, bool cs,
145 const QString &sender, const QString &chanName, bool self)
147 ui.highlightTable->setRowCount(ui.highlightTable->rowCount() + 1);
149 auto *nameItem = new QTableWidgetItem(name);
151 auto *regexItem = new QTableWidgetItem("");
153 regexItem->setCheckState(Qt::Checked);
155 regexItem->setCheckState(Qt::Unchecked);
156 regexItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
158 auto *csItem = new QTableWidgetItem("");
160 csItem->setCheckState(Qt::Checked);
162 csItem->setCheckState(Qt::Unchecked);
163 csItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
165 auto *enableItem = new QTableWidgetItem("");
167 enableItem->setCheckState(Qt::Checked);
169 enableItem->setCheckState(Qt::Unchecked);
170 enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
172 auto *chanNameItem = new QTableWidgetItem(chanName);
174 auto *senderItem = new QTableWidgetItem(sender);
176 int lastRow = ui.highlightTable->rowCount() - 1;
177 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem);
178 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::RegExColumn, regexItem);
179 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::CsColumn, csItem);
180 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::EnableColumn, enableItem);
181 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::SenderColumn, senderItem);
182 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::ChanColumn, chanNameItem);
185 ui.highlightTable->setCurrentItem(nameItem);
187 highlightList << HighlightRuleManager::HighlightRule(name, regex, cs, enable, false, sender, chanName);
190 void CoreHighlightSettingsPage::addNewIgnoredRow(bool enable, const QString &name, bool regex, bool cs,
191 const QString &sender, const QString &chanName, bool self)
193 ui.ignoredTable->setRowCount(ui.ignoredTable->rowCount() + 1);
195 auto *nameItem = new QTableWidgetItem(name);
197 auto *regexItem = new QTableWidgetItem("");
199 regexItem->setCheckState(Qt::Checked);
201 regexItem->setCheckState(Qt::Unchecked);
202 regexItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
204 auto *csItem = new QTableWidgetItem("");
206 csItem->setCheckState(Qt::Checked);
208 csItem->setCheckState(Qt::Unchecked);
209 csItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
211 auto *enableItem = new QTableWidgetItem("");
213 enableItem->setCheckState(Qt::Checked);
215 enableItem->setCheckState(Qt::Unchecked);
216 enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
218 auto *chanNameItem = new QTableWidgetItem(chanName);
220 auto *senderItem = new QTableWidgetItem(sender);
222 int lastRow = ui.ignoredTable->rowCount() - 1;
223 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem);
224 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::RegExColumn, regexItem);
225 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::CsColumn, csItem);
226 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::EnableColumn, enableItem);
227 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::SenderColumn, senderItem);
228 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::ChanColumn, chanNameItem);
231 ui.ignoredTable->setCurrentItem(nameItem);
233 ignoredList << HighlightRuleManager::HighlightRule(name, regex, cs, enable, true, sender, chanName);
236 void CoreHighlightSettingsPage::removeSelectedHighlightRows()
238 QList<int> selectedRows;
239 QList<QTableWidgetItem *> selectedItemList = ui.highlightTable->selectedItems();
240 for (auto selectedItem : selectedItemList) {
241 selectedRows.append(selectedItem->row());
243 qSort(selectedRows.begin(), selectedRows.end(), qGreater<int>());
245 for (auto row : selectedRows) {
246 if (row != lastRow) {
247 ui.highlightTable->removeRow(row);
248 highlightList.removeAt(row);
254 void CoreHighlightSettingsPage::removeSelectedIgnoredRows()
256 QList<int> selectedRows;
257 QList<QTableWidgetItem *> selectedItemList = ui.ignoredTable->selectedItems();
258 for (auto selectedItem : selectedItemList) {
259 selectedRows.append(selectedItem->row());
261 qSort(selectedRows.begin(), selectedRows.end(), qGreater<int>());
263 for (auto row : selectedRows) {
264 if (row != lastRow) {
265 ui.ignoredTable->removeRow(row);
266 ignoredList.removeAt(row);
272 void CoreHighlightSettingsPage::selectHighlightRow(QTableWidgetItem *item)
274 int row = item->row();
275 bool selected = item->isSelected();
277 ->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, CoreHighlightSettingsPage::ColumnCount - 1),
281 void CoreHighlightSettingsPage::selectIgnoredRow(QTableWidgetItem *item)
283 int row = item->row();
284 bool selected = item->isSelected();
286 ->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, CoreHighlightSettingsPage::ColumnCount - 1),
290 void CoreHighlightSettingsPage::emptyHighlightTable()
292 // ui.highlight and highlightList should have the same size, but just to make sure.
293 if (ui.highlightTable->rowCount() != highlightList.size()) {
294 qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!";
296 ui.highlightTable->clearContents();
297 highlightList.clear();
300 void CoreHighlightSettingsPage::emptyIgnoredTable()
302 // ui.highlight and highlightList should have the same size, but just to make sure.
303 if (ui.ignoredTable->rowCount() != ignoredList.size()) {
304 qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!";
306 ui.ignoredTable->clearContents();
310 void CoreHighlightSettingsPage::highlightTableChanged(QTableWidgetItem *item)
312 if (item->row() + 1 > highlightList.size())
315 auto highlightRule = highlightList.value(item->row());
318 switch (item->column()) {
319 case CoreHighlightSettingsPage::EnableColumn:
320 highlightRule.isEnabled = (item->checkState() == Qt::Checked);
321 case CoreHighlightSettingsPage::NameColumn:
322 if (item->text() == "")
323 item->setText(tr("this shouldn't be empty"));
324 highlightRule.name = item->text();
326 case CoreHighlightSettingsPage::RegExColumn:
327 highlightRule.isRegEx = (item->checkState() == Qt::Checked);
329 case CoreHighlightSettingsPage::CsColumn:
330 highlightRule.isCaseSensitive = (item->checkState() == Qt::Checked);
332 case CoreHighlightSettingsPage::SenderColumn:
333 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
335 highlightRule.sender = item->text();
337 case CoreHighlightSettingsPage::ChanColumn:
338 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
340 highlightRule.chanName = item->text();
343 highlightList[item->row()] = highlightRule;
344 emit widgetHasChanged();
347 void CoreHighlightSettingsPage::ignoredTableChanged(QTableWidgetItem *item)
349 if (item->row() + 1 > ignoredList.size())
352 auto ignoredRule = ignoredList.value(item->row());
355 switch (item->column()) {
356 case CoreHighlightSettingsPage::EnableColumn:
357 ignoredRule.isEnabled = (item->checkState() == Qt::Checked);
358 case CoreHighlightSettingsPage::NameColumn:
359 if (item->text() == "")
360 item->setText(tr("this shouldn't be empty"));
361 ignoredRule.name = item->text();
363 case CoreHighlightSettingsPage::RegExColumn:
364 ignoredRule.isRegEx = (item->checkState() == Qt::Checked);
366 case CoreHighlightSettingsPage::CsColumn:
367 ignoredRule.isCaseSensitive = (item->checkState() == Qt::Checked);
369 case CoreHighlightSettingsPage::SenderColumn:
370 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
372 ignoredRule.sender = item->text();
374 case CoreHighlightSettingsPage::ChanColumn:
375 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
377 ignoredRule.chanName = item->text();
380 ignoredList[item->row()] = ignoredRule;
381 emit widgetHasChanged();
384 void CoreHighlightSettingsPage::load()
386 emptyHighlightTable();
389 auto ruleManager = Client::highlightRuleManager();
391 for (auto &rule : ruleManager->highlightRuleList()) {
392 if (rule.isInverse) {
393 addNewIgnoredRow(rule.isEnabled,
396 rule.isCaseSensitive,
401 addNewHighlightRow(rule.isEnabled, rule.name, rule.isRegEx, rule.isCaseSensitive, rule.sender,
406 int highlightNickType = ruleManager->highlightNick();
407 ui.highlightNicksComboBox->setCurrentIndex(ui.highlightNicksComboBox->findData(QVariant(highlightNickType)));
408 ui.nicksCaseSensitive->setChecked(ruleManager->nicksCaseSensitive());
410 setChangedState(false);
417 void CoreHighlightSettingsPage::save()
425 auto ruleManager = Client::highlightRuleManager();
426 if (ruleManager == nullptr)
429 auto clonedManager = HighlightRuleManager();
430 clonedManager.fromVariantMap(ruleManager->toVariantMap());
431 clonedManager.clear();
433 for (auto &rule : highlightList) {
434 clonedManager.addHighlightRule(rule.name, rule.isRegEx, rule.isCaseSensitive, rule.isEnabled, false,
435 rule.sender, rule.chanName);
438 for (auto &rule : ignoredList) {
439 clonedManager.addHighlightRule(rule.name, rule.isRegEx, rule.isCaseSensitive, rule.isEnabled, true,
440 rule.sender, rule.chanName);
443 auto highlightNickType = ui.highlightNicksComboBox->currentData().value<int>();
445 clonedManager.setHighlightNick(HighlightRuleManager::HighlightNickType(highlightNickType));
446 clonedManager.setNicksCaseSensitive(ui.nicksCaseSensitive->isChecked());
448 ruleManager->requestUpdate(clonedManager.toVariantMap());
449 setChangedState(false);
453 void CoreHighlightSettingsPage::widgetHasChanged()
455 setChangedState(true);