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 <QHeaderView>
22 #include <QTableWidget>
25 #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()));
79 void CoreHighlightSettingsPage::setupRuleTable(QTableWidget *table) const
81 table->verticalHeader()->hide();
82 table->setShowGrid(false);
84 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setToolTip(
85 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."));
86 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setWhatsThis(
87 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."));
89 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setToolTip(
90 tr("<b>CS</b>: This option determines if the highlight rule should be interpreted <b>case sensitive</b>."));
91 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setWhatsThis(
92 tr("<b>CS</b>: This option determines if the highlight rule should be interpreted <b>case sensitive</b>."));
94 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setToolTip(
95 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."));
96 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setWhatsThis(
97 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."));
99 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
100 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents);
101 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::NameColumn, QHeaderView::Stretch);
102 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents);
103 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents);
104 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents);
106 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents);
107 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::NameColumn, QHeaderView::Stretch);
108 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents);
109 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents);
110 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents);
114 void CoreHighlightSettingsPage::clientConnected()
116 connect(Client::highlightRuleManager(), SIGNAL(updated()), SLOT(revert()));
119 void CoreHighlightSettingsPage::revert()
124 setChangedState(false);
128 bool CoreHighlightSettingsPage::hasDefaults() const
133 void CoreHighlightSettingsPage::defaults()
135 int highlightNickType = HighlightRuleManager::HighlightNickType::CurrentNick;
136 int defaultIndex = ui.highlightNicksComboBox->findData(QVariant(highlightNickType));
137 ui.highlightNicksComboBox->setCurrentIndex(defaultIndex);
138 ui.nicksCaseSensitive->setChecked(false);
139 emptyHighlightTable();
145 void CoreHighlightSettingsPage::addNewHighlightRow(bool enable, const QString &name, bool regex, bool cs,
146 const QString &sender, const QString &chanName, bool self)
148 ui.highlightTable->setRowCount(ui.highlightTable->rowCount() + 1);
150 auto *nameItem = new QTableWidgetItem(name);
152 auto *regexItem = new QTableWidgetItem("");
154 regexItem->setCheckState(Qt::Checked);
156 regexItem->setCheckState(Qt::Unchecked);
157 regexItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
159 auto *csItem = new QTableWidgetItem("");
161 csItem->setCheckState(Qt::Checked);
163 csItem->setCheckState(Qt::Unchecked);
164 csItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
166 auto *enableItem = new QTableWidgetItem("");
168 enableItem->setCheckState(Qt::Checked);
170 enableItem->setCheckState(Qt::Unchecked);
171 enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
173 auto *chanNameItem = new QTableWidgetItem(chanName);
175 auto *senderItem = new QTableWidgetItem(sender);
177 int lastRow = ui.highlightTable->rowCount() - 1;
178 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem);
179 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::RegExColumn, regexItem);
180 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::CsColumn, csItem);
181 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::EnableColumn, enableItem);
182 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::SenderColumn, senderItem);
183 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::ChanColumn, chanNameItem);
186 ui.highlightTable->setCurrentItem(nameItem);
188 highlightList << HighlightRuleManager::HighlightRule(name, regex, cs, enable, false, sender, chanName);
191 void CoreHighlightSettingsPage::addNewIgnoredRow(bool enable, const QString &name, bool regex, bool cs,
192 const QString &sender, const QString &chanName, bool self)
194 ui.ignoredTable->setRowCount(ui.ignoredTable->rowCount() + 1);
196 auto *nameItem = new QTableWidgetItem(name);
198 auto *regexItem = new QTableWidgetItem("");
200 regexItem->setCheckState(Qt::Checked);
202 regexItem->setCheckState(Qt::Unchecked);
203 regexItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
205 auto *csItem = new QTableWidgetItem("");
207 csItem->setCheckState(Qt::Checked);
209 csItem->setCheckState(Qt::Unchecked);
210 csItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
212 auto *enableItem = new QTableWidgetItem("");
214 enableItem->setCheckState(Qt::Checked);
216 enableItem->setCheckState(Qt::Unchecked);
217 enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
219 auto *chanNameItem = new QTableWidgetItem(chanName);
221 auto *senderItem = new QTableWidgetItem(sender);
223 int lastRow = ui.ignoredTable->rowCount() - 1;
224 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem);
225 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::RegExColumn, regexItem);
226 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::CsColumn, csItem);
227 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::EnableColumn, enableItem);
228 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::SenderColumn, senderItem);
229 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::ChanColumn, chanNameItem);
232 ui.ignoredTable->setCurrentItem(nameItem);
234 ignoredList << HighlightRuleManager::HighlightRule(name, regex, cs, enable, true, sender, chanName);
237 void CoreHighlightSettingsPage::removeSelectedHighlightRows()
239 QList<int> selectedRows;
240 QList<QTableWidgetItem *> selectedItemList = ui.highlightTable->selectedItems();
241 for (auto selectedItem : selectedItemList) {
242 selectedRows.append(selectedItem->row());
244 qSort(selectedRows.begin(), selectedRows.end(), qGreater<int>());
246 for (auto row : selectedRows) {
247 if (row != lastRow) {
248 ui.highlightTable->removeRow(row);
249 highlightList.removeAt(row);
255 void CoreHighlightSettingsPage::removeSelectedIgnoredRows()
257 QList<int> selectedRows;
258 QList<QTableWidgetItem *> selectedItemList = ui.ignoredTable->selectedItems();
259 for (auto selectedItem : selectedItemList) {
260 selectedRows.append(selectedItem->row());
262 qSort(selectedRows.begin(), selectedRows.end(), qGreater<int>());
264 for (auto row : selectedRows) {
265 if (row != lastRow) {
266 ui.ignoredTable->removeRow(row);
267 ignoredList.removeAt(row);
273 void CoreHighlightSettingsPage::selectHighlightRow(QTableWidgetItem *item)
275 int row = item->row();
276 bool selected = item->isSelected();
278 ->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, CoreHighlightSettingsPage::ColumnCount - 1),
282 void CoreHighlightSettingsPage::selectIgnoredRow(QTableWidgetItem *item)
284 int row = item->row();
285 bool selected = item->isSelected();
287 ->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, CoreHighlightSettingsPage::ColumnCount - 1),
291 void CoreHighlightSettingsPage::emptyHighlightTable()
293 // ui.highlight and highlightList should have the same size, but just to make sure.
294 if (ui.highlightTable->rowCount() != highlightList.size()) {
295 qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!";
297 ui.highlightTable->clearContents();
298 highlightList.clear();
301 void CoreHighlightSettingsPage::emptyIgnoredTable()
303 // ui.highlight and highlightList should have the same size, but just to make sure.
304 if (ui.ignoredTable->rowCount() != ignoredList.size()) {
305 qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!";
307 ui.ignoredTable->clearContents();
311 void CoreHighlightSettingsPage::highlightTableChanged(QTableWidgetItem *item)
313 if (item->row() + 1 > highlightList.size())
316 auto highlightRule = highlightList.value(item->row());
319 switch (item->column()) {
320 case CoreHighlightSettingsPage::EnableColumn:
321 highlightRule.isEnabled = (item->checkState() == Qt::Checked);
323 case CoreHighlightSettingsPage::NameColumn:
324 if (item->text() == "")
325 item->setText(tr("this shouldn't be empty"));
326 highlightRule.name = item->text();
328 case CoreHighlightSettingsPage::RegExColumn:
329 highlightRule.isRegEx = (item->checkState() == Qt::Checked);
331 case CoreHighlightSettingsPage::CsColumn:
332 highlightRule.isCaseSensitive = (item->checkState() == Qt::Checked);
334 case CoreHighlightSettingsPage::SenderColumn:
335 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
337 highlightRule.sender = item->text();
339 case CoreHighlightSettingsPage::ChanColumn:
340 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
342 highlightRule.chanName = item->text();
345 highlightList[item->row()] = highlightRule;
346 emit widgetHasChanged();
349 void CoreHighlightSettingsPage::ignoredTableChanged(QTableWidgetItem *item)
351 if (item->row() + 1 > ignoredList.size())
354 auto ignoredRule = ignoredList.value(item->row());
357 switch (item->column()) {
358 case CoreHighlightSettingsPage::EnableColumn:
359 ignoredRule.isEnabled = (item->checkState() == Qt::Checked);
361 case CoreHighlightSettingsPage::NameColumn:
362 if (item->text() == "")
363 item->setText(tr("this shouldn't be empty"));
364 ignoredRule.name = item->text();
366 case CoreHighlightSettingsPage::RegExColumn:
367 ignoredRule.isRegEx = (item->checkState() == Qt::Checked);
369 case CoreHighlightSettingsPage::CsColumn:
370 ignoredRule.isCaseSensitive = (item->checkState() == Qt::Checked);
372 case CoreHighlightSettingsPage::SenderColumn:
373 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
375 ignoredRule.sender = item->text();
377 case CoreHighlightSettingsPage::ChanColumn:
378 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
380 ignoredRule.chanName = item->text();
383 ignoredList[item->row()] = ignoredRule;
384 emit widgetHasChanged();
387 void CoreHighlightSettingsPage::load()
389 emptyHighlightTable();
392 auto ruleManager = Client::highlightRuleManager();
394 for (auto &rule : ruleManager->highlightRuleList()) {
395 if (rule.isInverse) {
396 addNewIgnoredRow(rule.isEnabled,
399 rule.isCaseSensitive,
404 addNewHighlightRow(rule.isEnabled, rule.name, rule.isRegEx, rule.isCaseSensitive, rule.sender,
409 int highlightNickType = ruleManager->highlightNick();
410 ui.highlightNicksComboBox->setCurrentIndex(ui.highlightNicksComboBox->findData(QVariant(highlightNickType)));
411 ui.nicksCaseSensitive->setChecked(ruleManager->nicksCaseSensitive());
413 setChangedState(false);
420 void CoreHighlightSettingsPage::save()
428 auto ruleManager = Client::highlightRuleManager();
429 if (ruleManager == nullptr)
432 auto clonedManager = HighlightRuleManager();
433 clonedManager.fromVariantMap(ruleManager->toVariantMap());
434 clonedManager.clear();
436 for (auto &rule : highlightList) {
437 clonedManager.addHighlightRule(rule.name, rule.isRegEx, rule.isCaseSensitive, rule.isEnabled, false,
438 rule.sender, rule.chanName);
441 for (auto &rule : ignoredList) {
442 clonedManager.addHighlightRule(rule.name, rule.isRegEx, rule.isCaseSensitive, rule.isEnabled, true,
443 rule.sender, rule.chanName);
446 auto highlightNickType = ui.highlightNicksComboBox->itemData(ui.highlightNicksComboBox->currentIndex()).value<int>();
448 clonedManager.setHighlightNick(HighlightRuleManager::HighlightNickType(highlightNickType));
449 clonedManager.setNicksCaseSensitive(ui.nicksCaseSensitive->isChecked());
451 ruleManager->requestUpdate(clonedManager.toVariantMap());
452 setChangedState(false);
456 void CoreHighlightSettingsPage::widgetHasChanged()
458 setChangedState(true);