1 /***************************************************************************
2 * Copyright (C) 2005-08 by the Quassel IRC Team *
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>
27 #include "bufferviewconfig.h"
28 #include "bufferviewfilter.h"
29 #include "bufferviewmanager.h"
30 #include "buffermodel.h"
31 #include "networkmodel.h"
33 BufferViewSettingsPage::BufferViewSettingsPage(QWidget *parent)
34 : SettingsPage(tr("General"), tr("Buffer Views"), parent),
35 _ignoreWidgetChanges(false)
40 ui.bufferViewList->setSortingEnabled(true);
41 ui.settingsGroupBox->setEnabled(false);
42 ui.bufferViewPreview->setEnabled(false);
44 setEnabled(Client::isConnected()); // need a core connection!
45 connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool)));
46 connect(ui.bufferViewList->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
47 this, SLOT(bufferViewSelectionChanged(const QItemSelection &, const QItemSelection &)));
49 connect(ui.onlyStatusBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
50 connect(ui.onlyChannelBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
51 connect(ui.onlyQueryBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
52 connect(ui.addNewBuffersAutomatically, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
53 connect(ui.sortAlphabetically, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
54 connect(ui.hideInactiveBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
55 connect(ui.networkSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
56 connect(ui.minimumActivitySelector, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
58 // FIXME: (see FIXME in BufferViewFilter::filterAcceptBuffer())
59 ui.minimumActivitySelector->setEnabled(false);
62 BufferViewSettingsPage::~BufferViewSettingsPage() {
66 void BufferViewSettingsPage::reset() {
67 ui.bufferViewList->clear();
69 QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIter = _changedBufferViews.begin();
70 QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIterEnd = _changedBufferViews.end();
71 BufferViewConfig *config;
72 while(changedConfigIter != changedConfigIterEnd) {
73 config = changedConfigIter.value();
74 changedConfigIter = _changedBufferViews.erase(changedConfigIter);
75 config->deleteLater();
78 QList<BufferViewConfig *>::iterator newConfigIter = _newBufferViews.begin();
79 QList<BufferViewConfig *>::iterator newConfigIterEnd = _newBufferViews.end();
80 while(newConfigIter != newConfigIterEnd) {
81 config = *newConfigIter;
82 newConfigIter = _newBufferViews.erase(newConfigIter);
83 config->deleteLater();
86 _deleteBufferViews.clear();
88 setChangedState(false);
91 void BufferViewSettingsPage::load() {
94 if(!Client::bufferViewManager())
97 const QList<BufferViewConfig *> bufferViewConfigs = Client::bufferViewManager()->bufferViewConfigs();
98 foreach(BufferViewConfig *bufferViewConfig, bufferViewConfigs) {
99 addBufferView(bufferViewConfig);
102 _ignoreWidgetChanges = true;
103 // load network selector
104 ui.networkSelector->clear();
105 ui.networkSelector->addItem("All");
106 ui.networkSelector->setItemData(0, qVariantFromValue<NetworkId>(NetworkId()));
108 foreach(NetworkId netId, Client::networkIds()) {
109 net = Client::network(netId);
110 ui.networkSelector->addItem(net->networkName());
111 ui.networkSelector->setItemData(ui.networkSelector->count() - 1, qVariantFromValue<NetworkId>(net->networkId()));
113 _ignoreWidgetChanges = false;
115 ui.bufferViewList->setCurrentRow(0);
118 void BufferViewSettingsPage::save() {
120 QVariantList newConfigs;
121 QVariantList deleteConfigs;
122 QVariantList changedConfigs;
124 foreach(int bufferId, _deleteBufferViews) {
125 deleteConfigs << bufferId;
127 _deleteBufferViews.clear();
128 if(Client::bufferViewManager()) {
129 Client::bufferViewManager()->requestDeleteBufferViews(deleteConfigs);
132 QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIter = _changedBufferViews.begin();
133 QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIterEnd = _changedBufferViews.end();
134 BufferViewConfig *config, *changedConfig;
135 while(changedConfigIter != changedConfigIterEnd) {
136 config = changedConfigIter.key();
137 changedConfig = changedConfigIter.value();
138 changedConfigIter = _changedBufferViews.erase(changedConfigIter);
139 config->requestUpdate(changedConfig->toVariantMap());
140 changedConfig->deleteLater();
143 QList<BufferViewConfig *>::iterator newConfigIter = _newBufferViews.begin();
144 QList<BufferViewConfig *>::iterator newConfigIterEnd = _newBufferViews.end();
145 while(newConfigIter != newConfigIterEnd) {
146 config = *newConfigIter;
147 newConfigIter = _newBufferViews.erase(newConfigIter);
148 newConfigs << config->toVariantMap();
149 config->deleteLater();
151 if(Client::bufferViewManager()) {
152 Client::bufferViewManager()->requestCreateBufferViews(newConfigs);
159 void BufferViewSettingsPage::coreConnectionStateChanged(bool state) {
163 connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigAdded(int)), this, SLOT(addBufferView(int)));
169 void BufferViewSettingsPage::addBufferView(BufferViewConfig *config) {
170 QListWidgetItem *item = new QListWidgetItem(config->bufferViewName(), ui.bufferViewList);
171 item->setData(Qt::UserRole, qVariantFromValue<QObject *>(qobject_cast<QObject *>(config)));
172 connect(config, SIGNAL(updatedRemotely()), this, SLOT(updateBufferView()));
173 connect(config, SIGNAL(destroyed()), this, SLOT(bufferViewDeleted()));
176 void BufferViewSettingsPage::addBufferView(int bufferViewId) {
177 Q_ASSERT(Client::bufferViewManager());
178 addBufferView(Client::bufferViewManager()->bufferViewConfig(bufferViewId));
181 void BufferViewSettingsPage::bufferViewDeleted() {
182 BufferViewConfig *config = static_cast<BufferViewConfig *>(sender());
184 for(int i = 0; i < ui.bufferViewList->count(); i++) {
185 obj = ui.bufferViewList->item(i)->data(Qt::UserRole).value<QObject *>();
186 if(config == static_cast<BufferViewConfig *>(obj)) {
187 QListWidgetItem *item = ui.bufferViewList->takeItem(i);
194 void BufferViewSettingsPage::newBufferView(const QString &bufferViewName) {
195 // id's of newly created bufferviews are negative (-1, -2... -n)
196 int fakeId = -1 * (_newBufferViews.count() + 1);
197 BufferViewConfig *config = new BufferViewConfig(fakeId);
198 config->setBufferViewName(bufferViewName);
200 QList<BufferId> bufferIds;
201 if(config->addNewBuffersAutomatically()) {
202 foreach(BufferInfo bufferInfo, Client::allBufferInfos()) {
203 bufferIds << bufferInfo.bufferId();
205 if(config->sortAlphabetically())
206 qSort(bufferIds.begin(), bufferIds.end(), bufferIdLessThan);
208 config->initSetBufferList(bufferIds);
210 _newBufferViews << config;
211 addBufferView(config);
212 ui.bufferViewList->setCurrentRow(listPos(config));
215 int BufferViewSettingsPage::listPos(BufferViewConfig *config) {
217 for(int i = 0; i < ui.bufferViewList->count(); i++) {
218 obj = ui.bufferViewList->item(i)->data(Qt::UserRole).value<QObject *>();
219 if(config == qobject_cast<BufferViewConfig *>(obj))
225 BufferViewConfig *BufferViewSettingsPage::bufferView(int listPos) {
226 if(listPos < ui.bufferViewList->count() && listPos >= 0) {
227 QObject *obj = ui.bufferViewList->item(listPos)->data(Qt::UserRole).value<QObject *>();
228 return qobject_cast<BufferViewConfig *>(obj);
234 void BufferViewSettingsPage::updateBufferView() {
235 BufferViewConfig *config = qobject_cast<BufferViewConfig *>(sender());
239 int itemPos = listPos(config);
241 qWarning() << "BufferViewSettingsPage::updateBufferView(): view is unknown:" << config->bufferViewId();
244 ui.bufferViewList->item(itemPos)->setText(config->bufferViewName());
245 if(itemPos == ui.bufferViewList->currentRow())
249 void BufferViewSettingsPage::on_addBufferView_clicked() {
250 if(!Client::bufferViewManager())
253 QStringList existing;
254 foreach(BufferViewConfig *bufferConfig, Client::bufferViewManager()->bufferViewConfigs()) {
255 existing << bufferConfig->bufferViewName();
258 BufferViewEditDlg dlg(QString(), existing, this);
259 if(dlg.exec() == QDialog::Accepted) {
260 newBufferView(dlg.bufferViewName());
265 void BufferViewSettingsPage::on_renameBufferView_clicked() {
266 if(ui.bufferViewList->selectedItems().isEmpty())
269 if(!Client::bufferViewManager())
272 BufferViewConfig *config = bufferView(ui.bufferViewList->currentRow());
276 QStringList existing;
277 foreach(BufferViewConfig *bufferConfig, Client::bufferViewManager()->bufferViewConfigs()) {
278 existing << bufferConfig->bufferViewName();
281 BufferViewEditDlg dlg(config->bufferViewName(), existing, this);
282 if(dlg.exec() == QDialog::Accepted) {
283 BufferViewConfig *changedConfig = cloneConfig(config);
284 changedConfig->setBufferViewName(dlg.bufferViewName());
285 ui.bufferViewList->item(listPos(config))->setText(dlg.bufferViewName());
290 void BufferViewSettingsPage::on_deleteBufferView_clicked() {
291 if(ui.bufferViewList->selectedItems().isEmpty())
294 QListWidgetItem *currentItem = ui.bufferViewList->item(ui.bufferViewList->currentRow());
295 QString viewName = currentItem->text();
296 int viewId = bufferView(ui.bufferViewList->currentRow())->bufferViewId();
297 int ret = QMessageBox::question(this, tr("Delete Buffer View?"),
298 tr("Do you really want to delete the buffer view \"%1\"?").arg(viewName),
299 QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
301 if(ret == QMessageBox::Yes) {
302 ui.bufferViewList->removeItemWidget(currentItem);
305 _deleteBufferViews << viewId;
310 void BufferViewSettingsPage::bufferViewSelectionChanged(const QItemSelection ¤t, const QItemSelection &previous) {
313 if(!current.isEmpty()) {
314 ui.settingsGroupBox->setEnabled(true);
315 ui.bufferViewPreview->setEnabled(true);
317 loadConfig(configForDisplay(bufferView(ui.bufferViewList->currentRow())));
319 ui.settingsGroupBox->setEnabled(false);
320 ui.bufferViewPreview->setEnabled(false);
324 void BufferViewSettingsPage::loadConfig(BufferViewConfig *config) {
328 _ignoreWidgetChanges = true;
329 ui.onlyStatusBuffers->setChecked(BufferInfo::StatusBuffer & config->allowedBufferTypes());
330 ui.onlyChannelBuffers->setChecked(BufferInfo::ChannelBuffer & config->allowedBufferTypes());
331 ui.onlyQueryBuffers->setChecked(BufferInfo::QueryBuffer & config->allowedBufferTypes());
332 ui.addNewBuffersAutomatically->setChecked(config->addNewBuffersAutomatically());
333 ui.sortAlphabetically->setChecked(config->sortAlphabetically());
334 ui.hideInactiveBuffers->setChecked(config->hideInactiveBuffers());
336 int networkIndex = 0;
337 for(int i = 0; i < ui.networkSelector->count(); i++) {
338 if(ui.networkSelector->itemData(i).value<NetworkId>() == config->networkId()) {
343 ui.networkSelector->setCurrentIndex(networkIndex);
345 int activityIndex = 0;
346 int minimumActivity = config->minimumActivity();
347 while(minimumActivity) {
349 minimumActivity = minimumActivity >> 1;
351 ui.minimumActivitySelector->setCurrentIndex(activityIndex);
353 ui.bufferViewPreview->setFilteredModel(Client::bufferModel(), config);
355 _ignoreWidgetChanges = false;
358 void BufferViewSettingsPage::saveConfig(BufferViewConfig *config) {
362 int allowedBufferTypes = 0;
363 if(ui.onlyStatusBuffers->isChecked())
364 allowedBufferTypes |= BufferInfo::StatusBuffer;
365 if(ui.onlyChannelBuffers->isChecked())
366 allowedBufferTypes |= BufferInfo::ChannelBuffer;
367 if(ui.onlyQueryBuffers->isChecked())
368 allowedBufferTypes |= BufferInfo::QueryBuffer;
369 config->setAllowedBufferTypes(allowedBufferTypes);
371 config->setAddNewBuffersAutomatically(ui.addNewBuffersAutomatically->isChecked());
372 config->setSortAlphabetically(ui.sortAlphabetically->isChecked());
373 config->setHideInactiveBuffers(ui.hideInactiveBuffers->isChecked());
374 config->setNetworkId(ui.networkSelector->itemData(ui.networkSelector->currentIndex()).value<NetworkId>());
376 int minimumActivity = 0;
377 if(ui.minimumActivitySelector->currentIndex() > 0)
378 minimumActivity = 1 << (ui.minimumActivitySelector->currentIndex() - 1);
379 config->setMinimumActivity(minimumActivity);
381 if(_newBufferViews.contains(config)) {
382 QList<BufferId> bufferIds;
383 if(config->addNewBuffersAutomatically()) {
384 foreach(BufferInfo bufferInfo, Client::allBufferInfos()) {
385 bufferIds << bufferInfo.bufferId();
387 if(config->sortAlphabetically())
388 qSort(bufferIds.begin(), bufferIds.end(), bufferIdLessThan);
390 config->initSetBufferList(bufferIds);
394 void BufferViewSettingsPage::widgetHasChanged() {
395 if(_ignoreWidgetChanges)
397 setChangedState(testHasChanged());
400 bool BufferViewSettingsPage::testHasChanged() {
401 saveConfig(cloneConfig(bufferView(ui.bufferViewList->currentRow())));
403 if(!_newBufferViews.isEmpty())
406 bool changed = false;
407 QHash<BufferViewConfig *, BufferViewConfig *>::iterator iter = _changedBufferViews.begin();
408 QHash<BufferViewConfig *, BufferViewConfig *>::iterator iterEnd = _changedBufferViews.end();
409 while(iter != iterEnd) {
410 if(&(iter.key()) == &(iter.value())) {
411 iter.value()->deleteLater();
412 _changedBufferViews.erase(iter);
421 BufferViewConfig *BufferViewSettingsPage::cloneConfig(BufferViewConfig *config) {
422 if(!config || config->bufferViewId() < 0)
425 if(_changedBufferViews.contains(config))
426 return _changedBufferViews[config];
428 BufferViewConfig *changedConfig = new BufferViewConfig(-1, this);
429 changedConfig->fromVariantMap(config->toVariantMap());
430 _changedBufferViews[config] = changedConfig;
431 connect(config, SIGNAL(bufferAdded(const BufferId &, int)), changedConfig, SLOT(addBuffer(const BufferId &, int)));
432 connect(config, SIGNAL(bufferMoved(const BufferId &, int)), changedConfig, SLOT(moveBuffer(const BufferId &, int)));
433 connect(config, SIGNAL(bufferRemoved(const BufferId &)), changedConfig, SLOT(removeBuffer(const BufferId &)));
434 connect(config, SIGNAL(addBufferRequested(const BufferId &, int)), changedConfig, SLOT(addBuffer(const BufferId &, int)));
435 connect(config, SIGNAL(moveBufferRequested(const BufferId &, int)), changedConfig, SLOT(moveBuffer(const BufferId &, int)));
436 connect(config, SIGNAL(removeBufferRequested(const BufferId &)), changedConfig, SLOT(removeBuffer(const BufferId &)));
438 // if this is the currently displayed view we have to change the config of the preview filter
439 BufferViewFilter *filter = qobject_cast<BufferViewFilter *>(ui.bufferViewPreview->model());
440 if(filter && filter->config() == config)
441 filter->setConfig(changedConfig);
442 ui.bufferViewPreview->setConfig(changedConfig);
444 return changedConfig;
447 BufferViewConfig *BufferViewSettingsPage::configForDisplay(BufferViewConfig *config) {
448 if(_changedBufferViews.contains(config))
449 return _changedBufferViews[config];
455 /**************************************************************************
457 *************************************************************************/
458 BufferViewEditDlg::BufferViewEditDlg(const QString &old, const QStringList &exist, QWidget *parent) : QDialog(parent), existing(exist) {
463 setWindowTitle(tr("Add Buffer View"));
464 on_bufferViewEdit_textChanged(""); // disable ok button
466 ui.bufferViewEdit->setText(old);
471 void BufferViewEditDlg::on_bufferViewEdit_textChanged(const QString &text) {
472 ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(text.isEmpty() || existing.contains(text));