1 /***************************************************************************
2 * Copyright (C) 2005-09 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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include "bufferviewsettingspage.h"
23 #include <QMessageBox>
26 #include "iconloader.h"
28 #include "bufferviewconfig.h"
29 #include "bufferviewfilter.h"
30 #include "buffermodel.h"
31 #include "clientbufferviewmanager.h"
32 #include "networkmodel.h"
35 BufferViewSettingsPage::BufferViewSettingsPage(QWidget *parent)
36 : SettingsPage(tr("Interface"), tr("Custom Chat Lists"), parent),
37 _ignoreWidgetChanges(false),
38 _useBufferViewHint(false),
42 ui.renameBufferView->setIcon(SmallIcon("edit-rename"));
43 ui.addBufferView->setIcon(SmallIcon("list-add"));
44 ui.deleteBufferView->setIcon(SmallIcon("edit-delete"));
48 ui.bufferViewList->setSortingEnabled(true);
49 ui.settingsGroupBox->setEnabled(false);
50 ui.bufferViewPreview->setEnabled(false);
52 coreConnectionStateChanged(Client::isConnected()); // need a core connection!
53 connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool)));
54 connect(ui.bufferViewList->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
55 this, SLOT(bufferViewSelectionChanged(const QItemSelection &, const QItemSelection &)));
57 connect(ui.onlyStatusBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
58 connect(ui.onlyChannelBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
59 connect(ui.onlyQueryBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
60 connect(ui.addNewBuffersAutomatically, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
61 connect(ui.sortAlphabetically, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
62 connect(ui.hideInactiveBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
63 connect(ui.networkSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
64 connect(ui.minimumActivitySelector, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
66 connect(ui.networkSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(enableStatusBuffers(int)));
69 BufferViewSettingsPage::~BufferViewSettingsPage() {
73 void BufferViewSettingsPage::reset() {
74 ui.bufferViewList->clear();
75 ui.deleteBufferView->setEnabled(false);
77 QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIter = _changedBufferViews.begin();
78 QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIterEnd = _changedBufferViews.end();
79 BufferViewConfig *config;
80 while(changedConfigIter != changedConfigIterEnd) {
81 config = changedConfigIter.value();
82 changedConfigIter = _changedBufferViews.erase(changedConfigIter);
83 config->deleteLater();
86 QList<BufferViewConfig *>::iterator newConfigIter = _newBufferViews.begin();
87 QList<BufferViewConfig *>::iterator newConfigIterEnd = _newBufferViews.end();
88 while(newConfigIter != newConfigIterEnd) {
89 config = *newConfigIter;
90 newConfigIter = _newBufferViews.erase(newConfigIter);
91 config->deleteLater();
94 _deleteBufferViews.clear();
96 _useBufferViewHint = false;
98 setChangedState(false);
101 void BufferViewSettingsPage::load() {
102 bool useBufferViewHint = _useBufferViewHint;
103 int bufferViewHint = _bufferViewHint;
106 if(!Client::bufferViewManager())
109 const QList<BufferViewConfig *> bufferViewConfigs = Client::bufferViewManager()->bufferViewConfigs();
110 foreach(BufferViewConfig *bufferViewConfig, bufferViewConfigs) {
111 addBufferView(bufferViewConfig);
114 _ignoreWidgetChanges = true;
115 // load network selector
116 ui.networkSelector->clear();
117 ui.networkSelector->addItem(tr("All"));
118 ui.networkSelector->setItemData(0, qVariantFromValue<NetworkId>(NetworkId()));
120 foreach(NetworkId netId, Client::networkIds()) {
121 net = Client::network(netId);
122 ui.networkSelector->addItem(net->networkName());
123 ui.networkSelector->setItemData(ui.networkSelector->count() - 1, qVariantFromValue<NetworkId>(net->networkId()));
125 _ignoreWidgetChanges = false;
128 if(!useBufferViewHint || !selectBufferViewById(bufferViewHint))
129 ui.bufferViewList->setCurrentRow(0);
132 void BufferViewSettingsPage::save() {
135 BufferViewConfig *currentConfig = bufferView(ui.bufferViewList->currentRow());
137 _useBufferViewHint = true;
138 _bufferViewHint = currentConfig->bufferViewId();
141 QVariantList newConfigs;
142 QVariantList deleteConfigs;
143 QVariantList changedConfigs;
145 foreach(int bufferId, _deleteBufferViews) {
146 deleteConfigs << bufferId;
148 _deleteBufferViews.clear();
149 if(Client::bufferViewManager()) {
150 Client::bufferViewManager()->requestDeleteBufferViews(deleteConfigs);
153 QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIter = _changedBufferViews.begin();
154 QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIterEnd = _changedBufferViews.end();
155 BufferViewConfig *config, *changedConfig;
156 while(changedConfigIter != changedConfigIterEnd) {
157 config = changedConfigIter.key();
158 changedConfig = changedConfigIter.value();
159 changedConfigIter = _changedBufferViews.erase(changedConfigIter);
160 config->requestUpdate(changedConfig->toVariantMap());
161 changedConfig->deleteLater();
164 QList<BufferViewConfig *>::iterator newConfigIter = _newBufferViews.begin();
165 QList<BufferViewConfig *>::iterator newConfigIterEnd = _newBufferViews.end();
166 while(newConfigIter != newConfigIterEnd) {
167 config = *newConfigIter;
168 newConfigIter = _newBufferViews.erase(newConfigIter);
169 newConfigs << config->toVariantMap();
170 config->deleteLater();
172 if(Client::bufferViewManager()) {
173 Client::bufferViewManager()->requestCreateBufferViews(newConfigs);
180 void BufferViewSettingsPage::coreConnectionStateChanged(bool state) {
184 connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigAdded(int)), this, SLOT(addBufferView(int)));
190 void BufferViewSettingsPage::addBufferView(BufferViewConfig *config) {
191 QListWidgetItem *item = new QListWidgetItem(config->bufferViewName(), ui.bufferViewList);
192 item->setData(Qt::UserRole, qVariantFromValue<QObject *>(qobject_cast<QObject *>(config)));
193 connect(config, SIGNAL(updatedRemotely()), this, SLOT(updateBufferView()));
194 connect(config, SIGNAL(destroyed()), this, SLOT(bufferViewDeleted()));
195 ui.deleteBufferView->setEnabled(ui.bufferViewList->count() > 1);
198 void BufferViewSettingsPage::addBufferView(int bufferViewId) {
199 // we are informed about a new bufferview from Client::bufferViewManager()
200 Q_ASSERT(Client::bufferViewManager());
201 addBufferView(Client::bufferViewManager()->bufferViewConfig(bufferViewId));
202 selectBufferViewById(bufferViewId);
205 void BufferViewSettingsPage::bufferViewDeleted() {
206 BufferViewConfig *config = static_cast<BufferViewConfig *>(sender());
208 for(int i = 0; i < ui.bufferViewList->count(); i++) {
209 obj = ui.bufferViewList->item(i)->data(Qt::UserRole).value<QObject *>();
210 if(config == static_cast<BufferViewConfig *>(obj)) {
211 QListWidgetItem *item = ui.bufferViewList->takeItem(i);
216 ui.deleteBufferView->setEnabled(ui.bufferViewList->count() > 1);
219 void BufferViewSettingsPage::newBufferView(const QString &bufferViewName) {
220 // id's of newly created bufferviews are negative (-1, -2... -n)
221 int fakeId = -1 * (_newBufferViews.count() + 1);
222 BufferViewConfig *config = new BufferViewConfig(fakeId);
223 config->setBufferViewName(bufferViewName);
224 config->setInitialized();
225 QList<BufferId> bufferIds;
226 if(config->addNewBuffersAutomatically()) {
227 if(config->sortAlphabetically()) {
228 bufferIds = Client::networkModel()->allBufferIdsSorted();
230 bufferIds = Client::networkModel()->allBufferIds();
232 config->setProperty("OriginalBufferList", toVariantList<BufferId>(bufferIds));
235 config->initSetBufferList(bufferIds);
237 _newBufferViews << config;
238 addBufferView(config);
239 ui.bufferViewList->setCurrentRow(listPos(config));
242 int BufferViewSettingsPage::listPos(BufferViewConfig *config) {
244 for(int i = 0; i < ui.bufferViewList->count(); i++) {
245 obj = ui.bufferViewList->item(i)->data(Qt::UserRole).value<QObject *>();
246 if(config == qobject_cast<BufferViewConfig *>(obj))
252 BufferViewConfig *BufferViewSettingsPage::bufferView(int listPos) {
253 if(listPos < ui.bufferViewList->count() && listPos >= 0) {
254 QObject *obj = ui.bufferViewList->item(listPos)->data(Qt::UserRole).value<QObject *>();
255 return qobject_cast<BufferViewConfig *>(obj);
261 bool BufferViewSettingsPage::selectBufferViewById(int bufferViewId) {
262 BufferViewConfig *config;
263 for(int i = 0; i < ui.bufferViewList->count(); i++) {
264 config = qobject_cast<BufferViewConfig *>(ui.bufferViewList->item(i)->data(Qt::UserRole).value<QObject *>());
265 if(config && config->bufferViewId() == bufferViewId) {
266 ui.bufferViewList->setCurrentRow(i);
273 void BufferViewSettingsPage::updateBufferView() {
274 BufferViewConfig *config = qobject_cast<BufferViewConfig *>(sender());
278 int itemPos = listPos(config);
280 qWarning() << "BufferViewSettingsPage::updateBufferView(): view is unknown:" << config->bufferViewId();
283 ui.bufferViewList->item(itemPos)->setText(config->bufferViewName());
284 if(itemPos == ui.bufferViewList->currentRow())
288 void BufferViewSettingsPage::enableStatusBuffers(int networkIdx) {
289 // we don't show a status buffer if we show multiple networks as selecting
290 // the network is the same as selecting the status buffer.
291 ui.onlyStatusBuffers->setEnabled(networkIdx != 0);
294 void BufferViewSettingsPage::on_addBufferView_clicked() {
295 if(!Client::bufferViewManager())
298 QStringList existing;
299 foreach(BufferViewConfig *bufferConfig, Client::bufferViewManager()->bufferViewConfigs()) {
300 existing << bufferConfig->bufferViewName();
303 BufferViewEditDlg dlg(QString(), existing, this);
304 if(dlg.exec() == QDialog::Accepted) {
305 newBufferView(dlg.bufferViewName());
310 void BufferViewSettingsPage::on_renameBufferView_clicked() {
311 if(ui.bufferViewList->selectedItems().isEmpty())
314 if(!Client::bufferViewManager())
317 BufferViewConfig *config = bufferView(ui.bufferViewList->currentRow());
321 QStringList existing;
322 foreach(BufferViewConfig *bufferConfig, Client::bufferViewManager()->bufferViewConfigs()) {
323 existing << bufferConfig->bufferViewName();
326 BufferViewEditDlg dlg(config->bufferViewName(), existing, this);
327 if(dlg.exec() == QDialog::Accepted) {
328 BufferViewConfig *changedConfig = cloneConfig(config);
329 changedConfig->setBufferViewName(dlg.bufferViewName());
330 ui.bufferViewList->item(listPos(config))->setText(dlg.bufferViewName());
335 void BufferViewSettingsPage::on_deleteBufferView_clicked() {
336 if(ui.bufferViewList->selectedItems().isEmpty())
339 QListWidgetItem *currentItem = ui.bufferViewList->item(ui.bufferViewList->currentRow());
340 QString viewName = currentItem->text();
341 int viewId = bufferView(ui.bufferViewList->currentRow())->bufferViewId();
342 int ret = QMessageBox::question(this, tr("Delete Chat List?"),
343 tr("Do you really want to delete the chat list \"%1\"?").arg(viewName),
344 QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
346 if(ret == QMessageBox::Yes) {
347 ui.bufferViewList->removeItemWidget(currentItem);
348 BufferViewConfig *config = qobject_cast<BufferViewConfig *>(currentItem->data(Qt::UserRole).value<QObject *>());
351 _deleteBufferViews << viewId;
354 QList<BufferViewConfig *>::iterator iter = _newBufferViews.begin();
355 while(iter != _newBufferViews.end()) {
356 if(*iter == config) {
357 iter = _newBufferViews.erase(iter);
364 if(_deleteBufferViews.isEmpty() && _changedBufferViews.isEmpty() && _newBufferViews.isEmpty())
365 setChangedState(false);
370 void BufferViewSettingsPage::bufferViewSelectionChanged(const QItemSelection ¤t, const QItemSelection &previous) {
373 if(!current.isEmpty()) {
374 ui.settingsGroupBox->setEnabled(true);
375 ui.bufferViewPreview->setEnabled(true);
377 loadConfig(configForDisplay(bufferView(ui.bufferViewList->currentRow())));
379 ui.settingsGroupBox->setEnabled(false);
380 ui.bufferViewPreview->setEnabled(false);
384 void BufferViewSettingsPage::loadConfig(BufferViewConfig *config) {
388 _ignoreWidgetChanges = true;
389 ui.onlyStatusBuffers->setChecked(BufferInfo::StatusBuffer & config->allowedBufferTypes());
390 ui.onlyChannelBuffers->setChecked(BufferInfo::ChannelBuffer & config->allowedBufferTypes());
391 ui.onlyQueryBuffers->setChecked(BufferInfo::QueryBuffer & config->allowedBufferTypes());
392 ui.addNewBuffersAutomatically->setChecked(config->addNewBuffersAutomatically());
393 ui.sortAlphabetically->setChecked(config->sortAlphabetically());
394 ui.hideInactiveBuffers->setChecked(config->hideInactiveBuffers());
396 int networkIndex = 0;
397 for(int i = 0; i < ui.networkSelector->count(); i++) {
398 if(ui.networkSelector->itemData(i).value<NetworkId>() == config->networkId()) {
403 ui.networkSelector->setCurrentIndex(networkIndex);
405 int activityIndex = 0;
406 int minimumActivity = config->minimumActivity();
407 while(minimumActivity) {
409 minimumActivity = minimumActivity >> 1;
411 ui.minimumActivitySelector->setCurrentIndex(activityIndex);
413 ui.bufferViewPreview->setFilteredModel(Client::bufferModel(), config);
415 _ignoreWidgetChanges = false;
418 void BufferViewSettingsPage::saveConfig(BufferViewConfig *config) {
422 int allowedBufferTypes = 0;
423 if(ui.onlyStatusBuffers->isChecked())
424 allowedBufferTypes |= BufferInfo::StatusBuffer;
425 if(ui.onlyChannelBuffers->isChecked())
426 allowedBufferTypes |= BufferInfo::ChannelBuffer;
427 if(ui.onlyQueryBuffers->isChecked())
428 allowedBufferTypes |= BufferInfo::QueryBuffer;
429 config->setAllowedBufferTypes(allowedBufferTypes);
431 config->setAddNewBuffersAutomatically(ui.addNewBuffersAutomatically->isChecked());
432 config->setSortAlphabetically(ui.sortAlphabetically->isChecked());
433 config->setHideInactiveBuffers(ui.hideInactiveBuffers->isChecked());
434 config->setNetworkId(ui.networkSelector->itemData(ui.networkSelector->currentIndex()).value<NetworkId>());
436 int minimumActivity = 0;
437 if(ui.minimumActivitySelector->currentIndex() > 0)
438 minimumActivity = 1 << (ui.minimumActivitySelector->currentIndex() - 1);
439 config->setMinimumActivity(minimumActivity);
441 QList<BufferId> bufferIds = fromVariantList<BufferId>(config->property("OriginalBufferList").toList());
442 if(config->sortAlphabetically())
443 Client::networkModel()->sortBufferIds(bufferIds);
445 if(!_newBufferViews.contains(config) || config->addNewBuffersAutomatically())
446 config->initSetBufferList(bufferIds);
449 void BufferViewSettingsPage::widgetHasChanged() {
450 if(_ignoreWidgetChanges)
452 setChangedState(testHasChanged());
455 bool BufferViewSettingsPage::testHasChanged() {
456 saveConfig(cloneConfig(bufferView(ui.bufferViewList->currentRow())));
458 if(!_newBufferViews.isEmpty())
461 bool changed = false;
462 QHash<BufferViewConfig *, BufferViewConfig *>::iterator iter = _changedBufferViews.begin();
463 QHash<BufferViewConfig *, BufferViewConfig *>::iterator iterEnd = _changedBufferViews.end();
464 while(iter != iterEnd) {
465 if(&(iter.key()) == &(iter.value())) {
466 iter.value()->deleteLater();
467 iter = _changedBufferViews.erase(iter);
476 BufferViewConfig *BufferViewSettingsPage::cloneConfig(BufferViewConfig *config) {
477 if(!config || config->bufferViewId() < 0)
480 if(_changedBufferViews.contains(config))
481 return _changedBufferViews[config];
483 BufferViewConfig *changedConfig = new BufferViewConfig(-1, this);
484 changedConfig->fromVariantMap(config->toVariantMap());
485 changedConfig->setInitialized();
486 _changedBufferViews[config] = changedConfig;
487 connect(config, SIGNAL(bufferAdded(const BufferId &, int)), changedConfig, SLOT(addBuffer(const BufferId &, int)));
488 connect(config, SIGNAL(bufferMoved(const BufferId &, int)), changedConfig, SLOT(moveBuffer(const BufferId &, int)));
489 connect(config, SIGNAL(bufferRemoved(const BufferId &)), changedConfig, SLOT(removeBuffer(const BufferId &)));
490 // connect(config, SIGNAL(addBufferRequested(const BufferId &, int)), changedConfig, SLOT(addBuffer(const BufferId &, int)));
491 // connect(config, SIGNAL(moveBufferRequested(const BufferId &, int)), changedConfig, SLOT(moveBuffer(const BufferId &, int)));
492 // connect(config, SIGNAL(removeBufferRequested(const BufferId &)), changedConfig, SLOT(removeBuffer(const BufferId &)));
494 changedConfig->setProperty("OriginalBufferList", toVariantList<BufferId>(config->bufferList()));
495 // if this is the currently displayed view we have to change the config of the preview filter
496 BufferViewFilter *filter = qobject_cast<BufferViewFilter *>(ui.bufferViewPreview->model());
497 if(filter && filter->config() == config)
498 filter->setConfig(changedConfig);
499 ui.bufferViewPreview->setConfig(changedConfig);
501 return changedConfig;
504 BufferViewConfig *BufferViewSettingsPage::configForDisplay(BufferViewConfig *config) {
505 if(_changedBufferViews.contains(config))
506 return _changedBufferViews[config];
512 /**************************************************************************
514 *************************************************************************/
515 BufferViewEditDlg::BufferViewEditDlg(const QString &old, const QStringList &exist, QWidget *parent) : QDialog(parent), existing(exist) {
520 setWindowTitle(tr("Add Chat List"));
521 on_bufferViewEdit_textChanged(""); // disable ok button
523 ui.bufferViewEdit->setText(old);
528 void BufferViewEditDlg::on_bufferViewEdit_textChanged(const QString &text) {
529 ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(text.isEmpty() || existing.contains(text));