1 /***************************************************************************
2 * Copyright (C) 2005-2018 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 "bufferviewsettingspage.h"
23 #include <QMessageBox>
26 #include "buffermodel.h"
27 #include "bufferviewconfig.h"
28 #include "bufferviewfilter.h"
30 #include "clientbufferviewmanager.h"
33 #include "networkmodel.h"
36 BufferViewSettingsPage::BufferViewSettingsPage(QWidget *parent)
37 : SettingsPage(tr("Interface"), tr("Custom Chat Lists"), parent),
38 _ignoreWidgetChanges(false),
39 _useBufferViewHint(false),
43 //Hide the hide inactive networks feature on older cores (which won't save the setting)
44 if (!Client::isCoreFeatureEnabled(Quassel::Feature::HideInactiveNetworks))
45 ui.hideInactiveNetworks->hide();
47 ui.renameBufferView->setIcon(icon::get("edit-rename"));
48 ui.addBufferView->setIcon(icon::get("list-add"));
49 ui.deleteBufferView->setIcon(icon::get("edit-delete"));
53 ui.bufferViewList->setSortingEnabled(true);
54 ui.settingsGroupBox->setEnabled(false);
55 ui.bufferViewPreview->setEnabled(false);
57 coreConnectionStateChanged(Client::isConnected()); // need a core connection!
58 connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool)));
59 connect(ui.bufferViewList->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
60 this, SLOT(bufferViewSelectionChanged(const QItemSelection &, const QItemSelection &)));
62 connect(ui.onlyStatusBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
63 connect(ui.onlyChannelBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
64 connect(ui.onlyQueryBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
65 connect(ui.addNewBuffersAutomatically, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
66 connect(ui.sortAlphabetically, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
67 connect(ui.hideInactiveBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
68 connect(ui.hideInactiveNetworks, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
69 connect(ui.networkSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
70 connect(ui.minimumActivitySelector, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
71 connect(ui.showSearch, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
73 connect(ui.networkSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(enableStatusBuffers(int)));
77 BufferViewSettingsPage::~BufferViewSettingsPage()
83 void BufferViewSettingsPage::reset()
85 ui.bufferViewList->clear();
86 ui.deleteBufferView->setEnabled(false);
88 QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIter = _changedBufferViews.begin();
89 QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIterEnd = _changedBufferViews.end();
90 BufferViewConfig *config;
91 while (changedConfigIter != changedConfigIterEnd) {
92 config = changedConfigIter.value();
93 changedConfigIter = _changedBufferViews.erase(changedConfigIter);
94 config->deleteLater();
97 QList<BufferViewConfig *>::iterator newConfigIter = _newBufferViews.begin();
98 QList<BufferViewConfig *>::iterator newConfigIterEnd = _newBufferViews.end();
99 while (newConfigIter != newConfigIterEnd) {
100 config = *newConfigIter;
101 newConfigIter = _newBufferViews.erase(newConfigIter);
102 config->deleteLater();
105 _deleteBufferViews.clear();
107 _useBufferViewHint = false;
109 setChangedState(false);
113 void BufferViewSettingsPage::load()
115 bool useBufferViewHint = _useBufferViewHint;
116 int bufferViewHint = _bufferViewHint;
119 if (!Client::bufferViewManager())
122 const QList<BufferViewConfig *> bufferViewConfigs = Client::bufferViewManager()->bufferViewConfigs();
123 foreach(BufferViewConfig *bufferViewConfig, bufferViewConfigs) {
124 addBufferView(bufferViewConfig);
127 _ignoreWidgetChanges = true;
128 // load network selector
129 ui.networkSelector->clear();
130 ui.networkSelector->addItem(tr("All"));
131 ui.networkSelector->setItemData(0, qVariantFromValue<NetworkId>(NetworkId()));
133 foreach(NetworkId netId, Client::networkIds()) {
134 net = Client::network(netId);
135 ui.networkSelector->addItem(net->networkName());
136 ui.networkSelector->setItemData(ui.networkSelector->count() - 1, qVariantFromValue<NetworkId>(net->networkId()));
138 _ignoreWidgetChanges = false;
140 if (!useBufferViewHint || !selectBufferViewById(bufferViewHint))
141 ui.bufferViewList->setCurrentRow(0);
145 void BufferViewSettingsPage::save()
149 BufferViewConfig *currentConfig = bufferView(ui.bufferViewList->currentRow());
151 _useBufferViewHint = true;
152 _bufferViewHint = currentConfig->bufferViewId();
155 QVariantList newConfigs;
156 QVariantList deleteConfigs;
157 QVariantList changedConfigs;
159 foreach(int bufferId, _deleteBufferViews) {
160 deleteConfigs << bufferId;
162 _deleteBufferViews.clear();
163 if (Client::bufferViewManager()) {
164 Client::bufferViewManager()->requestDeleteBufferViews(deleteConfigs);
167 QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIter = _changedBufferViews.begin();
168 QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIterEnd = _changedBufferViews.end();
169 BufferViewConfig *config, *changedConfig;
170 while (changedConfigIter != changedConfigIterEnd) {
171 config = changedConfigIter.key();
172 changedConfig = changedConfigIter.value();
173 changedConfigIter = _changedBufferViews.erase(changedConfigIter);
174 config->requestUpdate(changedConfig->toVariantMap());
175 changedConfig->deleteLater();
178 QList<BufferViewConfig *>::iterator newConfigIter = _newBufferViews.begin();
179 QList<BufferViewConfig *>::iterator newConfigIterEnd = _newBufferViews.end();
180 while (newConfigIter != newConfigIterEnd) {
181 config = *newConfigIter;
182 newConfigIter = _newBufferViews.erase(newConfigIter);
183 newConfigs << config->toVariantMap();
184 config->deleteLater();
186 if (Client::bufferViewManager()) {
187 Client::bufferViewManager()->requestCreateBufferViews(newConfigs);
195 void BufferViewSettingsPage::coreConnectionStateChanged(bool state)
200 connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigAdded(int)), this, SLOT(addBufferView(int)));
208 void BufferViewSettingsPage::addBufferView(BufferViewConfig *config)
210 QListWidgetItem *item = new QListWidgetItem(config->bufferViewName(), ui.bufferViewList);
211 item->setData(Qt::UserRole, qVariantFromValue<QObject *>(qobject_cast<QObject *>(config)));
212 connect(config, SIGNAL(updatedRemotely()), this, SLOT(updateBufferView()));
213 connect(config, SIGNAL(destroyed()), this, SLOT(bufferViewDeleted()));
214 ui.deleteBufferView->setEnabled(ui.bufferViewList->count() > 1);
218 void BufferViewSettingsPage::addBufferView(int bufferViewId)
220 // we are informed about a new bufferview from Client::bufferViewManager()
221 Q_ASSERT(Client::bufferViewManager());
222 addBufferView(Client::bufferViewManager()->bufferViewConfig(bufferViewId));
223 selectBufferViewById(bufferViewId);
227 void BufferViewSettingsPage::bufferViewDeleted()
229 BufferViewConfig *config = static_cast<BufferViewConfig *>(sender());
231 for (int i = 0; i < ui.bufferViewList->count(); i++) {
232 obj = ui.bufferViewList->item(i)->data(Qt::UserRole).value<QObject *>();
233 if (config == static_cast<BufferViewConfig *>(obj)) {
234 QListWidgetItem *item = ui.bufferViewList->takeItem(i);
239 ui.deleteBufferView->setEnabled(ui.bufferViewList->count() > 1);
243 void BufferViewSettingsPage::newBufferView(const QString &bufferViewName)
245 // id's of newly created bufferviews are negative (-1, -2... -n)
246 int fakeId = -1 * (_newBufferViews.count() + 1);
247 BufferViewConfig *config = new BufferViewConfig(fakeId);
248 config->setBufferViewName(bufferViewName);
249 config->setInitialized();
250 QList<BufferId> bufferIds;
251 if (config->addNewBuffersAutomatically()) {
252 if (config->sortAlphabetically()) {
253 bufferIds = Client::networkModel()->allBufferIdsSorted();
256 bufferIds = Client::networkModel()->allBufferIds();
258 config->setProperty("OriginalBufferList", toVariantList<BufferId>(bufferIds));
261 config->initSetBufferList(bufferIds);
263 _newBufferViews << config;
264 addBufferView(config);
265 ui.bufferViewList->setCurrentRow(listPos(config));
269 int BufferViewSettingsPage::listPos(BufferViewConfig *config)
272 for (int i = 0; i < ui.bufferViewList->count(); i++) {
273 obj = ui.bufferViewList->item(i)->data(Qt::UserRole).value<QObject *>();
274 if (config == qobject_cast<BufferViewConfig *>(obj))
281 BufferViewConfig *BufferViewSettingsPage::bufferView(int listPos)
283 if (listPos < ui.bufferViewList->count() && listPos >= 0) {
284 QObject *obj = ui.bufferViewList->item(listPos)->data(Qt::UserRole).value<QObject *>();
285 return qobject_cast<BufferViewConfig *>(obj);
293 bool BufferViewSettingsPage::selectBufferViewById(int bufferViewId)
295 BufferViewConfig *config;
296 for (int i = 0; i < ui.bufferViewList->count(); i++) {
297 config = qobject_cast<BufferViewConfig *>(ui.bufferViewList->item(i)->data(Qt::UserRole).value<QObject *>());
298 if (config && config->bufferViewId() == bufferViewId) {
299 ui.bufferViewList->setCurrentRow(i);
307 void BufferViewSettingsPage::updateBufferView()
309 BufferViewConfig *config = qobject_cast<BufferViewConfig *>(sender());
313 int itemPos = listPos(config);
315 qWarning() << "BufferViewSettingsPage::updateBufferView(): view is unknown:" << config->bufferViewId();
318 ui.bufferViewList->item(itemPos)->setText(config->bufferViewName());
319 if (itemPos == ui.bufferViewList->currentRow())
324 void BufferViewSettingsPage::enableStatusBuffers(int networkIdx)
326 // we don't show a status buffer if we show multiple networks as selecting
327 // the network is the same as selecting the status buffer.
328 ui.onlyStatusBuffers->setEnabled(networkIdx != 0);
332 void BufferViewSettingsPage::on_addBufferView_clicked()
334 if (!Client::bufferViewManager())
337 QStringList existing;
338 foreach(BufferViewConfig *bufferConfig, Client::bufferViewManager()->bufferViewConfigs()) {
339 existing << bufferConfig->bufferViewName();
342 BufferViewEditDlg dlg(QString(), existing, this);
343 if (dlg.exec() == QDialog::Accepted) {
344 newBufferView(dlg.bufferViewName());
350 void BufferViewSettingsPage::on_renameBufferView_clicked()
352 if (ui.bufferViewList->selectedItems().isEmpty())
355 if (!Client::bufferViewManager())
358 BufferViewConfig *config = bufferView(ui.bufferViewList->currentRow());
362 QStringList existing;
363 foreach(BufferViewConfig *bufferConfig, Client::bufferViewManager()->bufferViewConfigs()) {
364 existing << bufferConfig->bufferViewName();
367 BufferViewEditDlg dlg(config->bufferViewName(), existing, this);
368 if (dlg.exec() == QDialog::Accepted) {
369 BufferViewConfig *changedConfig = cloneConfig(config);
370 changedConfig->setBufferViewName(dlg.bufferViewName());
371 ui.bufferViewList->item(listPos(config))->setText(dlg.bufferViewName());
377 void BufferViewSettingsPage::on_deleteBufferView_clicked()
379 if (ui.bufferViewList->selectedItems().isEmpty())
382 QListWidgetItem *currentItem = ui.bufferViewList->item(ui.bufferViewList->currentRow());
383 QString viewName = currentItem->text();
384 int viewId = bufferView(ui.bufferViewList->currentRow())->bufferViewId();
385 int ret = QMessageBox::question(this, tr("Delete Chat List?"),
386 tr("Do you really want to delete the chat list \"%1\"?").arg(viewName),
387 QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
389 if (ret == QMessageBox::Yes) {
390 ui.bufferViewList->removeItemWidget(currentItem);
391 BufferViewConfig *config = qobject_cast<BufferViewConfig *>(currentItem->data(Qt::UserRole).value<QObject *>());
394 _deleteBufferViews << viewId;
398 QList<BufferViewConfig *>::iterator iter = _newBufferViews.begin();
399 while (iter != _newBufferViews.end()) {
400 if (*iter == config) {
401 iter = _newBufferViews.erase(iter);
409 if (_deleteBufferViews.isEmpty() && _changedBufferViews.isEmpty() && _newBufferViews.isEmpty())
410 setChangedState(false);
416 void BufferViewSettingsPage::bufferViewSelectionChanged(const QItemSelection ¤t, const QItemSelection &previous)
420 if (!current.isEmpty()) {
421 ui.settingsGroupBox->setEnabled(true);
422 ui.bufferViewPreview->setEnabled(true);
424 loadConfig(configForDisplay(bufferView(ui.bufferViewList->currentRow())));
427 ui.settingsGroupBox->setEnabled(false);
428 ui.bufferViewPreview->setEnabled(false);
433 void BufferViewSettingsPage::loadConfig(BufferViewConfig *config)
438 _ignoreWidgetChanges = true;
439 ui.onlyStatusBuffers->setChecked(BufferInfo::StatusBuffer & config->allowedBufferTypes());
440 ui.onlyChannelBuffers->setChecked(BufferInfo::ChannelBuffer & config->allowedBufferTypes());
441 ui.onlyQueryBuffers->setChecked(BufferInfo::QueryBuffer & config->allowedBufferTypes());
442 ui.addNewBuffersAutomatically->setChecked(config->addNewBuffersAutomatically());
443 ui.sortAlphabetically->setChecked(config->sortAlphabetically());
444 ui.hideInactiveBuffers->setChecked(config->hideInactiveBuffers());
445 ui.hideInactiveNetworks->setChecked(config->hideInactiveNetworks());
446 ui.showSearch->setChecked(config->showSearch());
448 int networkIndex = 0;
449 for (int i = 0; i < ui.networkSelector->count(); i++) {
450 if (ui.networkSelector->itemData(i).value<NetworkId>() == config->networkId()) {
455 ui.networkSelector->setCurrentIndex(networkIndex);
457 int activityIndex = 0;
458 int minimumActivity = config->minimumActivity();
459 while (minimumActivity) {
461 minimumActivity = minimumActivity >> 1;
463 ui.minimumActivitySelector->setCurrentIndex(activityIndex);
465 ui.bufferViewPreview->setFilteredModel(Client::bufferModel(), config);
467 _ignoreWidgetChanges = false;
471 void BufferViewSettingsPage::saveConfig(BufferViewConfig *config)
476 int allowedBufferTypes = 0;
477 if (ui.onlyStatusBuffers->isChecked())
478 allowedBufferTypes |= BufferInfo::StatusBuffer;
479 if (ui.onlyChannelBuffers->isChecked())
480 allowedBufferTypes |= BufferInfo::ChannelBuffer;
481 if (ui.onlyQueryBuffers->isChecked())
482 allowedBufferTypes |= BufferInfo::QueryBuffer;
483 config->setAllowedBufferTypes(allowedBufferTypes);
485 config->setAddNewBuffersAutomatically(ui.addNewBuffersAutomatically->isChecked());
486 config->setSortAlphabetically(ui.sortAlphabetically->isChecked());
487 config->setHideInactiveBuffers(ui.hideInactiveBuffers->isChecked());
488 config->setHideInactiveNetworks(ui.hideInactiveNetworks->isChecked());
489 config->setNetworkId(ui.networkSelector->itemData(ui.networkSelector->currentIndex()).value<NetworkId>());
490 config->setShowSearch(ui.showSearch->isChecked());
492 int minimumActivity = 0;
493 if (ui.minimumActivitySelector->currentIndex() > 0)
494 minimumActivity = 1 << (ui.minimumActivitySelector->currentIndex() - 1);
495 config->setMinimumActivity(minimumActivity);
497 QList<BufferId> bufferIds = fromVariantList<BufferId>(config->property("OriginalBufferList").toList());
498 if (config->sortAlphabetically())
499 Client::networkModel()->sortBufferIds(bufferIds);
501 if (!_newBufferViews.contains(config) || config->addNewBuffersAutomatically())
502 config->initSetBufferList(bufferIds);
506 void BufferViewSettingsPage::widgetHasChanged()
508 if (_ignoreWidgetChanges)
510 setChangedState(testHasChanged());
514 bool BufferViewSettingsPage::testHasChanged()
516 saveConfig(cloneConfig(bufferView(ui.bufferViewList->currentRow())));
518 if (!_newBufferViews.isEmpty())
521 bool changed = false;
522 QHash<BufferViewConfig *, BufferViewConfig *>::iterator iter = _changedBufferViews.begin();
523 QHash<BufferViewConfig *, BufferViewConfig *>::iterator iterEnd = _changedBufferViews.end();
524 while (iter != iterEnd) {
525 if (&(iter.key()) == &(iter.value())) {
526 iter.value()->deleteLater();
527 iter = _changedBufferViews.erase(iter);
538 BufferViewConfig *BufferViewSettingsPage::cloneConfig(BufferViewConfig *config)
540 if (!config || config->bufferViewId() < 0)
543 if (_changedBufferViews.contains(config))
544 return _changedBufferViews[config];
546 BufferViewConfig *changedConfig = new BufferViewConfig(-1, this);
547 changedConfig->fromVariantMap(config->toVariantMap());
548 changedConfig->setInitialized();
549 _changedBufferViews[config] = changedConfig;
550 connect(config, SIGNAL(bufferAdded(const BufferId &, int)), changedConfig, SLOT(addBuffer(const BufferId &, int)));
551 connect(config, SIGNAL(bufferMoved(const BufferId &, int)), changedConfig, SLOT(moveBuffer(const BufferId &, int)));
552 connect(config, SIGNAL(bufferRemoved(const BufferId &)), changedConfig, SLOT(removeBuffer(const BufferId &)));
553 // connect(config, SIGNAL(addBufferRequested(const BufferId &, int)), changedConfig, SLOT(addBuffer(const BufferId &, int)));
554 // connect(config, SIGNAL(moveBufferRequested(const BufferId &, int)), changedConfig, SLOT(moveBuffer(const BufferId &, int)));
555 // connect(config, SIGNAL(removeBufferRequested(const BufferId &)), changedConfig, SLOT(removeBuffer(const BufferId &)));
557 changedConfig->setProperty("OriginalBufferList", toVariantList<BufferId>(config->bufferList()));
558 // if this is the currently displayed view we have to change the config of the preview filter
559 BufferViewFilter *filter = qobject_cast<BufferViewFilter *>(ui.bufferViewPreview->model());
560 if (filter && filter->config() == config)
561 filter->setConfig(changedConfig);
562 ui.bufferViewPreview->setConfig(changedConfig);
564 return changedConfig;
568 BufferViewConfig *BufferViewSettingsPage::configForDisplay(BufferViewConfig *config)
570 if (_changedBufferViews.contains(config))
571 return _changedBufferViews[config];
577 /**************************************************************************
579 *************************************************************************/
580 BufferViewEditDlg::BufferViewEditDlg(const QString &old, QStringList exist, QWidget *parent) : QDialog(parent), existing(std::move(exist))
586 setWindowTitle(tr("Add Chat List"));
587 on_bufferViewEdit_textChanged(""); // disable ok button
590 ui.bufferViewEdit->setText(old);
595 void BufferViewEditDlg::on_bufferViewEdit_textChanged(const QString &text)
597 ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(text.isEmpty() || existing.contains(text));