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 coreConnectionStateChanged(Client::isConnected()); // need a core connection!
41 connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool)));
43 connect(ui.highlightAdd, SIGNAL(clicked(bool)), this, SLOT(addNewHighlightRow()));
44 connect(ui.highlightRemove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedHighlightRows()));
46 connect(ui.ignoredAdd, SIGNAL(clicked(bool)), this, SLOT(addNewIgnoredRow()));
47 connect(ui.ignoredRemove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedIgnoredRows()));
49 // TODO: search for a better signal (one that emits everytime a selection has been changed for one item)
50 connect(ui.highlightTable,
51 SIGNAL(itemClicked(QTableWidgetItem * )),
53 SLOT(selectHighlightRow(QTableWidgetItem * )));
54 connect(ui.ignoredTable,
55 SIGNAL(itemClicked(QTableWidgetItem * )),
57 SLOT(selectIgnoredRow(QTableWidgetItem * )));
60 connect(ui.highlightNicksComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
61 connect(ui.nicksCaseSensitive, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
63 connect(ui.highlightAdd, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
64 connect(ui.highlightRemove, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
66 connect(ui.ignoredAdd, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
67 connect(ui.ignoredRemove, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
69 connect(ui.highlightTable,
70 SIGNAL(itemChanged(QTableWidgetItem * )),
72 SLOT(highlightTableChanged(QTableWidgetItem * )));
74 connect(ui.ignoredTable,
75 SIGNAL(itemChanged(QTableWidgetItem * )),
77 SLOT(ignoredTableChanged(QTableWidgetItem * )));
79 connect(Client::instance(), SIGNAL(connected()), this, SLOT(clientConnected()));
82 void CoreHighlightSettingsPage::coreConnectionStateChanged(bool state)
92 void CoreHighlightSettingsPage::setupRuleTable(QTableWidget *table) const
94 table->verticalHeader()->hide();
95 table->setShowGrid(false);
97 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setToolTip(
98 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."));
99 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setWhatsThis(
100 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."));
102 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setToolTip(
103 tr("<b>CS</b>: This option determines if the highlight rule should be interpreted <b>case sensitive</b>."));
104 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setWhatsThis(
105 tr("<b>CS</b>: This option determines if the highlight rule should be interpreted <b>case sensitive</b>."));
107 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setToolTip(
108 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."));
109 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setWhatsThis(
110 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."));
112 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
113 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents);
114 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::NameColumn, QHeaderView::Stretch);
115 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents);
116 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents);
117 table->horizontalHeader()->setResizeMode(CoreHighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents);
119 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents);
120 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::NameColumn, QHeaderView::Stretch);
121 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents);
122 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents);
123 table->horizontalHeader()->setSectionResizeMode(CoreHighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents);
127 void CoreHighlightSettingsPage::clientConnected()
129 connect(Client::highlightRuleManager(), SIGNAL(updated()), SLOT(revert()));
132 void CoreHighlightSettingsPage::revert()
137 setChangedState(false);
141 bool CoreHighlightSettingsPage::hasDefaults() const
146 void CoreHighlightSettingsPage::defaults()
148 int highlightNickType = HighlightRuleManager::HighlightNickType::CurrentNick;
149 int defaultIndex = ui.highlightNicksComboBox->findData(QVariant(highlightNickType));
150 ui.highlightNicksComboBox->setCurrentIndex(defaultIndex);
151 ui.nicksCaseSensitive->setChecked(false);
152 emptyHighlightTable();
158 void CoreHighlightSettingsPage::addNewHighlightRow(bool enable, const QString &name, bool regex, bool cs,
159 const QString &sender, const QString &chanName, bool self)
161 ui.highlightTable->setRowCount(ui.highlightTable->rowCount() + 1);
163 auto *nameItem = new QTableWidgetItem(name);
165 auto *regexItem = new QTableWidgetItem("");
167 regexItem->setCheckState(Qt::Checked);
169 regexItem->setCheckState(Qt::Unchecked);
170 regexItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
172 auto *csItem = new QTableWidgetItem("");
174 csItem->setCheckState(Qt::Checked);
176 csItem->setCheckState(Qt::Unchecked);
177 csItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
179 auto *enableItem = new QTableWidgetItem("");
181 enableItem->setCheckState(Qt::Checked);
183 enableItem->setCheckState(Qt::Unchecked);
184 enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
186 auto *chanNameItem = new QTableWidgetItem(chanName);
188 auto *senderItem = new QTableWidgetItem(sender);
190 int lastRow = ui.highlightTable->rowCount() - 1;
191 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem);
192 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::RegExColumn, regexItem);
193 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::CsColumn, csItem);
194 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::EnableColumn, enableItem);
195 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::SenderColumn, senderItem);
196 ui.highlightTable->setItem(lastRow, CoreHighlightSettingsPage::ChanColumn, chanNameItem);
199 ui.highlightTable->setCurrentItem(nameItem);
201 highlightList << HighlightRuleManager::HighlightRule(name, regex, cs, enable, false, sender, chanName);
204 void CoreHighlightSettingsPage::addNewIgnoredRow(bool enable, const QString &name, bool regex, bool cs,
205 const QString &sender, const QString &chanName, bool self)
207 ui.ignoredTable->setRowCount(ui.ignoredTable->rowCount() + 1);
209 auto *nameItem = new QTableWidgetItem(name);
211 auto *regexItem = new QTableWidgetItem("");
213 regexItem->setCheckState(Qt::Checked);
215 regexItem->setCheckState(Qt::Unchecked);
216 regexItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
218 auto *csItem = new QTableWidgetItem("");
220 csItem->setCheckState(Qt::Checked);
222 csItem->setCheckState(Qt::Unchecked);
223 csItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
225 auto *enableItem = new QTableWidgetItem("");
227 enableItem->setCheckState(Qt::Checked);
229 enableItem->setCheckState(Qt::Unchecked);
230 enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
232 auto *chanNameItem = new QTableWidgetItem(chanName);
234 auto *senderItem = new QTableWidgetItem(sender);
236 int lastRow = ui.ignoredTable->rowCount() - 1;
237 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::NameColumn, nameItem);
238 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::RegExColumn, regexItem);
239 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::CsColumn, csItem);
240 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::EnableColumn, enableItem);
241 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::SenderColumn, senderItem);
242 ui.ignoredTable->setItem(lastRow, CoreHighlightSettingsPage::ChanColumn, chanNameItem);
245 ui.ignoredTable->setCurrentItem(nameItem);
247 ignoredList << HighlightRuleManager::HighlightRule(name, regex, cs, enable, true, sender, chanName);
250 void CoreHighlightSettingsPage::removeSelectedHighlightRows()
252 QList<int> selectedRows;
253 QList<QTableWidgetItem *> selectedItemList = ui.highlightTable->selectedItems();
254 for (auto selectedItem : selectedItemList) {
255 selectedRows.append(selectedItem->row());
257 qSort(selectedRows.begin(), selectedRows.end(), qGreater<int>());
259 for (auto row : selectedRows) {
260 if (row != lastRow) {
261 ui.highlightTable->removeRow(row);
262 highlightList.removeAt(row);
268 void CoreHighlightSettingsPage::removeSelectedIgnoredRows()
270 QList<int> selectedRows;
271 QList<QTableWidgetItem *> selectedItemList = ui.ignoredTable->selectedItems();
272 for (auto selectedItem : selectedItemList) {
273 selectedRows.append(selectedItem->row());
275 qSort(selectedRows.begin(), selectedRows.end(), qGreater<int>());
277 for (auto row : selectedRows) {
278 if (row != lastRow) {
279 ui.ignoredTable->removeRow(row);
280 ignoredList.removeAt(row);
286 void CoreHighlightSettingsPage::selectHighlightRow(QTableWidgetItem *item)
288 int row = item->row();
289 bool selected = item->isSelected();
291 ->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, CoreHighlightSettingsPage::ColumnCount - 1),
295 void CoreHighlightSettingsPage::selectIgnoredRow(QTableWidgetItem *item)
297 int row = item->row();
298 bool selected = item->isSelected();
300 ->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, CoreHighlightSettingsPage::ColumnCount - 1),
304 void CoreHighlightSettingsPage::emptyHighlightTable()
306 // ui.highlight and highlightList should have the same size, but just to make sure.
307 if (ui.highlightTable->rowCount() != highlightList.size()) {
308 qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!";
310 ui.highlightTable->clearContents();
311 highlightList.clear();
314 void CoreHighlightSettingsPage::emptyIgnoredTable()
316 // ui.highlight and highlightList should have the same size, but just to make sure.
317 if (ui.ignoredTable->rowCount() != ignoredList.size()) {
318 qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!";
320 ui.ignoredTable->clearContents();
324 void CoreHighlightSettingsPage::highlightTableChanged(QTableWidgetItem *item)
326 if (item->row() + 1 > highlightList.size())
329 auto highlightRule = highlightList.value(item->row());
332 switch (item->column()) {
333 case CoreHighlightSettingsPage::EnableColumn:
334 highlightRule.isEnabled = (item->checkState() == Qt::Checked);
336 case CoreHighlightSettingsPage::NameColumn:
337 if (item->text() == "")
338 item->setText(tr("this shouldn't be empty"));
339 highlightRule.name = item->text();
341 case CoreHighlightSettingsPage::RegExColumn:
342 highlightRule.isRegEx = (item->checkState() == Qt::Checked);
344 case CoreHighlightSettingsPage::CsColumn:
345 highlightRule.isCaseSensitive = (item->checkState() == Qt::Checked);
347 case CoreHighlightSettingsPage::SenderColumn:
348 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
350 highlightRule.sender = item->text();
352 case CoreHighlightSettingsPage::ChanColumn:
353 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
355 highlightRule.chanName = item->text();
358 highlightList[item->row()] = highlightRule;
359 emit widgetHasChanged();
362 void CoreHighlightSettingsPage::ignoredTableChanged(QTableWidgetItem *item)
364 if (item->row() + 1 > ignoredList.size())
367 auto ignoredRule = ignoredList.value(item->row());
370 switch (item->column()) {
371 case CoreHighlightSettingsPage::EnableColumn:
372 ignoredRule.isEnabled = (item->checkState() == Qt::Checked);
374 case CoreHighlightSettingsPage::NameColumn:
375 if (item->text() == "")
376 item->setText(tr("this shouldn't be empty"));
377 ignoredRule.name = item->text();
379 case CoreHighlightSettingsPage::RegExColumn:
380 ignoredRule.isRegEx = (item->checkState() == Qt::Checked);
382 case CoreHighlightSettingsPage::CsColumn:
383 ignoredRule.isCaseSensitive = (item->checkState() == Qt::Checked);
385 case CoreHighlightSettingsPage::SenderColumn:
386 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
388 ignoredRule.sender = item->text();
390 case CoreHighlightSettingsPage::ChanColumn:
391 if (!item->text().isEmpty() && item->text().trimmed().isEmpty())
393 ignoredRule.chanName = item->text();
396 ignoredList[item->row()] = ignoredRule;
397 emit widgetHasChanged();
400 void CoreHighlightSettingsPage::load()
402 emptyHighlightTable();
405 auto ruleManager = Client::highlightRuleManager();
407 for (auto &rule : ruleManager->highlightRuleList()) {
408 if (rule.isInverse) {
409 addNewIgnoredRow(rule.isEnabled,
412 rule.isCaseSensitive,
417 addNewHighlightRow(rule.isEnabled, rule.name, rule.isRegEx, rule.isCaseSensitive, rule.sender,
422 int highlightNickType = ruleManager->highlightNick();
423 ui.highlightNicksComboBox->setCurrentIndex(ui.highlightNicksComboBox->findData(QVariant(highlightNickType)));
424 ui.nicksCaseSensitive->setChecked(ruleManager->nicksCaseSensitive());
426 setChangedState(false);
433 void CoreHighlightSettingsPage::save()
441 auto ruleManager = Client::highlightRuleManager();
442 if (ruleManager == nullptr)
445 auto clonedManager = HighlightRuleManager();
446 clonedManager.fromVariantMap(ruleManager->toVariantMap());
447 clonedManager.clear();
449 for (auto &rule : highlightList) {
450 clonedManager.addHighlightRule(rule.name, rule.isRegEx, rule.isCaseSensitive, rule.isEnabled, false,
451 rule.sender, rule.chanName);
454 for (auto &rule : ignoredList) {
455 clonedManager.addHighlightRule(rule.name, rule.isRegEx, rule.isCaseSensitive, rule.isEnabled, true,
456 rule.sender, rule.chanName);
459 auto highlightNickType = ui.highlightNicksComboBox->itemData(ui.highlightNicksComboBox->currentIndex()).value<int>();
461 clonedManager.setHighlightNick(HighlightRuleManager::HighlightNickType(highlightNickType));
462 clonedManager.setNicksCaseSensitive(ui.nicksCaseSensitive->isChecked());
464 ruleManager->requestUpdate(clonedManager.toVariantMap());
465 setChangedState(false);
469 void CoreHighlightSettingsPage::widgetHasChanged()
471 setChangedState(true);