1/***************************************************************************
2 * Copyright (C) 2005-2014 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 General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
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 General Public License for more details. *
14 * *
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 ***************************************************************************/
20
21#include "ignorelistsettingspage.h"
22
23#include <QHeaderView>
24#include <QItemSelectionModel>
25#include <QModelIndex>
26#include <QPainter>
27#include <QMessageBox>
28#include <QString>
29#include <QEvent>
30#include <QDebug>
31#include "iconloader.h"
32
33IgnoreListSettingsPage::IgnoreListSettingsPage(QWidget *parent)
34 : SettingsPage(tr("IRC"), tr("Ignore List"), parent)
35{
36 ui.setupUi(this);
37 _delegate = new IgnoreListDelegate(ui.ignoreListView);
38 ui.newIgnoreRuleButton->setIcon(SmallIcon("list-add"));
39 ui.deleteIgnoreRuleButton->setIcon(SmallIcon("edit-delete"));
40 ui.editIgnoreRuleButton->setIcon(SmallIcon("configure"));
41
42 ui.ignoreListView->setSelectionBehavior(QAbstractItemView::SelectRows);
43 ui.ignoreListView->setSelectionMode(QAbstractItemView::SingleSelection);
44 ui.ignoreListView->setAlternatingRowColors(true);
45 ui.ignoreListView->setTabKeyNavigation(false);
46 ui.ignoreListView->setModel(&_ignoreListModel);
47 // ui.ignoreListView->setEditTriggers(QAbstractItemView::NoEditTriggers);
48
49 // ui.ignoreListView->setSortingEnabled(true);
50 ui.ignoreListView->verticalHeader()->hide();
51 ui.ignoreListView->hideColumn(1);
52 ui.ignoreListView->resizeColumnToContents(0);
53 ui.ignoreListView->horizontalHeader()->setStretchLastSection(true);
54 ui.ignoreListView->setItemDelegateForColumn(0, _delegate);
55 ui.ignoreListView->viewport()->setAttribute(Qt::WA_Hover);
56 ui.ignoreListView->viewport()->setMouseTracking(true);
57
58 connect(ui.ignoreListView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT(selectionChanged(const QItemSelection &, const QItemSelection &)));
59 connect(ui.newIgnoreRuleButton, SIGNAL(clicked()), this, SLOT(newIgnoreRule()));
60 connect(ui.deleteIgnoreRuleButton, SIGNAL(clicked()), this, SLOT(deleteSelectedIgnoreRule()));
61 connect(ui.editIgnoreRuleButton, SIGNAL(clicked()), this, SLOT(editSelectedIgnoreRule()));
62 connect(&_ignoreListModel, SIGNAL(configChanged(bool)), this, SLOT(setChangedState(bool)));
63 connect(&_ignoreListModel, SIGNAL(modelReady(bool)), this, SLOT(enableDialog(bool)));
64
65 enableDialog(_ignoreListModel.isReady());
66}
67
68
69IgnoreListSettingsPage::~IgnoreListSettingsPage()
70{
71 delete _delegate;
72}
73
74
75void IgnoreListSettingsPage::load()
76{
77 if (_ignoreListModel.configChanged())
78 _ignoreListModel.revert();
79 ui.ignoreListView->selectionModel()->reset();
80 ui.editIgnoreRuleButton->setEnabled(false);
81}
82
83
84void IgnoreListSettingsPage::defaults()
85{
86 _ignoreListModel.loadDefaults();
87}
88
89
90void IgnoreListSettingsPage::save()
91{
92 if (_ignoreListModel.configChanged()) {
93 _ignoreListModel.commit();
94 }
95 ui.ignoreListView->selectionModel()->reset();
96 ui.editIgnoreRuleButton->setEnabled(false);
97}
98
99
100void IgnoreListSettingsPage::enableDialog(bool enabled)
101{
102 ui.newIgnoreRuleButton->setEnabled(enabled);
103 setEnabled(enabled);
104}
105
106
107void IgnoreListSettingsPage::selectionChanged(const QItemSelection &selection, const QItemSelection &)
108{
109 bool state = !selection.isEmpty();
110 ui.deleteIgnoreRuleButton->setEnabled(state);
111 ui.editIgnoreRuleButton->setEnabled(state);
112}
113
114
115void IgnoreListSettingsPage::deleteSelectedIgnoreRule()
116{
117 if (!ui.ignoreListView->selectionModel()->hasSelection())
118 return;
119
120 _ignoreListModel.removeIgnoreRule(ui.ignoreListView->selectionModel()->selectedIndexes()[0].row());
121}
122
123
124void IgnoreListSettingsPage::newIgnoreRule(QString rule)
125{
126 IgnoreListManager::IgnoreListItem newItem = IgnoreListManager::IgnoreListItem();
127 newItem.strictness = IgnoreListManager::SoftStrictness;
128 newItem.scope = IgnoreListManager::GlobalScope;
129 newItem.isRegEx = false;
130 newItem.isActive = true;
131
132 bool enableOkButton = false;
133 if (!rule.isEmpty()) {
134 // we're called from contextmenu
135 newItem.ignoreRule = rule;
136 enableOkButton = true;
137 }
138
139 IgnoreListEditDlg *dlg = new IgnoreListEditDlg(newItem, this, enableOkButton);
140 dlg->enableOkButton(enableOkButton);
141 while (dlg->exec() == QDialog::Accepted) {
142 if (!_ignoreListModel.newIgnoreRule(dlg->ignoreListItem())) {
143 if (QMessageBox::warning(this,
144 tr("Rule already exists"),
145 tr("There is already a rule\n\"%1\"\nPlease choose another rule.")
146 .arg(dlg->ignoreListItem().ignoreRule),
147 QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok)
148 == QMessageBox::Cancel)
149 break;
150
151 IgnoreListManager::IgnoreListItem item = dlg->ignoreListItem();
152 delete dlg;
153 dlg = new IgnoreListEditDlg(item, this);
154 }
155 else {
156 break;
157 }
158 }
159 dlg->deleteLater();
160}
161
162
163void IgnoreListSettingsPage::editSelectedIgnoreRule()
164{
165 if (!ui.ignoreListView->selectionModel()->hasSelection())
166 return;
167 int row = ui.ignoreListView->selectionModel()->selectedIndexes()[0].row();
168 IgnoreListEditDlg dlg(_ignoreListModel.ignoreListItemAt(row), this);
169 dlg.setAttribute(Qt::WA_DeleteOnClose, false);
170 if (dlg.exec() == QDialog::Accepted) {
171 _ignoreListModel.setIgnoreListItemAt(row, dlg.ignoreListItem());
172 }
173}
174
175
176void IgnoreListSettingsPage::editIgnoreRule(const QString &ignoreRule)
177{
178 ui.ignoreListView->selectionModel()->select(_ignoreListModel.indexOf(ignoreRule), QItemSelectionModel::Select);
179 if (ui.ignoreListView->selectionModel()->hasSelection()) // && ui.ignoreListView->selectionModel()->selectedIndexes()[0].row() != -1)
180 editSelectedIgnoreRule();
181 else
182 newIgnoreRule(ignoreRule);
183}
184
185
186/*
187 IgnoreListDelegate
188*/
189void IgnoreListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
190{
191 if (index.column() == 0) {
192 QStyle *style = QApplication::style();
193 if (option.state & QStyle::State_Selected)
194 painter->fillRect(option.rect, option.palette.highlight());
195
196 QStyleOptionButton opts;
197 opts.direction = option.direction;
198 opts.rect = option.rect;
199 opts.rect.moveLeft(option.rect.center().rx()-10);
200 opts.state = option.state;
201 opts.state |= index.data().toBool() ? QStyle::State_On : QStyle::State_Off;
202 style->drawControl(QStyle::CE_CheckBox, &opts, painter);
203 }
204 else
205 QStyledItemDelegate::paint(painter, option, index);
206}
207
208
209// provide interactivity for the checkboxes
210bool IgnoreListDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
211 const QStyleOptionViewItem &option, const QModelIndex &index)
212{
213 Q_UNUSED(option)
214 switch (event->type()) {
215 case QEvent::MouseButtonRelease:
216 model->setData(index, !index.data().toBool());
217 return true;
218 // don't show the default editor for the column
219 case QEvent::MouseButtonDblClick:
220 return true;
221 default:
222 return false;
223 }
224}
225
226
227/*
228 IgnoreListEditDlg
229*/
230IgnoreListEditDlg::IgnoreListEditDlg(const IgnoreListManager::IgnoreListItem &item, QWidget *parent, bool enabled)
231 : QDialog(parent), _ignoreListItem(item), _hasChanged(enabled)
232{
233 ui.setupUi(this);
234 setAttribute(Qt::WA_DeleteOnClose, false);
235 setModal(true);
236 // FIXME patch out the bugger completely if it's good without it
237 ui.isActiveCheckBox->hide();
238
239 // setup buttongroups
240 // this could be moved to .ui file with qt4.5
241 _typeButtonGroup.addButton(ui.senderTypeButton, 0);
242 _typeButtonGroup.addButton(ui.messageTypeButton, 1);
243 _typeButtonGroup.addButton(ui.ctcpTypeButton, 2);
244 _strictnessButtonGroup.addButton(ui.dynamicStrictnessButton, 0);
245 _strictnessButtonGroup.addButton(ui.permanentStrictnessButton, 1);
246 _scopeButtonGroup.addButton(ui.globalScopeButton, 0);
247 _scopeButtonGroup.addButton(ui.networkScopeButton, 1);
248 _scopeButtonGroup.addButton(ui.channelScopeButton, 2);
249
250 ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
251
252 ui.ignoreRuleLineEdit->setText(item.ignoreRule);
253
254 if (item.type == IgnoreListManager::MessageIgnore)
255 ui.messageTypeButton->setChecked(true);
256 else if (item.type == IgnoreListManager::CtcpIgnore)
257 ui.ctcpTypeButton->setChecked(true);
258 else
259 ui.senderTypeButton->setChecked(true);
260
261 ui.isRegExCheckBox->setChecked(item.isRegEx);
262 ui.isActiveCheckBox->setChecked(item.isActive);
263
264 if (item.strictness == IgnoreListManager::HardStrictness)
265 ui.permanentStrictnessButton->setChecked(true);
266 else
267 ui.dynamicStrictnessButton->setChecked(true);
268
269 switch (item.scope) {
270 case IgnoreListManager::NetworkScope:
271 ui.networkScopeButton->setChecked(true);
272 ui.scopeRuleTextEdit->setEnabled(true);
273 break;
274 case IgnoreListManager::ChannelScope:
275 ui.channelScopeButton->setChecked(true);
276 ui.scopeRuleTextEdit->setEnabled(true);
277 break;
278 default:
279 ui.globalScopeButton->setChecked(true);
280 ui.scopeRuleTextEdit->setEnabled(false);
281 }
282
283 if (item.scope == IgnoreListManager::GlobalScope)
284 ui.scopeRuleTextEdit->clear();
285 else
286 ui.scopeRuleTextEdit->setPlainText(item.scopeRule);
287
288 connect(ui.ignoreRuleLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(widgetHasChanged()));
289 connect(ui.scopeRuleTextEdit, SIGNAL(textChanged()), this, SLOT(widgetHasChanged()));
290 connect(&_typeButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(widgetHasChanged()));
291 connect(&_strictnessButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(widgetHasChanged()));
292 connect(&_scopeButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(widgetHasChanged()));
293 connect(ui.isRegExCheckBox, SIGNAL(stateChanged(int)), this, SLOT(widgetHasChanged()));
294 connect(ui.isActiveCheckBox, SIGNAL(stateChanged(int)), this, SLOT(widgetHasChanged()));
295
296 connect(ui.buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(aboutToAccept()));
297 widgetHasChanged();
298}
299
300
301void IgnoreListEditDlg::widgetHasChanged()
302{
303 if (ui.messageTypeButton->isChecked())
304 _clonedIgnoreListItem.type = IgnoreListManager::MessageIgnore;
305 else if (ui.ctcpTypeButton->isChecked())
306 _clonedIgnoreListItem.type = IgnoreListManager::CtcpIgnore;
307 else
308 _clonedIgnoreListItem.type = IgnoreListManager::SenderIgnore;
309
310 if (ui.permanentStrictnessButton->isChecked())
311 _clonedIgnoreListItem.strictness = IgnoreListManager::HardStrictness;
312 else
313 _clonedIgnoreListItem.strictness = IgnoreListManager::SoftStrictness;
314
315 if (ui.networkScopeButton->isChecked()) {
316 _clonedIgnoreListItem.scope = IgnoreListManager::NetworkScope;
317 ui.scopeRuleTextEdit->setEnabled(true);
318 }
319 else if (ui.channelScopeButton->isChecked()) {
320 _clonedIgnoreListItem.scope = IgnoreListManager::ChannelScope;
321 ui.scopeRuleTextEdit->setEnabled(true);
322 }
323 else {
324 _clonedIgnoreListItem.scope = IgnoreListManager::GlobalScope;
325 ui.scopeRuleTextEdit->setEnabled(false);
326 }
327
328 if (_clonedIgnoreListItem.scope == IgnoreListManager::GlobalScope) {
329 _clonedIgnoreListItem.scopeRule = QString();
330 }
331 else {
332 QStringList text = ui.scopeRuleTextEdit->toPlainText().split(";", QString::SkipEmptyParts);
333 QStringList::iterator it = text.begin();
334 while (it != text.end()) {
335 *it = it->trimmed();
336 ++it;
337 }
338
339 _clonedIgnoreListItem.scopeRule = text.join("; ");
340 }
341
342 _clonedIgnoreListItem.ignoreRule = ui.ignoreRuleLineEdit->text();
343 _clonedIgnoreListItem.isRegEx = ui.isRegExCheckBox->isChecked();
344 _clonedIgnoreListItem.isActive = ui.isActiveCheckBox->isChecked();
345
346 if (!_clonedIgnoreListItem.ignoreRule.isEmpty() && _clonedIgnoreListItem != _ignoreListItem)
347 _hasChanged = true;
348 else
349 _hasChanged = false;
350 ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(_hasChanged);
351}
352
353
354void IgnoreListEditDlg::enableOkButton(bool state)
355{
356 ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(state);
357}
358