4a77807314a7f6fe9a107419b8ed05bc47db7c5f
[quassel.git] / src / qtui / settingspages / bufferviewsettingspage.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2018 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 "bufferviewsettingspage.h"
22
23 #include <QMessageBox>
24 #include <utility>
25
26 #include "buffermodel.h"
27 #include "bufferviewconfig.h"
28 #include "bufferviewfilter.h"
29 #include "client.h"
30 #include "clientbufferviewmanager.h"
31 #include "icon.h"
32 #include "network.h"
33 #include "networkmodel.h"
34 #include "util.h"
35
36 BufferViewSettingsPage::BufferViewSettingsPage(QWidget *parent)
37     : SettingsPage(tr("Interface"), tr("Custom Chat Lists"), parent)
38 {
39     ui.setupUi(this);
40     //Hide the hide inactive networks feature on older cores (which won't save the setting)
41     if (!Client::isCoreFeatureEnabled(Quassel::Feature::HideInactiveNetworks))
42         ui.hideInactiveNetworks->hide();
43
44     ui.renameBufferView->setIcon(icon::get("edit-rename"));
45     ui.addBufferView->setIcon(icon::get("list-add"));
46     ui.deleteBufferView->setIcon(icon::get("edit-delete"));
47
48     reset();
49
50     ui.bufferViewList->setSortingEnabled(true);
51     ui.settingsGroupBox->setEnabled(false);
52     ui.bufferViewPreview->setEnabled(false);
53
54     coreConnectionStateChanged(Client::isConnected()); // need a core connection!
55     connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool)));
56     connect(ui.bufferViewList->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
57         this, SLOT(bufferViewSelectionChanged(const QItemSelection &, const QItemSelection &)));
58
59     connect(ui.onlyStatusBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
60     connect(ui.onlyChannelBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
61     connect(ui.onlyQueryBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
62     connect(ui.addNewBuffersAutomatically, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
63     connect(ui.sortAlphabetically, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
64     connect(ui.hideInactiveBuffers, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
65     connect(ui.hideInactiveNetworks, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
66     connect(ui.networkSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
67     connect(ui.minimumActivitySelector, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
68     connect(ui.showSearch, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
69
70     connect(ui.networkSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(enableStatusBuffers(int)));
71 }
72
73
74 BufferViewSettingsPage::~BufferViewSettingsPage()
75 {
76     reset();
77 }
78
79
80 void BufferViewSettingsPage::reset()
81 {
82     ui.bufferViewList->clear();
83     ui.deleteBufferView->setEnabled(false);
84
85     QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIter = _changedBufferViews.begin();
86     QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIterEnd = _changedBufferViews.end();
87     BufferViewConfig *config;
88     while (changedConfigIter != changedConfigIterEnd) {
89         config = changedConfigIter.value();
90         changedConfigIter = _changedBufferViews.erase(changedConfigIter);
91         config->deleteLater();
92     }
93
94     QList<BufferViewConfig *>::iterator newConfigIter = _newBufferViews.begin();
95     QList<BufferViewConfig *>::iterator newConfigIterEnd = _newBufferViews.end();
96     while (newConfigIter != newConfigIterEnd) {
97         config = *newConfigIter;
98         newConfigIter = _newBufferViews.erase(newConfigIter);
99         config->deleteLater();
100     }
101
102     _deleteBufferViews.clear();
103
104     _useBufferViewHint = false;
105
106     setChangedState(false);
107 }
108
109
110 void BufferViewSettingsPage::load()
111 {
112     bool useBufferViewHint = _useBufferViewHint;
113     int bufferViewHint = _bufferViewHint;
114     reset();
115
116     if (!Client::bufferViewManager())
117         return;
118
119     const QList<BufferViewConfig *> bufferViewConfigs = Client::bufferViewManager()->bufferViewConfigs();
120     foreach(BufferViewConfig *bufferViewConfig, bufferViewConfigs) {
121         addBufferView(bufferViewConfig);
122     }
123
124     _ignoreWidgetChanges = true;
125     // load network selector
126     ui.networkSelector->clear();
127     ui.networkSelector->addItem(tr("All"));
128     ui.networkSelector->setItemData(0, qVariantFromValue<NetworkId>(NetworkId()));
129     const Network *net;
130     foreach(NetworkId netId, Client::networkIds()) {
131         net = Client::network(netId);
132         ui.networkSelector->addItem(net->networkName());
133         ui.networkSelector->setItemData(ui.networkSelector->count() - 1, qVariantFromValue<NetworkId>(net->networkId()));
134     }
135     _ignoreWidgetChanges = false;
136
137     if (!useBufferViewHint || !selectBufferViewById(bufferViewHint))
138         ui.bufferViewList->setCurrentRow(0);
139 }
140
141
142 void BufferViewSettingsPage::save()
143 {
144     setEnabled(false);
145
146     BufferViewConfig *currentConfig = bufferView(ui.bufferViewList->currentRow());
147     if (currentConfig) {
148         _useBufferViewHint = true;
149         _bufferViewHint = currentConfig->bufferViewId();
150     }
151
152     QVariantList newConfigs;
153     QVariantList deleteConfigs;
154     QVariantList changedConfigs;
155
156     foreach(int bufferId, _deleteBufferViews) {
157         deleteConfigs << bufferId;
158     }
159     _deleteBufferViews.clear();
160     if (Client::bufferViewManager()) {
161         Client::bufferViewManager()->requestDeleteBufferViews(deleteConfigs);
162     }
163
164     QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIter = _changedBufferViews.begin();
165     QHash<BufferViewConfig *, BufferViewConfig *>::iterator changedConfigIterEnd = _changedBufferViews.end();
166     BufferViewConfig *config, *changedConfig;
167     while (changedConfigIter != changedConfigIterEnd) {
168         config = changedConfigIter.key();
169         changedConfig = changedConfigIter.value();
170         changedConfigIter = _changedBufferViews.erase(changedConfigIter);
171         config->requestUpdate(changedConfig->toVariantMap());
172         changedConfig->deleteLater();
173     }
174
175     QList<BufferViewConfig *>::iterator newConfigIter = _newBufferViews.begin();
176     QList<BufferViewConfig *>::iterator newConfigIterEnd = _newBufferViews.end();
177     while (newConfigIter != newConfigIterEnd) {
178         config = *newConfigIter;
179         newConfigIter = _newBufferViews.erase(newConfigIter);
180         newConfigs << config->toVariantMap();
181         config->deleteLater();
182     }
183     if (Client::bufferViewManager()) {
184         Client::bufferViewManager()->requestCreateBufferViews(newConfigs);
185     }
186
187     load();
188     setEnabled(true);
189 }
190
191
192 void BufferViewSettingsPage::coreConnectionStateChanged(bool state)
193 {
194     setEnabled(state);
195     if (state) {
196         load();
197         connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigAdded(int)), this, SLOT(addBufferView(int)));
198     }
199     else {
200         reset();
201     }
202 }
203
204
205 void BufferViewSettingsPage::addBufferView(BufferViewConfig *config)
206 {
207     QListWidgetItem *item = new QListWidgetItem(config->bufferViewName(), ui.bufferViewList);
208     item->setData(Qt::UserRole, qVariantFromValue<QObject *>(qobject_cast<QObject *>(config)));
209     connect(config, SIGNAL(updatedRemotely()), this, SLOT(updateBufferView()));
210     connect(config, SIGNAL(destroyed()), this, SLOT(bufferViewDeleted()));
211     ui.deleteBufferView->setEnabled(ui.bufferViewList->count() > 1);
212 }
213
214
215 void BufferViewSettingsPage::addBufferView(int bufferViewId)
216 {
217     // we are informed about a new bufferview from Client::bufferViewManager()
218     Q_ASSERT(Client::bufferViewManager());
219     addBufferView(Client::bufferViewManager()->bufferViewConfig(bufferViewId));
220     selectBufferViewById(bufferViewId);
221 }
222
223
224 void BufferViewSettingsPage::bufferViewDeleted()
225 {
226     BufferViewConfig *config = static_cast<BufferViewConfig *>(sender());
227     QObject *obj;
228     for (int i = 0; i < ui.bufferViewList->count(); i++) {
229         obj = ui.bufferViewList->item(i)->data(Qt::UserRole).value<QObject *>();
230         if (config == static_cast<BufferViewConfig *>(obj)) {
231             QListWidgetItem *item = ui.bufferViewList->takeItem(i);
232             delete item;
233             break;
234         }
235     }
236     ui.deleteBufferView->setEnabled(ui.bufferViewList->count() > 1);
237 }
238
239
240 void BufferViewSettingsPage::newBufferView(const QString &bufferViewName)
241 {
242     // id's of newly created bufferviews are negative (-1, -2... -n)
243     int fakeId = -1 * (_newBufferViews.count() + 1);
244     BufferViewConfig *config = new BufferViewConfig(fakeId);
245     config->setBufferViewName(bufferViewName);
246     config->setInitialized();
247     QList<BufferId> bufferIds;
248     if (config->addNewBuffersAutomatically()) {
249         if (config->sortAlphabetically()) {
250             bufferIds = Client::networkModel()->allBufferIdsSorted();
251         }
252         else {
253             bufferIds = Client::networkModel()->allBufferIds();
254             qSort(bufferIds);
255             config->setProperty("OriginalBufferList", toVariantList<BufferId>(bufferIds));
256         }
257     }
258     config->initSetBufferList(bufferIds);
259
260     _newBufferViews << config;
261     addBufferView(config);
262     ui.bufferViewList->setCurrentRow(listPos(config));
263 }
264
265
266 int BufferViewSettingsPage::listPos(BufferViewConfig *config)
267 {
268     QObject *obj;
269     for (int i = 0; i < ui.bufferViewList->count(); i++) {
270         obj = ui.bufferViewList->item(i)->data(Qt::UserRole).value<QObject *>();
271         if (config == qobject_cast<BufferViewConfig *>(obj))
272             return i;
273     }
274     return -1;
275 }
276
277
278 BufferViewConfig *BufferViewSettingsPage::bufferView(int listPos)
279 {
280     if (listPos < ui.bufferViewList->count() && listPos >= 0) {
281         QObject *obj = ui.bufferViewList->item(listPos)->data(Qt::UserRole).value<QObject *>();
282         return qobject_cast<BufferViewConfig *>(obj);
283     }
284     else {
285         return nullptr;
286     }
287 }
288
289
290 bool BufferViewSettingsPage::selectBufferViewById(int bufferViewId)
291 {
292     BufferViewConfig *config;
293     for (int i = 0; i < ui.bufferViewList->count(); i++) {
294         config = qobject_cast<BufferViewConfig *>(ui.bufferViewList->item(i)->data(Qt::UserRole).value<QObject *>());
295         if (config && config->bufferViewId() == bufferViewId) {
296             ui.bufferViewList->setCurrentRow(i);
297             return true;
298         }
299     }
300     return false;
301 }
302
303
304 void BufferViewSettingsPage::updateBufferView()
305 {
306     BufferViewConfig *config = qobject_cast<BufferViewConfig *>(sender());
307     if (!config)
308         return;
309
310     int itemPos = listPos(config);
311     if (itemPos == -1) {
312         qWarning() << "BufferViewSettingsPage::updateBufferView(): view is unknown:" << config->bufferViewId();
313         return;
314     }
315     ui.bufferViewList->item(itemPos)->setText(config->bufferViewName());
316     if (itemPos == ui.bufferViewList->currentRow())
317         loadConfig(config);
318 }
319
320
321 void BufferViewSettingsPage::enableStatusBuffers(int networkIdx)
322 {
323     // we don't show a status buffer if we show multiple networks as selecting
324     // the network is the same as selecting the status buffer.
325     ui.onlyStatusBuffers->setEnabled(networkIdx != 0);
326 }
327
328
329 void BufferViewSettingsPage::on_addBufferView_clicked()
330 {
331     if (!Client::bufferViewManager())
332         return;
333
334     QStringList existing;
335     foreach(BufferViewConfig *bufferConfig, Client::bufferViewManager()->bufferViewConfigs()) {
336         existing << bufferConfig->bufferViewName();
337     }
338
339     BufferViewEditDlg dlg(QString(), existing, this);
340     if (dlg.exec() == QDialog::Accepted) {
341         newBufferView(dlg.bufferViewName());
342         changed();
343     }
344 }
345
346
347 void BufferViewSettingsPage::on_renameBufferView_clicked()
348 {
349     if (ui.bufferViewList->selectedItems().isEmpty())
350         return;
351
352     if (!Client::bufferViewManager())
353         return;
354
355     BufferViewConfig *config = bufferView(ui.bufferViewList->currentRow());
356     if (!config)
357         return;
358
359     QStringList existing;
360     foreach(BufferViewConfig *bufferConfig, Client::bufferViewManager()->bufferViewConfigs()) {
361         existing << bufferConfig->bufferViewName();
362     }
363
364     BufferViewEditDlg dlg(config->bufferViewName(), existing, this);
365     if (dlg.exec() == QDialog::Accepted) {
366         BufferViewConfig *changedConfig = cloneConfig(config);
367         changedConfig->setBufferViewName(dlg.bufferViewName());
368         ui.bufferViewList->item(listPos(config))->setText(dlg.bufferViewName());
369         changed();
370     }
371 }
372
373
374 void BufferViewSettingsPage::on_deleteBufferView_clicked()
375 {
376     if (ui.bufferViewList->selectedItems().isEmpty())
377         return;
378
379     QListWidgetItem *currentItem = ui.bufferViewList->item(ui.bufferViewList->currentRow());
380     QString viewName = currentItem->text();
381     int viewId = bufferView(ui.bufferViewList->currentRow())->bufferViewId();
382     int ret = QMessageBox::question(this, tr("Delete Chat List?"),
383         tr("Do you really want to delete the chat list \"%1\"?").arg(viewName),
384         QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
385
386     if (ret == QMessageBox::Yes) {
387         ui.bufferViewList->removeItemWidget(currentItem);
388         BufferViewConfig *config = qobject_cast<BufferViewConfig *>(currentItem->data(Qt::UserRole).value<QObject *>());
389         delete currentItem;
390         if (viewId >= 0) {
391             _deleteBufferViews << viewId;
392             changed();
393         }
394         else if (config) {
395             QList<BufferViewConfig *>::iterator iter = _newBufferViews.begin();
396             while (iter != _newBufferViews.end()) {
397                 if (*iter == config) {
398                     iter = _newBufferViews.erase(iter);
399                     break;
400                 }
401                 else {
402                     ++iter;
403                 }
404             }
405             delete config;
406             if (_deleteBufferViews.isEmpty() && _changedBufferViews.isEmpty() && _newBufferViews.isEmpty())
407                 setChangedState(false);
408         }
409     }
410 }
411
412
413 void BufferViewSettingsPage::bufferViewSelectionChanged(const QItemSelection &current, const QItemSelection &previous)
414 {
415     Q_UNUSED(previous)
416
417     if (!current.isEmpty()) {
418         ui.settingsGroupBox->setEnabled(true);
419         ui.bufferViewPreview->setEnabled(true);
420
421         loadConfig(configForDisplay(bufferView(ui.bufferViewList->currentRow())));
422     }
423     else {
424         ui.settingsGroupBox->setEnabled(false);
425         ui.bufferViewPreview->setEnabled(false);
426     }
427 }
428
429
430 void BufferViewSettingsPage::loadConfig(BufferViewConfig *config)
431 {
432     if (!config)
433         return;
434
435     _ignoreWidgetChanges = true;
436     ui.onlyStatusBuffers->setChecked(BufferInfo::StatusBuffer & config->allowedBufferTypes());
437     ui.onlyChannelBuffers->setChecked(BufferInfo::ChannelBuffer & config->allowedBufferTypes());
438     ui.onlyQueryBuffers->setChecked(BufferInfo::QueryBuffer & config->allowedBufferTypes());
439     ui.addNewBuffersAutomatically->setChecked(config->addNewBuffersAutomatically());
440     ui.sortAlphabetically->setChecked(config->sortAlphabetically());
441     ui.hideInactiveBuffers->setChecked(config->hideInactiveBuffers());
442     ui.hideInactiveNetworks->setChecked(config->hideInactiveNetworks());
443     ui.showSearch->setChecked(config->showSearch());
444
445     int networkIndex = 0;
446     for (int i = 0; i < ui.networkSelector->count(); i++) {
447         if (ui.networkSelector->itemData(i).value<NetworkId>() == config->networkId()) {
448             networkIndex = i;
449             break;
450         }
451     }
452     ui.networkSelector->setCurrentIndex(networkIndex);
453
454     int activityIndex = 0;
455     int minimumActivity = config->minimumActivity();
456     while (minimumActivity) {
457         activityIndex++;
458         minimumActivity = minimumActivity >> 1;
459     }
460     ui.minimumActivitySelector->setCurrentIndex(activityIndex);
461
462     ui.bufferViewPreview->setFilteredModel(Client::bufferModel(), config);
463
464     _ignoreWidgetChanges = false;
465 }
466
467
468 void BufferViewSettingsPage::saveConfig(BufferViewConfig *config)
469 {
470     if (!config)
471         return;
472
473     int allowedBufferTypes = 0;
474     if (ui.onlyStatusBuffers->isChecked())
475         allowedBufferTypes |= BufferInfo::StatusBuffer;
476     if (ui.onlyChannelBuffers->isChecked())
477         allowedBufferTypes |= BufferInfo::ChannelBuffer;
478     if (ui.onlyQueryBuffers->isChecked())
479         allowedBufferTypes |= BufferInfo::QueryBuffer;
480     config->setAllowedBufferTypes(allowedBufferTypes);
481
482     config->setAddNewBuffersAutomatically(ui.addNewBuffersAutomatically->isChecked());
483     config->setSortAlphabetically(ui.sortAlphabetically->isChecked());
484     config->setHideInactiveBuffers(ui.hideInactiveBuffers->isChecked());
485     config->setHideInactiveNetworks(ui.hideInactiveNetworks->isChecked());
486     config->setNetworkId(ui.networkSelector->itemData(ui.networkSelector->currentIndex()).value<NetworkId>());
487     config->setShowSearch(ui.showSearch->isChecked());
488
489     int minimumActivity = 0;
490     if (ui.minimumActivitySelector->currentIndex() > 0)
491         minimumActivity = 1 << (ui.minimumActivitySelector->currentIndex() - 1);
492     config->setMinimumActivity(minimumActivity);
493
494     QList<BufferId> bufferIds = fromVariantList<BufferId>(config->property("OriginalBufferList").toList());
495     if (config->sortAlphabetically())
496         Client::networkModel()->sortBufferIds(bufferIds);
497
498     if (!_newBufferViews.contains(config) || config->addNewBuffersAutomatically())
499         config->initSetBufferList(bufferIds);
500 }
501
502
503 void BufferViewSettingsPage::widgetHasChanged()
504 {
505     if (_ignoreWidgetChanges)
506         return;
507     setChangedState(testHasChanged());
508 }
509
510
511 bool BufferViewSettingsPage::testHasChanged()
512 {
513     saveConfig(cloneConfig(bufferView(ui.bufferViewList->currentRow())));
514
515     if (!_newBufferViews.isEmpty())
516         return true;
517
518     bool changed = false;
519     QHash<BufferViewConfig *, BufferViewConfig *>::iterator iter = _changedBufferViews.begin();
520     QHash<BufferViewConfig *, BufferViewConfig *>::iterator iterEnd = _changedBufferViews.end();
521     while (iter != iterEnd) {
522         if (&(iter.key()) == &(iter.value())) {
523             iter.value()->deleteLater();
524             iter = _changedBufferViews.erase(iter);
525         }
526         else {
527             changed = true;
528             ++iter;
529         }
530     }
531     return changed;
532 }
533
534
535 BufferViewConfig *BufferViewSettingsPage::cloneConfig(BufferViewConfig *config)
536 {
537     if (!config || config->bufferViewId() < 0)
538         return config;
539
540     if (_changedBufferViews.contains(config))
541         return _changedBufferViews[config];
542
543     BufferViewConfig *changedConfig = new BufferViewConfig(-1, this);
544     changedConfig->fromVariantMap(config->toVariantMap());
545     changedConfig->setInitialized();
546     _changedBufferViews[config] = changedConfig;
547     connect(config, SIGNAL(bufferAdded(const BufferId &, int)), changedConfig, SLOT(addBuffer(const BufferId &, int)));
548     connect(config, SIGNAL(bufferMoved(const BufferId &, int)), changedConfig, SLOT(moveBuffer(const BufferId &, int)));
549     connect(config, SIGNAL(bufferRemoved(const BufferId &)), changedConfig, SLOT(removeBuffer(const BufferId &)));
550 //   connect(config, SIGNAL(addBufferRequested(const BufferId &, int)), changedConfig, SLOT(addBuffer(const BufferId &, int)));
551 //   connect(config, SIGNAL(moveBufferRequested(const BufferId &, int)), changedConfig, SLOT(moveBuffer(const BufferId &, int)));
552 //   connect(config, SIGNAL(removeBufferRequested(const BufferId &)), changedConfig, SLOT(removeBuffer(const BufferId &)));
553
554     changedConfig->setProperty("OriginalBufferList", toVariantList<BufferId>(config->bufferList()));
555     // if this is the currently displayed view we have to change the config of the preview filter
556     BufferViewFilter *filter = qobject_cast<BufferViewFilter *>(ui.bufferViewPreview->model());
557     if (filter && filter->config() == config)
558         filter->setConfig(changedConfig);
559     ui.bufferViewPreview->setConfig(changedConfig);
560
561     return changedConfig;
562 }
563
564
565 BufferViewConfig *BufferViewSettingsPage::configForDisplay(BufferViewConfig *config)
566 {
567     if (_changedBufferViews.contains(config))
568         return _changedBufferViews[config];
569     else
570         return config;
571 }
572
573
574 /**************************************************************************
575  * BufferViewEditDlg
576  *************************************************************************/
577 BufferViewEditDlg::BufferViewEditDlg(const QString &old, QStringList exist, QWidget *parent) : QDialog(parent), existing(std::move(exist))
578 {
579     ui.setupUi(this);
580
581     if (old.isEmpty()) {
582         // new buffer
583         setWindowTitle(tr("Add Chat List"));
584         on_bufferViewEdit_textChanged(""); // disable ok button
585     }
586     else {
587         ui.bufferViewEdit->setText(old);
588     }
589 }
590
591
592 void BufferViewEditDlg::on_bufferViewEdit_textChanged(const QString &text)
593 {
594     ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(text.isEmpty() || existing.contains(text));
595 }