delay a few things on startup, such as setting the visibility mode, which ensures...
[personal-kdebase.git] / runtime / phonon / kcm / devicepreference.cpp
blob7a12a7fbca878d84f58cd50bcb2cd2eaca3c5279
1 /* This file is part of the KDE project
2 Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org>
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) version 3.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
21 #include "devicepreference.h"
23 #include <QtCore/QList>
24 #include <QtDBus/QDBusConnection>
25 #include <QtDBus/QDBusReply>
26 #include <QtDBus/QDBusInterface>
27 #include <QtDBus/QDBusMessage>
28 #include <QtGui/QApplication>
29 #include <QtGui/QPainter>
30 #include <QtGui/QItemDelegate>
31 #include <QtGui/QLabel>
32 #include <QtGui/QVBoxLayout>
33 #include <QtGui/QHeaderView>
35 #include <Phonon/AudioOutput>
36 #include <Phonon/MediaObject>
37 #include <phonon/backendcapabilities.h>
38 #include <phonon/objectdescription.h>
39 #include <phonon/phononnamespace.h>
40 #include "qsettingsgroup_p.h"
41 #include "globalconfig_p.h"
42 #include <kfadewidgeteffect.h>
44 #include <kdialog.h>
45 #include <klistwidget.h>
46 #include <klocale.h>
47 #include <kmenu.h>
48 #include <kmessagebox.h>
49 #include <kstandarddirs.h>
50 #include <kdebug.h>
52 #ifndef METATYPE_QLIST_INT_DEFINED
53 #define METATYPE_QLIST_INT_DEFINED
54 // Want this exactly once, see phonondefs_p.h kcm/devicepreference.cpp
55 Q_DECLARE_METATYPE(QList<int>)
56 #endif
58 using Phonon::QSettingsGroup;
60 static const Phonon::Category captureCategories[] = {
61 Phonon::NoCategory,
62 Phonon::CommunicationCategory,
63 Phonon::AccessibilityCategory
65 static const int captureCategoriesCount = sizeof(captureCategories)/sizeof(Phonon::Category);
67 void operator++(Phonon::Category &c)
69 c = static_cast<Phonon::Category>(1 + static_cast<int>(c));
70 //Q_ASSERT(c <= Phonon::LastCategory);
73 class CategoryItem : public QStandardItem {
74 public:
75 CategoryItem(Phonon::Category cat, bool output = true)
76 : QStandardItem(cat == Phonon::NoCategory ? (output ? i18n("Audio Output") : i18n("Audio Capture")) : Phonon::categoryToString(cat)),
77 isOutputItem(output),
78 m_cat(cat)
82 int type() const { return 1001; }
83 Phonon::Category category() const { return m_cat; }
84 const bool isOutputItem;
86 private:
87 Phonon::Category m_cat;
90 /**
91 * Need this to change the colors of the ListView if the Palette changed. With CSS set this won't
92 * change automatically
94 void DevicePreference::changeEvent(QEvent *e)
96 QWidget::changeEvent(e);
97 if (e->type() == QEvent::PaletteChange) {
98 //deviceList->viewport()->setStyleSheet(deviceList->viewport()->styleSheet());
99 deviceList->setStyleSheet(deviceList->styleSheet());
103 DevicePreference::DevicePreference(QWidget *parent)
104 : QWidget(parent),
105 m_headerModel(0, 1, 0),
106 m_showingOutputModel(true),
107 m_media(0), m_output(0)
109 setupUi(this);
110 testPlaybackButton->setIcon(KIcon("media-playback-start"));
111 testPlaybackButton->setEnabled(false);
112 testPlaybackButton->setToolTip(i18n("Play a test sound on the selected device"));
113 removeButton->setIcon(KIcon("list-remove"));
114 deferButton->setIcon(KIcon("go-down"));
115 preferButton->setIcon(KIcon("go-up"));
116 deviceList->setDragDropMode(QAbstractItemView::InternalMove);
117 //deviceList->viewport()->setStyleSheet(QString("QWidget#qt_scrollarea_viewport {"
118 deviceList->setStyleSheet(QString("QTreeView {"
119 "background-color: palette(base);"
120 "background-image: url(%1);"
121 "background-position: bottom left;"
122 "background-attachment: fixed;"
123 "background-repeat: no-repeat;"
124 "}")
125 .arg(KStandardDirs::locate("data", "kcm_phonon/listview-background.png")));
126 deviceList->setAlternatingRowColors(false);
127 QStandardItem *parentItem = m_categoryModel.invisibleRootItem();
129 // Audio Output Parent
130 QStandardItem *outputItem = new CategoryItem(Phonon::NoCategory);
131 m_outputModel[Phonon::NoCategory] = new Phonon::AudioOutputDeviceModel;
132 outputItem->setEditable(false);
133 outputItem->setToolTip(i18n("Defines the default ordering of devices which can be overridden by individual categories."));
134 parentItem->appendRow(outputItem);
136 // Audio Capture Parent
137 QStandardItem *captureItem = new CategoryItem(Phonon::NoCategory, false);
138 m_captureModel[Phonon::NoCategory] = new Phonon::AudioCaptureDeviceModel;
139 captureItem->setEditable(false);
140 captureItem->setToolTip(i18n("Defines the default ordering of devices which can be overridden by individual categories."));
141 parentItem->appendRow(captureItem);
143 // Audio Output Children
144 parentItem = outputItem;
145 for (int i = 0; i <= Phonon::LastCategory; ++i) {
146 m_outputModel[i] = new Phonon::AudioOutputDeviceModel;
147 QStandardItem *item = new CategoryItem(static_cast<Phonon::Category>(i));
148 item->setEditable(false);
149 parentItem->appendRow(item);
152 // Audio Capture Children
153 parentItem = captureItem;
154 for (int i = 1; i < captureCategoriesCount; ++i) { // i == 1 to skip NoCategory
155 m_captureModel[captureCategories[i]] = new Phonon::AudioCaptureDeviceModel;
156 QStandardItem *item = new CategoryItem(captureCategories[i], false);
157 item->setEditable(false);
158 parentItem->appendRow(item);
161 categoryTree->setModel(&m_categoryModel);
162 if (categoryTree->header()) {
163 categoryTree->header()->hide();
165 categoryTree->expandAll();
167 connect(categoryTree->selectionModel(),
168 SIGNAL(currentChanged(const QModelIndex &,const QModelIndex &)),
169 SLOT(updateDeviceList()));
171 for (int i = -1; i <= Phonon::LastCategory; ++i) {
172 connect(m_outputModel[i], SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SIGNAL(changed()));
173 connect(m_outputModel[i], SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SIGNAL(changed()));
174 connect(m_outputModel[i], SIGNAL(layoutChanged()), this, SIGNAL(changed()));
175 connect(m_outputModel[i], SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SIGNAL(changed()));
176 if (m_captureModel.contains(i)) {
177 connect(m_captureModel[i], SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SIGNAL(changed()));
178 connect(m_captureModel[i], SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SIGNAL(changed()));
179 connect(m_captureModel[i], SIGNAL(layoutChanged()), this, SIGNAL(changed()));
180 connect(m_captureModel[i], SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SIGNAL(changed()));
183 connect(showCheckBox, SIGNAL(stateChanged (int)), this, SIGNAL(changed()));
184 connect(Phonon::BackendCapabilities::notifier(), SIGNAL(availableAudioOutputDevicesChanged()), SLOT(updateAudioOutputDevices()));
185 connect(Phonon::BackendCapabilities::notifier(), SIGNAL(availableAudioCaptureDevicesChanged()), SLOT(updateAudioCaptureDevices()));
186 connect(Phonon::BackendCapabilities::notifier(), SIGNAL(capabilitiesChanged()), SLOT(updateAudioOutputDevices()));
187 connect(Phonon::BackendCapabilities::notifier(), SIGNAL(capabilitiesChanged()), SLOT(updateAudioCaptureDevices()));
189 if (!categoryTree->currentIndex().isValid()) {
190 categoryTree->setCurrentIndex(m_categoryModel.index(0, 0).child(1, 0));
194 void DevicePreference::updateDeviceList()
196 QStandardItem *currentItem = m_categoryModel.itemFromIndex(categoryTree->currentIndex());
197 KFadeWidgetEffect *animation = new KFadeWidgetEffect(deviceList);
198 if (deviceList->selectionModel()) {
199 disconnect(deviceList->selectionModel(),
200 SIGNAL(currentRowChanged(const QModelIndex &,const QModelIndex &)),
201 this, SLOT(updateButtonsEnabled()));
203 if (currentItem && currentItem->type() == 1001) {
204 CategoryItem *catItem = static_cast<CategoryItem *>(currentItem);
205 const Phonon::Category cat = catItem->category();
206 if (catItem->isOutputItem) {
207 deviceList->setModel(m_outputModel[cat]);
208 } else {
209 deviceList->setModel(m_captureModel[cat]);
211 m_showingOutputModel = catItem->isOutputItem;
212 if (cat == Phonon::NoCategory) {
213 if (catItem->isOutputItem) {
214 m_headerModel.setHeaderData(0, Qt::Horizontal, i18n("Default Output Device Preference"), Qt::DisplayRole);
215 } else {
216 m_headerModel.setHeaderData(0, Qt::Horizontal, i18n("Default Capture Device Preference"), Qt::DisplayRole);
218 } else {
219 if (catItem->isOutputItem) {
220 m_headerModel.setHeaderData(0, Qt::Horizontal, i18n("Output Device Preference for the '%1' Category", Phonon::categoryToString(cat)), Qt::DisplayRole);
221 } else {
222 m_headerModel.setHeaderData(0, Qt::Horizontal, i18n("Capture Device Preference for the '%1' Category", Phonon::categoryToString(cat)), Qt::DisplayRole);
225 } else {
226 m_showingOutputModel = false;
227 m_headerModel.setHeaderData(0, Qt::Horizontal, QString(), Qt::DisplayRole);
228 deviceList->setModel(0);
230 deviceList->header()->setModel(&m_headerModel);
231 updateButtonsEnabled();
232 if (deviceList->selectionModel()) {
233 connect(deviceList->selectionModel(),
234 SIGNAL(currentRowChanged(const QModelIndex &,const QModelIndex &)),
235 this, SLOT(updateButtonsEnabled()));
237 deviceList->resizeColumnToContents(0);
238 animation->start();
241 void DevicePreference::updateAudioCaptureDevices()
243 kDebug();
244 const QList<Phonon::AudioCaptureDevice> list = availableAudioCaptureDevices();
245 QHash<int, Phonon::AudioCaptureDevice> hash;
246 foreach (const Phonon::AudioCaptureDevice &dev, list) {
247 hash.insert(dev.index(), dev);
249 for (int ii = 0; ii < captureCategoriesCount; ++ii) {
250 const int i = captureCategories[ii];
251 Phonon::AudioCaptureDeviceModel *model = m_captureModel.value(i);
252 Q_ASSERT(model);
254 QHash<int, Phonon::AudioCaptureDevice> hashCopy(hash);
255 QList<Phonon::AudioCaptureDevice> orderedList;
256 if (model->rowCount() > 0) {
257 QList<int> order = model->tupleIndexOrder();
258 foreach (int idx, order) {
259 if (hashCopy.contains(idx)) {
260 orderedList << hashCopy.take(idx);
263 if (hashCopy.size() > 1) {
264 // keep the order of the original list
265 foreach (const Phonon::AudioCaptureDevice &dev, list) {
266 if (hashCopy.contains(dev.index())) {
267 orderedList << hashCopy.take(dev.index());
270 } else if (hashCopy.size() == 1) {
271 orderedList += hashCopy.values();
273 model->setModelData(orderedList);
274 } else {
275 model->setModelData(list);
278 deviceList->resizeColumnToContents(0);
281 void DevicePreference::updateAudioOutputDevices()
283 const QList<Phonon::AudioOutputDevice> list = availableAudioOutputDevices();
284 QHash<int, Phonon::AudioOutputDevice> hash;
285 foreach (const Phonon::AudioOutputDevice &dev, list) {
286 hash.insert(dev.index(), dev);
288 for (int i = -1; i <= Phonon::LastCategory; ++i) {
289 Phonon::AudioOutputDeviceModel *model = m_outputModel.value(i);
290 Q_ASSERT(model);
292 QHash<int, Phonon::AudioOutputDevice> hashCopy(hash);
293 QList<Phonon::AudioOutputDevice> orderedList;
294 if (model->rowCount() > 0) {
295 QList<int> order = model->tupleIndexOrder();
296 foreach (int idx, order) {
297 if (hashCopy.contains(idx)) {
298 orderedList << hashCopy.take(idx);
301 if (hashCopy.size() > 1) {
302 // keep the order of the original list
303 foreach (const Phonon::AudioOutputDevice &dev, list) {
304 if (hashCopy.contains(dev.index())) {
305 orderedList << hashCopy.take(dev.index());
308 } else if (hashCopy.size() == 1) {
309 orderedList += hashCopy.values();
311 model->setModelData(orderedList);
312 } else {
313 model->setModelData(list);
316 deviceList->resizeColumnToContents(0);
319 QList<Phonon::AudioOutputDevice> DevicePreference::availableAudioOutputDevices() const
321 QList<Phonon::AudioOutputDevice> ret;
322 const QList<int> deviceIndexes = Phonon::GlobalConfig().audioOutputDeviceListFor(Phonon::NoCategory,
323 showCheckBox->isChecked()
324 ? Phonon::GlobalConfig::ShowAdvancedDevices
325 : Phonon::GlobalConfig::HideAdvancedDevices);
326 foreach (int i, deviceIndexes) {
327 ret.append(Phonon::AudioOutputDevice::fromIndex(i));
329 return ret;
332 QList<Phonon::AudioCaptureDevice> DevicePreference::availableAudioCaptureDevices() const
334 QList<Phonon::AudioCaptureDevice> ret;
335 const QList<int> deviceIndexes = Phonon::GlobalConfig().audioCaptureDeviceListFor(Phonon::NoCategory,
336 showCheckBox->isChecked()
337 ? Phonon::GlobalConfig::ShowAdvancedDevices
338 : Phonon::GlobalConfig::HideAdvancedDevices);
339 kDebug() << deviceIndexes;
340 foreach (int i, deviceIndexes) {
341 ret.append(Phonon::AudioCaptureDevice::fromIndex(i));
343 return ret;
346 void DevicePreference::load()
348 QSettings phononConfig(QLatin1String("kde.org"), QLatin1String("libphonon"));
349 QSettingsGroup outputDeviceGroup(&phononConfig, QLatin1String("AudioOutputDevice"));
350 QSettingsGroup captureDeviceGroup(&phononConfig, QLatin1String("AudioCaptureDevice"));
351 QSettingsGroup generalGroup(&phononConfig, QLatin1String("General"));
352 showCheckBox->setChecked(!generalGroup.value(QLatin1String("HideAdvancedDevices"), true));
355 // the following call returns ordered according to NoCategory
356 const QList<Phonon::AudioOutputDevice> list = availableAudioOutputDevices();
357 m_outputModel[Phonon::NoCategory]->setModelData(list);
359 QHash<int, Phonon::AudioOutputDevice> hash;
360 foreach (const Phonon::AudioOutputDevice &dev, list) {
361 hash.insert(dev.index(), dev);
363 for (int i = 0; i <= Phonon::LastCategory; ++i) {
364 const QString configKey(QLatin1String("Category_") + QString::number(i));
365 if (!outputDeviceGroup.hasKey(configKey)) {
366 m_outputModel[i]->setModelData(list); // use the NoCategory order
367 continue;
369 QHash<int, Phonon::AudioOutputDevice> hashCopy(hash);
370 const QList<int> order = outputDeviceGroup.value(configKey, QList<int>());
371 QList<Phonon::AudioOutputDevice> orderedList;
372 foreach (int idx, order) {
373 if (hashCopy.contains(idx)) {
374 orderedList << hashCopy.take(idx);
377 if (hashCopy.size() > 1) {
378 // keep the order of the original list
379 foreach (const Phonon::AudioOutputDevice &dev, list) {
380 if (hashCopy.contains(dev.index())) {
381 orderedList << hashCopy.take(dev.index());
384 } else if (hashCopy.size() == 1) {
385 orderedList += hashCopy.values();
387 m_outputModel[i]->setModelData(orderedList);
391 // the following call returns ordered according to NoCategory
392 QList<Phonon::AudioCaptureDevice> list = availableAudioCaptureDevices();
393 m_captureModel[Phonon::NoCategory]->setModelData(list);
395 QHash<int, Phonon::AudioCaptureDevice> hash;
396 foreach (const Phonon::AudioCaptureDevice &dev, list) {
397 hash.insert(dev.index(), dev);
399 for (int i = 1; i < captureCategoriesCount; ++i) { // i == 1 to skip NoCategory
400 const Phonon::Category cat = captureCategories[i];
401 const QString configKey(QLatin1String("Category_") + QString::number(cat));
402 if (!captureDeviceGroup.hasKey(configKey)) {
403 m_captureModel[cat]->setModelData(list); // use the NoCategory order
404 continue;
406 QHash<int, Phonon::AudioCaptureDevice> hashCopy(hash);
407 const QList<int> order = captureDeviceGroup.value(configKey, QList<int>());
408 QList<Phonon::AudioCaptureDevice> orderedList;
409 foreach (int idx, order) {
410 if (hashCopy.contains(idx)) {
411 orderedList << hashCopy.take(idx);
414 if (hashCopy.size() > 1) {
415 // keep the order of the original list
416 foreach (const Phonon::AudioCaptureDevice &dev, list) {
417 if (hashCopy.contains(dev.index())) {
418 orderedList << hashCopy.take(dev.index());
421 } else if (hashCopy.size() == 1) {
422 orderedList += hashCopy.values();
424 m_captureModel[cat]->setModelData(orderedList);
428 deviceList->resizeColumnToContents(0);
431 void DevicePreference::save()
433 QSettings config(QLatin1String("kde.org"), QLatin1String("libphonon"));
435 QSettingsGroup generalGroup(&config, QLatin1String("General"));
436 generalGroup.setValue(QLatin1String("HideAdvancedDevices"), !showCheckBox->isChecked());
438 if (!m_removeOnApply.isEmpty()) {
439 QDBusMessage msg = QDBusMessage::createMethodCall("org.kde.kded", "/modules/phononserver",
440 "org.kde.PhononServer", "removeAudioDevices");
441 msg << QVariant::fromValue(m_removeOnApply);
442 QDBusConnection::sessionBus().send(msg);
443 m_removeOnApply.clear();
446 QSettingsGroup globalGroup(&config, QLatin1String("AudioOutputDevice"));
447 const QList<int> noCategoryOrder = m_outputModel.value(Phonon::NoCategory)->tupleIndexOrder();
448 globalGroup.setValue(QLatin1String("Category_") + QString::number(Phonon::NoCategory), noCategoryOrder);
449 for (int i = 0; i <= Phonon::LastCategory; ++i) {
450 Q_ASSERT(m_outputModel.value(i));
451 const QList<int> order = m_outputModel.value(i)->tupleIndexOrder();
452 if (order == noCategoryOrder) {
453 globalGroup.removeEntry(QLatin1String("Category_") + QString::number(i));
454 } else {
455 globalGroup.setValue(QLatin1String("Category_") + QString::number(i), order);
460 QSettingsGroup globalGroup(&config, QLatin1String("AudioCaptureDevice"));
461 const QList<int> noCategoryOrder = m_captureModel.value(Phonon::NoCategory)->tupleIndexOrder();
462 globalGroup.setValue(QLatin1String("Category_") + QString::number(Phonon::NoCategory), noCategoryOrder);
463 for (int i = 1; i < captureCategoriesCount; ++i) {
464 const Phonon::Category cat = captureCategories[i];
465 Q_ASSERT(m_captureModel.value(cat));
466 const QList<int> order = m_captureModel.value(cat)->tupleIndexOrder();
467 if (order == noCategoryOrder) {
468 globalGroup.removeEntry(QLatin1String("Category_") + QString::number(cat));
469 } else {
470 globalGroup.setValue(QLatin1String("Category_") + QString::number(cat), order);
476 void DevicePreference::defaults()
479 QList<Phonon::AudioOutputDevice> list = availableAudioOutputDevices();
480 for (int i = -1; i <= Phonon::LastCategory; ++i) {
481 m_outputModel[i]->setModelData(list);
485 QList<Phonon::AudioCaptureDevice> list = availableAudioCaptureDevices();
486 for (int i = 0; i < captureCategoriesCount; ++i) {
487 m_captureModel[captureCategories[i]]->setModelData(list);
491 deviceList->resizeColumnToContents(0);
494 void DevicePreference::on_preferButton_clicked()
496 QAbstractItemModel *model = deviceList->model();
498 Phonon::AudioOutputDeviceModel *deviceModel = qobject_cast<Phonon::AudioOutputDeviceModel *>(model);
499 if (deviceModel) {
500 deviceModel->moveUp(deviceList->currentIndex());
501 updateButtonsEnabled();
502 emit changed();
506 Phonon::AudioCaptureDeviceModel *deviceModel = qobject_cast<Phonon::AudioCaptureDeviceModel *>(model);
507 if (deviceModel) {
508 deviceModel->moveUp(deviceList->currentIndex());
509 updateButtonsEnabled();
510 emit changed();
515 void DevicePreference::on_deferButton_clicked()
517 QAbstractItemModel *model = deviceList->model();
519 Phonon::AudioOutputDeviceModel *deviceModel = qobject_cast<Phonon::AudioOutputDeviceModel *>(model);
520 if (deviceModel) {
521 deviceModel->moveDown(deviceList->currentIndex());
522 updateButtonsEnabled();
523 emit changed();
527 Phonon::AudioCaptureDeviceModel *deviceModel = qobject_cast<Phonon::AudioCaptureDeviceModel *>(model);
528 if (deviceModel) {
529 deviceModel->moveDown(deviceList->currentIndex());
530 updateButtonsEnabled();
531 emit changed();
536 template<Phonon::ObjectDescriptionType T>
537 void DevicePreference::removeDevice(const Phonon::ObjectDescription<T> &deviceToRemove,
538 QMap<int, Phonon::ObjectDescriptionModel<T> *> *modelMap)
540 QDBusInterface phononServer(QLatin1String("org.kde.kded"), QLatin1String("/modules/phononserver"),
541 QLatin1String("org.kde.PhononServer"));
542 QDBusReply<bool> reply = phononServer.call(QLatin1String("isAudioDeviceRemovable"), deviceToRemove.index());
543 if (!reply.isValid()) {
544 kError(600) << reply.error();
545 return;
547 if (!reply.value()) {
548 return;
550 m_removeOnApply << deviceToRemove.index();
552 // remove from all models, idx.row() is only correct for the current model
553 foreach (Phonon::ObjectDescriptionModel<T> *model, *modelMap) {
554 QList<Phonon::ObjectDescription<T> > data = model->modelData();
555 for (int row = 0; row < data.size(); ++row) {
556 if (data[row] == deviceToRemove) {
557 model->removeRows(row, 1);
558 break;
562 updateButtonsEnabled();
563 emit changed();
566 void DevicePreference::on_removeButton_clicked()
568 const QModelIndex idx = deviceList->currentIndex();
570 QAbstractItemModel *model = deviceList->model();
571 Phonon::AudioOutputDeviceModel *playbackModel = qobject_cast<Phonon::AudioOutputDeviceModel *>(model);
572 if (playbackModel && idx.isValid()) {
573 removeDevice(playbackModel->modelData(idx), &m_outputModel);
574 } else {
575 Phonon::AudioCaptureDeviceModel *captureModel = qobject_cast<Phonon::AudioCaptureDeviceModel *>(model);
576 if (captureModel && idx.isValid()) {
577 removeDevice(captureModel->modelData(idx), &m_captureModel);
581 deviceList->resizeColumnToContents(0);
584 void DevicePreference::on_applyPreferencesButton_clicked()
586 const QModelIndex idx = categoryTree->currentIndex();
587 const QStandardItem *item = m_categoryModel.itemFromIndex(idx);
588 if( !item )
589 return;
590 Q_ASSERT(item->type() == 1001);
591 const CategoryItem *catItem = static_cast<const CategoryItem *>(item);
592 const QList<Phonon::AudioOutputDevice> modelData = m_outputModel.value(catItem->category())->modelData();
594 KDialog dialog(this);
595 dialog.setButtons(KDialog::Ok | KDialog::Cancel);
596 dialog.setDefaultButton(KDialog::Ok);
598 QWidget mainWidget(&dialog);
599 dialog.setMainWidget(&mainWidget);
601 QLabel label(&mainWidget);
602 label.setText(i18n("Apply the currently shown device preference list to the following other "
603 "audio output categories:"));
604 label.setWordWrap(true);
606 KListWidget list(&mainWidget);
607 for (Phonon::Category cat = Phonon::NoCategory; cat <= Phonon::LastCategory; ++cat) {
608 QListWidgetItem *item = new QListWidgetItem(cat == Phonon::NoCategory
609 ? i18n("Default/Unspecified Category") : Phonon::categoryToString(cat), &list, cat);
610 item->setCheckState(Qt::Checked);
611 if (cat == catItem->category()) {
612 item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
616 QVBoxLayout layout(&mainWidget);
617 layout.setMargin(0);
618 layout.addWidget(&label);
619 layout.addWidget(&list);
621 switch (dialog.exec()) {
622 case QDialog::Accepted:
623 for (Phonon::Category cat = Phonon::NoCategory; cat <= Phonon::LastCategory; ++cat) {
624 if (cat != catItem->category()) {
625 QListWidgetItem *item = list.item(static_cast<int>(cat) + 1);
626 Q_ASSERT(item->type() == cat);
627 if (item->checkState() == Qt::Checked) {
628 m_outputModel.value(cat)->setModelData(modelData);
632 break;
633 case QDialog::Rejected:
634 // nothing to do
635 break;
639 void DevicePreference::on_showCheckBox_toggled()
642 // the following call returns ordered according to NoCategory
643 const QList<Phonon::AudioOutputDevice> list = availableAudioOutputDevices();
644 m_outputModel[Phonon::NoCategory]->setModelData(list);
646 QHash<int, Phonon::AudioOutputDevice> hash;
647 foreach (const Phonon::AudioOutputDevice &dev, list) {
648 hash.insert(dev.index(), dev);
650 for (int i = 0; i <= Phonon::LastCategory; ++i) {
651 QHash<int, Phonon::AudioOutputDevice> hashCopy(hash);
652 const QList<int> order = m_outputModel[i]->tupleIndexOrder();
653 QList<Phonon::AudioOutputDevice> orderedList;
654 foreach (int idx, order) {
655 if (hashCopy.contains(idx)) {
656 orderedList << hashCopy.take(idx);
659 if (hashCopy.size() > 1) {
660 // keep the order of the original list
661 foreach (const Phonon::AudioOutputDevice &dev, list) {
662 if (hashCopy.contains(dev.index())) {
663 orderedList << hashCopy.take(dev.index());
666 } else if (hashCopy.size() == 1) {
667 orderedList += hashCopy.values();
669 m_outputModel[i]->setModelData(orderedList);
673 // the following call returns ordered according to NoCategory
674 const QList<Phonon::AudioCaptureDevice> list = availableAudioCaptureDevices();
675 m_captureModel[Phonon::NoCategory]->setModelData(list);
677 QHash<int, Phonon::AudioCaptureDevice> hash;
678 foreach (const Phonon::AudioCaptureDevice &dev, list) {
679 hash.insert(dev.index(), dev);
681 for (int i = 1; i < captureCategoriesCount; ++i) {
682 const Phonon::Category cat = captureCategories[i];
683 QHash<int, Phonon::AudioCaptureDevice> hashCopy(hash);
684 const QList<int> order = m_captureModel[cat]->tupleIndexOrder();
685 QList<Phonon::AudioCaptureDevice> orderedList;
686 foreach (int idx, order) {
687 if (hashCopy.contains(idx)) {
688 orderedList << hashCopy.take(idx);
691 if (hashCopy.size() > 1) {
692 // keep the order of the original list
693 foreach (const Phonon::AudioCaptureDevice &dev, list) {
694 if (hashCopy.contains(dev.index())) {
695 orderedList << hashCopy.take(dev.index());
698 } else if (hashCopy.size() == 1) {
699 orderedList += hashCopy.values();
701 m_captureModel[cat]->setModelData(orderedList);
704 deviceList->resizeColumnToContents(0);
707 void DevicePreference::on_testPlaybackButton_toggled(bool down)
709 if (down) {
710 QModelIndex idx = deviceList->currentIndex();
711 if (!idx.isValid() || !m_showingOutputModel) {
712 return;
714 const Phonon::AudioOutputDeviceModel *model = static_cast<const Phonon::AudioOutputDeviceModel *>(idx.model());
715 const Phonon::AudioOutputDevice &device = model->modelData(idx);
716 m_media = new Phonon::MediaObject(this);
717 m_output = new Phonon::AudioOutput(this);
718 m_output->setOutputDevice(device);
720 // just to be very sure that nothing messes our test sound up
721 m_output->setVolume(1.0);
722 m_output->setMuted(false);
724 Phonon::createPath(m_media, m_output);
725 connect(m_media, SIGNAL(finished()), testPlaybackButton, SLOT(toggle()));
726 m_media->setCurrentSource(KStandardDirs::locate("sound", "KDE-Sys-Log-In.ogg"));
727 m_media->play();
728 } else {
729 disconnect(m_media, SIGNAL(finished()), testPlaybackButton, SLOT(toggle()));
730 delete m_media;
731 m_media = 0;
732 delete m_output;
733 m_output = 0;
737 void DevicePreference::updateButtonsEnabled()
739 //kDebug() ;
740 if (deviceList->model()) {
741 //kDebug() << "model available";
742 QModelIndex idx = deviceList->currentIndex();
743 preferButton->setEnabled(idx.isValid() && idx.row() > 0);
744 deferButton->setEnabled(idx.isValid() && idx.row() < deviceList->model()->rowCount() - 1);
745 removeButton->setEnabled(idx.isValid() && !(idx.flags() & Qt::ItemIsEnabled));
746 testPlaybackButton->setEnabled(m_showingOutputModel && idx.isValid() &&
747 (idx.flags() & Qt::ItemIsEnabled));
748 } else {
749 preferButton->setEnabled(false);
750 deferButton->setEnabled(false);
751 removeButton->setEnabled(false);
752 testPlaybackButton->setEnabled(false);
756 #include "moc_devicepreference.cpp"
757 // vim: sw=4 ts=4