/*
 * Cantata
 *
 * Copyright (c) 2011-2014 Craig Drummond <craig.p.drummond@gmail.com>
 *
 * ----
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "devicespage.h"
#include "musiclibraryitemroot.h"
#include "musiclibraryitemartist.h"
#include "musiclibraryitemalbum.h"
#include "musiclibraryitemsong.h"
#include "mainwindow.h"
#include "devicesmodel.h"
#include "settings.h"
#include "messagebox.h"
#include "localize.h"
#include "icons.h"
#include "action.h"
#include "actioncollection.h"
#include "stdactions.h"
#ifdef ENABLE_KDE_SUPPORT
#include <KDE/KGlobalSettings>
#endif
#ifdef ENABLE_REMOTE_DEVICES
#include "remotedevicepropertiesdialog.h"
#include "devicepropertieswidget.h"
#endif
#include "syncdialog.h"
#ifdef ENABLE_REPLAYGAIN_SUPPORT
#include "rgdialog.h"
#endif
#include "tageditor.h"
#include "actiondialog.h"
#include "trackorganiser.h"
#include "preferencesdialog.h"
#include "coverdialog.h"
#include "mpdconnection.h"
#if defined CDDB_FOUND || defined MUSICBRAINZ5_FOUND
#include "audiocddevice.h"
#include "albumdetailsdialog.h"
#include "cddbselectiondialog.h"
#endif

DevicesPage::DevicesPage(QWidget *p)
    : QWidget(p)
{
    setupUi(this);
    copyAction = ActionCollection::get()->createAction("copytolibrary", i18n("Copy To Library"), Icons::self()->importIcon);
    copyToLibraryButton->setDefaultAction(copyAction);
    syncAction = ActionCollection::get()->createAction("syncdevice", i18n("Sync"), "folder-sync");
    connect(syncAction, SIGNAL(triggered()), this, SLOT(sync()));
    #ifdef ENABLE_REMOTE_DEVICES
    forgetDeviceAction=ActionCollection::get()->createAction("forgetdevice", i18n("Forget Device"), "list-remove");
    connect(forgetDeviceAction, SIGNAL(triggered()), this, SLOT(forgetRemoteDevice()));
    #endif
    connect(DevicesModel::self()->connectAct(), SIGNAL(triggered()), this, SLOT(toggleDevice()));
    connect(DevicesModel::self()->disconnectAct(), SIGNAL(triggered()), this, SLOT(toggleDevice()));
    copyToLibraryButton->setEnabled(false);
    syncAction->setEnabled(false);
    view->addAction(copyAction);
    view->addAction(syncAction);
    view->addAction(StdActions::self()->organiseFilesAction);
    view->addAction(StdActions::self()->editTagsAction);
    #ifdef ENABLE_REPLAYGAIN_SUPPORT
    view->addAction(StdActions::self()->replaygainAction);
    #endif
    #ifdef ENABLE_REMOTE_DEVICES
    QAction *sepA=new QAction(this);
    sepA->setSeparator(true);
    view->addAction(sepA);
    view->addAction(forgetDeviceAction);
    #endif
    QAction *sep=new QAction(this);
    sep->setSeparator(true);
    view->addAction(sep);
    view->addAction(StdActions::self()->deleteSongsAction);
    connect(this, SIGNAL(add(const QStringList &, bool, quint8)), MPDConnection::self(), SLOT(add(const QStringList &, bool, quint8)));
    connect(this, SIGNAL(addSongsToPlaylist(const QString &, const QStringList &)), MPDConnection::self(), SLOT(addToPlaylist(const QString &, const QStringList &)));
    connect(genreCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(searchItems()));
    connect(DevicesModel::self(), SIGNAL(updateGenres(const QSet<QString> &)), genreCombo, SLOT(update(const QSet<QString> &)));
    connect(DevicesModel::self(), SIGNAL(updated(QModelIndex)), this, SLOT(updated(QModelIndex)));
    connect(view, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(itemDoubleClicked(const QModelIndex &)));
    connect(view, SIGNAL(searchItems()), this, SLOT(searchItems()));
    connect(view, SIGNAL(itemsSelected(bool)), SLOT(controlActions()));
    connect(view, SIGNAL(rootIndexSet(QModelIndex)), this, SLOT(updateGenres(QModelIndex)));
    connect(copyAction, SIGNAL(triggered()), this, SLOT(copyToLibrary()));
    connect(DevicesModel::self()->configureAct(), SIGNAL(triggered()), this, SLOT(configureDevice()));
    connect(DevicesModel::self()->refreshAct(), SIGNAL(triggered()), this, SLOT(refreshDevice()));
    #if defined CDDB_FOUND || defined MUSICBRAINZ5_FOUND
    connect(DevicesModel::self()->editAct(), SIGNAL(triggered()), this, SLOT(editDetails()));
    connect(DevicesModel::self(), SIGNAL(matches(const QString &, const QList<CdAlbum> &)),
            SLOT(cdMatches(const QString &, const QList<CdAlbum> &)));
    #endif
    QMenu *menu=new QMenu(this);
    #ifdef ENABLE_REMOTE_DEVICES
    Action *addRemote=ActionCollection::get()->createAction("adddevice", i18n("Add Device"), "network-server");
    connect(addRemote, SIGNAL(triggered()), this, SLOT(addRemoteDevice()));
    menu->addAction(addRemote);
    menu->addAction(forgetDeviceAction);
    menu->addSeparator();
    #endif
    menu->addAction(DevicesModel::self()->configureAct());
    menu->addAction(DevicesModel::self()->refreshAct());
    menu->addSeparator();
    menu->addAction(StdActions::self()->organiseFilesAction);
    menu->addAction(StdActions::self()->editTagsAction);
    #ifdef ENABLE_REPLAYGAIN_SUPPORT
    menu->addAction(StdActions::self()->replaygainAction);
    #endif
    menuButton->setMenu(menu);
    proxy.setSourceModel(DevicesModel::self());
    view->setModel(&proxy);
    view->setRootIsDecorated(false);
    view->setSearchResetLevel(1);
}

DevicesPage::~DevicesPage()
{
}

void DevicesPage::showEvent(QShowEvent *e)
{
    view->focusView();
    QWidget::showEvent(e);
}

void DevicesPage::clear()
{
    DevicesModel::self()->clear();
    view->goToTop();
}

QString DevicesPage::activeFsDeviceUdi() const
{
    Device *dev=activeFsDevice();
    return dev ? dev->id() : QString();
}

Device * DevicesPage::activeFsDevice() const
{
    const QModelIndexList selected = view->selectedIndexes(false); // Dont need sorted selection here...

    if (selected.isEmpty()) {
        return 0;
    }

    QString udi;
    Device *activeDev=0;
    foreach (const QModelIndex &idx, selected) {
        QModelIndex index = proxy.mapToSource(idx);
        MusicLibraryItem *item=static_cast<MusicLibraryItem *>(index.internalPointer());

        if (item && MusicLibraryItem::Type_Root!=item->itemType()) {
            while(item->parentItem()) {
                item=item->parentItem();
            }
        }

        if (item && MusicLibraryItem::Type_Root==item->itemType()) {
            Device *dev=static_cast<Device *>(item);
            if (Device::Ums!=dev->devType() && Device::RemoteFs!=dev->devType()) {
                return 0;
            }
            if (activeDev) {
                return 0;
            }
            activeDev=dev;
        }
    }

    return activeDev;
}

QStringList DevicesPage::playableUrls() const
{
    QModelIndexList selected = view->selectedIndexes();
    if (selected.isEmpty()) {
        return QStringList();
    }

    QModelIndexList mapped;
    foreach (const QModelIndex &idx, selected) {
        mapped.append(proxy.mapToSource(idx));
    }

    return DevicesModel::self()->playableUrls(mapped);
}

QList<Song> DevicesPage::selectedSongs(bool allowPlaylists) const
{
    Q_UNUSED(allowPlaylists)
    QModelIndexList selected = view->selectedIndexes();
    if (selected.isEmpty()) {
        return QList<Song>();
    }

    // Ensure all songs are from UMS/Remote devices...
    QString udi;
    QModelIndexList mapped;
    foreach (const QModelIndex &idx, selected) {
        QModelIndex index = proxy.mapToSource(idx);
        mapped.append(index);
        MusicLibraryItem *item=static_cast<MusicLibraryItem *>(index.internalPointer());

        if (item && MusicLibraryItem::Type_Root!=item->itemType()) {
            while(item->parentItem()) {
                item=item->parentItem();
            }
        }

        if (item && MusicLibraryItem::Type_Root==item->itemType()) {
            Device *dev=static_cast<Device *>(item);
            if (Device::Ums!=dev->devType() && Device::RemoteFs!=dev->devType()) {
                return QList<Song>();
            }
        }
    }

    return DevicesModel::self()->songs(mapped);
}

void DevicesPage::addSelectionToPlaylist(const QString &name, bool replace, quint8 priorty, bool randomAlbums)
{
    Q_UNUSED(randomAlbums)
    QStringList files=playableUrls();

    if (!files.isEmpty()) {
        if (name.isEmpty()) {
            emit add(files, replace, priorty);
        } else {
            emit addSongsToPlaylist(name, files);
        }
        view->clearSelection();
    }
}

void DevicesPage::refresh()
{
    view->goToTop();
    DevicesModel::self()->resetModel();
    if (ItemView::Mode_SimpleTree==view->viewMode() || ItemView::Mode_DetailedTree==view->viewMode()) {
        for (int i=0; i<DevicesModel::self()->rowCount(QModelIndex()); ++i) {
            view->setExpanded(proxy.mapFromSource(DevicesModel::self()->index(i, 0, QModelIndex())));
        }
    }
}

void DevicesPage::itemDoubleClicked(const QModelIndex &)
{
//     const QModelIndexList selected = view->selectedIndexes();
//     if (1!=selected.size()) {
//         return; //doubleclick should only have one selected item
//     }
//     MusicDevicesItem *item = DevicesModel::self()->toItem(proxy.mapToSource(selected.at(0)));
//     if (MusicDevicesItem::Type_Song==item->itemType()) {
//         addSelectionToPlaylist();
//     }
}

void DevicesPage::searchItems()
{
    QString text=view->searchText().trimmed();
    proxy.update(text, genreCombo->currentIndex()<=0 ? QString() : genreCombo->currentText());
    if (proxy.enabled() && !proxy.filterText().isEmpty()) {
        view->expandAll();
    }
}

void DevicesPage::controlActions()
{
    QModelIndexList selected=view->selectedIndexes(false); // Dont need sorted selection here...
    bool haveTracks=false;
    bool onlyFs=true;
    bool singleUdi=true;
    bool connected=false;
    #ifdef ENABLE_REMOTE_DEVICES
    bool remoteDev=false;
    #endif
    bool deviceSelected=false;
    bool busyDevice=false;
    bool audioCd=false;
    bool canPlay=false;
    QString udi;

    foreach (const QModelIndex &idx, selected) {
        MusicLibraryItem *item=static_cast<MusicLibraryItem *>(proxy.mapToSource(idx).internalPointer());

        if (item && MusicLibraryItem::Type_Root==item->itemType()) {
            deviceSelected=true;
        }

        if (item && MusicLibraryItem::Type_Root!=item->itemType()) {
            while(item->parentItem()) {
                item=item->parentItem();
            }
        }

        if (item && MusicLibraryItem::Type_Root==item->itemType()) {
            Device *dev=static_cast<Device *>(item);
            if (!dev->isStdFs()) {
                onlyFs=false;
            }
            if (!dev->isIdle()) {
                busyDevice=true;
            }
            if (Device::AudioCd==dev->devType()) {
                audioCd=true;
            }
            #ifdef ENABLE_REMOTE_DEVICES
            else if (Device::RemoteFs==dev->devType()) {
                remoteDev=true;
            }
            #endif
            canPlay=dev->canPlaySongs();
            if (udi.isEmpty()) {
                udi=dev->id();
            } else if (udi!=dev->id()) {
                singleUdi=false;
            }
            if (!haveTracks) {
                haveTracks=dev->childCount()>0;
            }
            connected=dev->isConnected();
        }
    }

    DevicesModel::self()->configureAct()->setEnabled(!busyDevice && 1==selected.count() && !audioCd);
    DevicesModel::self()->refreshAct()->setEnabled(!busyDevice && 1==selected.count());
    copyAction->setEnabled(!busyDevice && haveTracks && (!deviceSelected || audioCd));
    syncAction->setEnabled(!audioCd && !busyDevice && deviceSelected && connected && 1==selected.count() && singleUdi &&
                           MPDConnection::self()->getDetails().dirReadable);
    StdActions::self()->deleteSongsAction->setEnabled(!audioCd && !busyDevice && haveTracks && !deviceSelected);
    StdActions::self()->editTagsAction->setEnabled(!busyDevice && haveTracks && onlyFs && singleUdi && !deviceSelected);
    #ifdef ENABLE_REPLAYGAIN_SUPPORT
    StdActions::self()->replaygainAction->setEnabled(!busyDevice && haveTracks && onlyFs && singleUdi && !deviceSelected);
    #endif
    StdActions::self()->organiseFilesAction->setEnabled(!busyDevice && haveTracks && onlyFs && singleUdi && !deviceSelected);
    StdActions::self()->addToPlayQueueAction->setEnabled(canPlay && !selected.isEmpty() && singleUdi && !busyDevice && haveTracks && (audioCd || !deviceSelected));
    StdActions::self()->addWithPriorityAction->setEnabled(StdActions::self()->addToPlayQueueAction->isEnabled());
    StdActions::self()->replacePlayQueueAction->setEnabled(StdActions::self()->addToPlayQueueAction->isEnabled());
    #ifdef ENABLE_REMOTE_DEVICES
    forgetDeviceAction->setEnabled(singleUdi && remoteDev);
    #endif
    #if defined CDDB_FOUND || defined MUSICBRAINZ5_FOUND
    DevicesModel::self()->editAct()->setEnabled(!AlbumDetailsDialog::instanceCount() && !busyDevice && 1==selected.count() && audioCd && haveTracks && deviceSelected);
    #endif
    menuButton->controlState();
}

void DevicesPage::copyToLibrary()
{
    const QModelIndexList selected = view->selectedIndexes();

    if (selected.isEmpty()) {
        return;
    }

    QModelIndexList mapped;
    foreach (const QModelIndex &idx, selected) {
        mapped.append(proxy.mapToSource(idx));
    }

    MusicLibraryItem *item=static_cast<MusicLibraryItem *>(mapped.first().internalPointer());
    while (item->parentItem()) {
        item=item->parentItem();
    }
    QString udi;
    if (MusicLibraryItem::Type_Root==item->itemType()) {
        udi=static_cast<Device *>(item)->id();
    }

    if (udi.isEmpty()) {
        return;
    }

    QList<Song> songs=DevicesModel::self()->songs(mapped);

    if (!songs.isEmpty()) {
        emit addToDevice(udi, QString(), songs);
        view->clearSelection();
    }
}

void DevicesPage::configureDevice()
{
    const QModelIndexList selected = view->selectedIndexes(false); // Dont need sorted selection here...

    if (1!=selected.size()) {
        return;
    }

    MusicLibraryItem *item=static_cast<MusicLibraryItem *>(proxy.mapToSource(selected.first()).internalPointer());

    if (MusicLibraryItem::Type_Root==item->itemType()) {
        static_cast<Device *>(item)->configure(this);
    }
}

void DevicesPage::refreshDevice()
{
    const QModelIndexList selected = view->selectedIndexes(false); // Dont need sorted selection here...

    if (1!=selected.size()) {
        return;
    }

    MusicLibraryItem *item=static_cast<MusicLibraryItem *>(proxy.mapToSource(selected.first()).internalPointer());

    if (MusicLibraryItem::Type_Root==item->itemType()) {
        Device *dev=static_cast<Device *>(item);
        QString udi=dev->id();
        bool full=true;

        if (Device::AudioCd==dev->devType()) {
            // Bit hacky - we use 'full' to determine CDDB/MusicBrainz!
            #if defined CDDB_FOUND && defined MUSICBRAINZ5_FOUND
            switch (MessageBox::questionYesNoCancel(this, i18n("Lookup album and track details?"),
                                                    i18n("Refresh"), GuiItem(i18n("Via CDDB")), GuiItem(i18n("Via MusicBrainz")))) {
            case MessageBox::Yes:
                full=true; // full==true => CDDB
                break;
            case MessageBox::No:
                full=false; // full==false => MusicBrainz
                break;
            default:
                return;
            }
            #else
            if (MessageBox::No==MessageBox::questionYesNo(this, i18n("Lookup album and track details?"),
                                                          i18n("Refresh"), GuiItem(i18n("Refresh")), StdGuiItem::cancel())) {
                return;
            }
            #endif
            dev=DevicesModel::self()->device(udi);
        } else {
            if (dev->childCount() && Device::Mtp!=dev->devType()) {
                switch (MessageBox::questionYesNoCancel(this, i18n("<p>Which type of refresh do you wish to perform?<ul>"
                                                                   "<li>Partial - Only new songs are scanned <i>(quick)</i></li>"
                                                                   "<li>Full - All songs are rescanned <i>(slow)</i></li></ul></p>"),
                                                        i18n("Refresh"), GuiItem(i18n("Partial")), GuiItem(i18n("Full")))) {
                case MessageBox::Yes:
                    full=false;
                case MessageBox::No:
                    break;
                default:
                    return;
                }
                // We have to query for device again, as it could have been unplugged whilst the above question dialog was visible...
                dev=DevicesModel::self()->device(udi);
            }
        }
        if (dev) {
            dev->rescan(full);
        }
    }
}

void DevicesPage::deleteSongs()
{
    const QModelIndexList selected = view->selectedIndexes();

    if (selected.isEmpty()) {
        return;
    }

    QModelIndexList mapped;
    foreach (const QModelIndex &idx, selected) {
        mapped.append(proxy.mapToSource(idx));
    }

    MusicLibraryItem *item=static_cast<MusicLibraryItem *>(mapped.first().internalPointer());
    while (item->parentItem()) {
        item=item->parentItem();
    }
    QString udi;
    if (MusicLibraryItem::Type_Root==item->itemType()) {
        udi=static_cast<Device *>(item)->id();
    }

    if (udi.isEmpty()) {
        return;
    }

    QList<Song> songs=DevicesModel::self()->songs(mapped);

    if (!songs.isEmpty()) {
        if (MessageBox::Yes==MessageBox::warningYesNo(this, i18n("Are you sure you wish to delete the selected songs?\nThis cannot be undone."),
                                                      i18n("Delete Songs"), StdGuiItem::del(), StdGuiItem::cancel())) {
            emit deleteSongs(udi, songs);
        }
        view->clearSelection();
    }
}

void DevicesPage::addRemoteDevice()
{
    #ifdef ENABLE_REMOTE_DEVICES
    RemoteDevicePropertiesDialog *dlg=new RemoteDevicePropertiesDialog(this);
    dlg->show(DeviceOptions(QLatin1String("cover.jpg")), RemoteFsDevice::Details(), DevicePropertiesWidget::Prop_All-DevicePropertiesWidget::Prop_Folder, true);
    connect(dlg, SIGNAL(updatedSettings(const DeviceOptions &, RemoteFsDevice::Details)),
            DevicesModel::self(), SLOT(addRemoteDevice(const DeviceOptions &, RemoteFsDevice::Details)));
    #endif
}

void DevicesPage::forgetRemoteDevice()
{
    #ifdef ENABLE_REMOTE_DEVICES
    Device *dev=activeFsDevice();
    if (!dev) {
        return;
    }
    QString udi=dev->id();
    QString devName=dev->data();
    if (MessageBox::Yes==MessageBox::warningYesNo(this, i18n("Are you sure you wish to forget <b>%1</b>?", devName))) {
        DevicesModel::self()->removeRemoteDevice(udi);
    }
    #endif
}

void DevicesPage::toggleDevice()
{
    const QModelIndexList selected = view->selectedIndexes(false); // Dont need sorted selection here...
    if (1!=selected.size()) {
        return;
    }

    MusicLibraryItem *item=static_cast<MusicLibraryItem *>(proxy.mapToSource(selected.first()).internalPointer());

    if (MusicLibraryItem::Type_Root==item->itemType()) {
        Device *dev=static_cast<Device *>(item);
        if (dev->isConnected() &&
            (Device::AudioCd==dev->devType()
                ? MessageBox::No==MessageBox::warningYesNo(this, i18n("Are you sure you wish to eject Audio CD <b>%1 - %2</b>?", dev->data(), dev->subText()),
                                                           i18n("Eject"), GuiItem(i18n("Eject")), StdGuiItem::cancel())
                : MessageBox::No==MessageBox::warningYesNo(this, i18n("Are you sure you wish to disconnect <b>%1</b>?", dev->data()),
                                                           i18n("Disconnect"), GuiItem(i18n("Disconnect")), StdGuiItem::cancel()))) {
            return;
        }
        static_cast<Device *>(item)->toggle();
    }
}

void DevicesPage::sync()
{
    if (0!=SyncDialog::instanceCount()) {
        return;
    }

    if (0!=PreferencesDialog::instanceCount() || 0!=TagEditor::instanceCount() || 0!=TrackOrganiser::instanceCount()
        || 0!=ActionDialog::instanceCount() || 0!=CoverDialog::instanceCount()
        #ifdef ENABLE_REPLAYGAIN_SUPPORT
        || 0!=RgDialog::instanceCount()
        #endif
        ) {
        MessageBox::error(this, i18n("Please close other dialogs first."));
        return;
    }

    const QModelIndexList selected = view->selectedIndexes();

    if (1!=selected.size()) {
        return;
    }

    MusicLibraryItem *item=static_cast<MusicLibraryItem *>(proxy.mapToSource(selected.first()).internalPointer());

    if (MusicLibraryItem::Type_Root==item->itemType()) {
        SyncDialog *dlg=new SyncDialog(this);
        dlg->sync(static_cast<Device *>(item)->id());
    }
}

void DevicesPage::updateGenres(const QModelIndex &idx)
{
    if (idx.isValid()) {
        QModelIndex m=proxy.mapToSource(idx);
        if (m.isValid()) {
            MusicLibraryItem *item=static_cast<MusicLibraryItem *>(m.internalPointer());
            MusicLibraryItem::Type itemType=item->itemType();
            if (itemType==MusicLibraryItem::Type_Root) {
                genreCombo->update(static_cast<MusicLibraryItemRoot *>(item)->genres());
                return;
            } else if (itemType==MusicLibraryItem::Type_Artist) {
                genreCombo->update(static_cast<MusicLibraryItemArtist *>(item)->genres());
                return;
            } else if (itemType==MusicLibraryItem::Type_Album) {
                genreCombo->update(static_cast<MusicLibraryItemAlbum *>(item)->genres());
                return;
            }
        }
    }
    genreCombo->update(DevicesModel::self()->genres());
}

void DevicesPage::updated(const QModelIndex &idx)
{
    view->setExpanded(proxy.mapFromSource(idx));
}

void DevicesPage::cdMatches(const QString &udi, const QList<CdAlbum> &albums)
{
    #if defined CDDB_FOUND || defined MUSICBRAINZ5_FOUND
    int chosen=0;
    Device *dev=DevicesModel::self()->device(udi);
    if (dev && Device::AudioCd==dev->devType()) {
        if (Device::AudioCd==dev->devType()) {
            CddbSelectionDialog *dlg=new CddbSelectionDialog(this);
            chosen=dlg->select(albums);
            if (chosen<0 || chosen>=albums.count()) {
                chosen=0;
            }
        }
    }

    // Need to get device again, as it may have been removed!
    dev=DevicesModel::self()->device(udi);
    if (dev && Device::AudioCd==dev->devType()) {
        if (Device::AudioCd==dev->devType()) {
            static_cast<AudioCdDevice *>(dev)->setDetails(albums.at(chosen));
        }
    }
    #else
    Q_UNUSED(udi)
    Q_UNUSED(albums)
    #endif
}

void DevicesPage::editDetails()
{
    #if defined CDDB_FOUND || defined MUSICBRAINZ5_FOUND
    if (AlbumDetailsDialog::instanceCount()) {
        return;
    }
    const QModelIndexList selected = view->selectedIndexes(false); // Dont need sorted selection here...
    if (1!=selected.size()) {
        return;
    }

    MusicLibraryItem *item=static_cast<MusicLibraryItem *>(proxy.mapToSource(selected.first()).internalPointer());

    if (MusicLibraryItem::Type_Root==item->itemType()) {
        Device *dev=static_cast<Device *>(item);
        if (Device::AudioCd==dev->devType()) {
            AlbumDetailsDialog *dlg=new AlbumDetailsDialog(this);
            dlg->show(static_cast<AudioCdDevice *>(dev));
        }
    }
    #endif
}
