Chan -> Channel, it's just nicer in user-visible strings
[quassel.git] / src / qtui / settingspages / highlightsettingspage.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-09 by the Quassel Project                          *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU Highlight Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
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 Highlight Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU Highlight Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20
21 #include "highlightsettingspage.h"
22
23 #include "qtui.h"
24 #include "uisettings.h"
25
26 #include <QHeaderView>
27
28
29 HighlightSettingsPage::HighlightSettingsPage(QWidget *parent)
30   : SettingsPage(tr("Interface"), tr("Highlight"), parent) {
31   ui.setupUi(this);
32   ui.highlightTable->verticalHeader()->hide();
33   ui.highlightTable->setShowGrid(false);
34
35   ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::RegExColumn)->setToolTip("<b>RegEx</b>: This option determines if the highlight rule should be interpreted as a <b>regular expression</b> or just as a keyword.");
36   ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::RegExColumn)->setWhatsThis("<b>RegEx</b>: This option determines if the highlight rule should be interpreted as a <b>regular expression</b> or just as a keyword.");
37
38   ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::CsColumn)->setToolTip("<b>CS</b>: This option determines if the highlight rule should be interpreted <b>case sensitive</b>.");
39   ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::CsColumn)->setWhatsThis("<b>CS</b>: This option determines if the highlight rule should be interpreted <b>case sensitive</b>.");
40
41   ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::ChanColumn)->setToolTip("<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.");
42   ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::ChanColumn)->setWhatsThis("<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.");
43
44   ui.highlightTable->horizontalHeader()->setResizeMode(HighlightSettingsPage::NameColumn, QHeaderView::Stretch);
45   ui.highlightTable->horizontalHeader()->setResizeMode(HighlightSettingsPage::RegExColumn, QHeaderView::ResizeToContents);
46   ui.highlightTable->horizontalHeader()->setResizeMode(HighlightSettingsPage::CsColumn, QHeaderView::ResizeToContents);
47   ui.highlightTable->horizontalHeader()->setResizeMode(HighlightSettingsPage::EnableColumn, QHeaderView::ResizeToContents);
48   ui.highlightTable->horizontalHeader()->setResizeMode(HighlightSettingsPage::ChanColumn, QHeaderView::ResizeToContents);
49
50   connect(ui.add, SIGNAL(clicked(bool)), this, SLOT(addNewRow()));
51   connect(ui.remove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedRows()));
52   //TODO: search for a better signal (one that emits everytime a selection has been changed for one item)
53   connect(ui.highlightTable, SIGNAL(itemClicked(QTableWidgetItem *)), this, SLOT(selectRow(QTableWidgetItem *)));
54
55   connect(ui.highlightAllNicks, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
56   connect(ui.highlightCurrentNick, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
57   connect(ui.highlightNoNick, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
58   connect(ui.nicksCaseSensitive, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
59   connect(ui.add, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
60   connect(ui.remove, SIGNAL(clicked()), this, SLOT(widgetHasChanged()));
61   connect(ui.highlightTable, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(tableChanged(QTableWidgetItem *)));
62 }
63
64 bool HighlightSettingsPage::hasDefaults() const {
65   return true;
66 }
67
68 void HighlightSettingsPage::defaults() {
69   ui.highlightCurrentNick->setChecked(true);
70   ui.nicksCaseSensitive->setChecked(false);
71   emptyTable();
72
73   widgetHasChanged();
74 }
75
76 void HighlightSettingsPage::addNewRow(QString name, bool regex, bool cs, bool enable, QString chanName, bool self) {
77   ui.highlightTable->setRowCount(ui.highlightTable->rowCount()+1);
78
79   QTableWidgetItem *nameItem = new QTableWidgetItem(name);
80
81   QTableWidgetItem *regexItem = new QTableWidgetItem("");
82   if(regex)
83     regexItem->setCheckState(Qt::Checked);
84   else
85     regexItem->setCheckState(Qt::Unchecked);
86   regexItem->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
87
88   QTableWidgetItem *csItem = new QTableWidgetItem("");
89   if(cs)
90     csItem->setCheckState(Qt::Checked);
91   else
92     csItem->setCheckState(Qt::Unchecked);
93   csItem->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
94
95   QTableWidgetItem *enableItem = new QTableWidgetItem("");
96   if(enable)
97     enableItem->setCheckState(Qt::Checked);
98   else
99     enableItem->setCheckState(Qt::Unchecked);
100   enableItem->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
101
102   QTableWidgetItem *chanNameItem = new QTableWidgetItem(chanName);
103
104   int lastRow = ui.highlightTable->rowCount()-1;
105   ui.highlightTable->setItem(lastRow, HighlightSettingsPage::NameColumn, nameItem);
106   ui.highlightTable->setItem(lastRow, HighlightSettingsPage::RegExColumn, regexItem);
107   ui.highlightTable->setItem(lastRow, HighlightSettingsPage::CsColumn, csItem);
108   ui.highlightTable->setItem(lastRow, HighlightSettingsPage::EnableColumn, enableItem);
109   ui.highlightTable->setItem(lastRow, HighlightSettingsPage::ChanColumn, chanNameItem);
110
111   if(!self)
112     ui.highlightTable->setCurrentItem(nameItem);
113
114   QVariantMap highlightRule;
115   highlightRule["Name"] = name;
116   highlightRule["RegEx"] = regex;
117   highlightRule["CS"] = cs;
118   highlightRule["Enable"] = enable;
119   highlightRule["Channel"] = chanName;
120
121   highlightList.append(highlightRule);
122 }
123
124 void HighlightSettingsPage::removeSelectedRows() {
125   QList<int> selectedRows;
126   QList<QTableWidgetItem *> selectedItemList = ui.highlightTable->selectedItems();
127   foreach(QTableWidgetItem *selectedItem, selectedItemList) {
128     selectedRows.append(selectedItem->row());
129   }
130   qSort(selectedRows.begin(), selectedRows.end(), qGreater<int>());
131   int lastRow = -1;
132   foreach(int row, selectedRows) {
133     if(row != lastRow) {
134       ui.highlightTable->removeRow(row);
135       highlightList.removeAt(row);
136     }
137     lastRow = row;
138   }
139 }
140
141 void HighlightSettingsPage::selectRow(QTableWidgetItem *item) {
142   int row = item->row();
143   bool selected = item->isSelected();
144   ui.highlightTable->setRangeSelected(QTableWidgetSelectionRange(row, 0, row, HighlightSettingsPage::ColumnCount-1), selected);
145 }
146
147 void HighlightSettingsPage::emptyTable() {
148   // ui.highlight and highlightList should have the same size, but just to make sure.
149   if(ui.highlightTable->rowCount() != highlightList.size()) {
150     qDebug() << "something is wrong: ui.highlight and highlightList don't have the same size!";
151   }
152   while(ui.highlightTable->rowCount()) {
153     ui.highlightTable->removeRow(0);
154   }
155   while(highlightList.size()) {
156         highlightList.removeLast();
157   }
158 }
159
160 void HighlightSettingsPage::tableChanged(QTableWidgetItem *item) {
161   if(item->row()+1 > highlightList.size())
162     return;
163
164   QVariantMap highlightRule = highlightList.value(item->row()).toMap();
165
166   switch(item->column())
167   {
168     case HighlightSettingsPage::NameColumn:
169       if(item->text() == "")
170         item->setText(tr("this shouldn't be empty"));
171       highlightRule["Name"] = item->text();
172       break;
173     case HighlightSettingsPage::RegExColumn:
174       highlightRule["RegEx"] = (item->checkState() == Qt::Checked);
175       break;
176     case HighlightSettingsPage::CsColumn:
177       highlightRule["CS"] = (item->checkState() == Qt::Checked);
178       break;
179     case HighlightSettingsPage::EnableColumn:
180       highlightRule["Enable"] = (item->checkState() == Qt::Checked);
181       break;
182     case HighlightSettingsPage::ChanColumn:
183       if(!item->text().isEmpty() && item->text().trimmed().isEmpty())
184         item->setText("");
185       highlightRule["Channel"] = item->text();
186       break;
187   }
188   highlightList[item->row()] = highlightRule;
189   emit widgetHasChanged();
190 }
191
192 void HighlightSettingsPage::load() {
193   NotificationSettings notificationSettings;
194
195   emptyTable();
196
197   foreach(QVariant highlight, notificationSettings.highlightList()) {
198     QVariantMap highlightRule = highlight.toMap();
199     QString name = highlightRule["Name"].toString();
200     bool regex = highlightRule["RegEx"].toBool();
201     bool cs = highlightRule["CS"].toBool();
202     bool enable = highlightRule["Enable"].toBool();
203     QString chanName = highlightRule["Channel"].toString();
204
205     addNewRow(name, regex, cs, enable, chanName, true);
206   }
207
208   switch(notificationSettings.highlightNick())
209   {
210     case NotificationSettings::NoNick:
211       ui.highlightNoNick->setChecked(true);
212       break;
213     case NotificationSettings::CurrentNick:
214       ui.highlightCurrentNick->setChecked(true);
215       break;
216     case NotificationSettings::AllNicks:
217       ui.highlightAllNicks->setChecked(true);
218       break;
219   }
220   ui.nicksCaseSensitive->setChecked(notificationSettings.nicksCaseSensitive());
221
222   setChangedState(false);
223 }
224
225 void HighlightSettingsPage::save() {
226   NotificationSettings notificationSettings;
227   notificationSettings.setHighlightList(highlightList);
228
229   NotificationSettings::HighlightNickType highlightNickType;
230   if(ui.highlightNoNick->isChecked())
231     highlightNickType = NotificationSettings::NoNick;
232   if(ui.highlightCurrentNick->isChecked())
233     highlightNickType = NotificationSettings::CurrentNick;
234   if(ui.highlightAllNicks->isChecked())
235     highlightNickType = NotificationSettings::AllNicks;
236
237   notificationSettings.setHighlightNick(highlightNickType);
238   notificationSettings.setNicksCaseSensitive(ui.nicksCaseSensitive->isChecked());
239
240   load();
241   setChangedState(false);
242 }
243
244 void HighlightSettingsPage::widgetHasChanged() {
245   bool changed = testHasChanged();
246   if(changed != hasChanged()) setChangedState(changed);
247 }
248
249 bool HighlightSettingsPage::testHasChanged() {
250   NotificationSettings notificationSettings;
251
252   NotificationSettings::HighlightNickType highlightNickType;
253   if(ui.highlightNoNick->isChecked())
254     highlightNickType = NotificationSettings::NoNick;
255   if(ui.highlightCurrentNick->isChecked())
256     highlightNickType = NotificationSettings::CurrentNick;
257   if(ui.highlightAllNicks->isChecked())
258     highlightNickType = NotificationSettings::AllNicks;
259
260   if(notificationSettings.highlightNick() != highlightNickType) return true;
261   if(notificationSettings.nicksCaseSensitive() != ui.nicksCaseSensitive->isChecked()) return true;
262
263   if(notificationSettings.highlightList() != highlightList) return true;
264
265   return false;
266 }