coverdialog.cpp 5.86 KB
Newer Older
1 2
/**
 * Copyright (C) 2005 Michael Pyne <mpyne@kde.org>
Arnold Dumas's avatar
Arnold Dumas committed
3
 * Copyright (C) 2014 Arnold Dumas <contact@arnolddumas.fr>
4 5 6 7 8 9 10 11 12 13 14 15 16
 *
 * 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.  If not, see <http://www.gnu.org/licenses/>.
 */
17

18 19
#include "coverdialog.h"

Michael Pyne's avatar
Michael Pyne committed
20
#include <kiconloader.h>
21
#include <kapplication.h>
Laurent Montel's avatar
Laurent Montel committed
22
#include <kmenu.h>
23 24
#include <klocale.h>

25
#include <QTimer>
26

Michael Pyne's avatar
Michael Pyne committed
27
#include "covericonview.h"
28 29 30
#include "covermanager.h"
#include "collectionlist.h"

Michael Pyne's avatar
Michael Pyne committed
31
using CoverUtility::CoverIconViewItem;
32

33
class AllArtistsListViewItem : public QListWidgetItem
34 35
{
public:
36 37
    AllArtistsListViewItem(KListWidget *parent) :
        QListWidgetItem(i18n("&lt;All Artists&gt;"), parent)
38 39 40
    {
    }

41
    bool operator< (const QListWidgetItem& other) const
42
    {
43 44
        Q_UNUSED(other);
        return true; // Always be at the top.
45 46 47
    }
};

48
class CaseInsensitiveItem : public QListWidgetItem
49 50
{
public:
51 52
    CaseInsensitiveItem(KListWidget *parent, const QString &text) :
        QListWidgetItem(text, parent)
53 54 55
    {
    }

56
    bool operator< (const QListWidgetItem& other) const
57
    {
58
        return text().toLower().localeAwareCompare(other.text().toLower());
59 60 61
    }
};

62
CoverDialog::CoverDialog(QWidget *parent) :
63
    QWidget(parent, Qt::Dialog)
64
{
Tim Beaulen's avatar
Tim Beaulen committed
65 66
    setupUi(this);

Laurent Montel's avatar
Laurent Montel committed
67
    setObjectName( QLatin1String("juk_cover_dialog" ));
Tim Beaulen's avatar
Tim Beaulen committed
68

69
    m_searchLine->setClearButtonShown(true);
Michael Pyne's avatar
Michael Pyne committed
70

71 72 73 74 75 76 77 78
    connect(m_artists, SIGNAL(itemClicked(QListWidgetItem*)),
            this, SLOT(slotArtistClicked(QListWidgetItem*)));

    connect(m_covers, SIGNAL(customContextMenuRequested(QPoint)),
            this, SLOT(slotContextRequested(QPoint)));

    connect(m_searchLine, SIGNAL(textChanged(QString)),
            this, SLOT(slotSearchPatternChanged(QString)));
79 80 81 82 83 84 85 86 87 88 89 90 91 92
}

CoverDialog::~CoverDialog()
{
}

void CoverDialog::show()
{
    m_artists->clear();
    m_covers->clear();

    QStringList artists = CollectionList::instance()->uniqueSet(CollectionList::Artists);

    new AllArtistsListViewItem(m_artists);
Laurent Montel's avatar
Laurent Montel committed
93
    for(QStringList::ConstIterator it = artists.constBegin(); it != artists.constEnd(); ++it)
94
        new CaseInsensitiveItem(m_artists, *it);
95 96

    QTimer::singleShot(0, this, SLOT(loadCovers()));
Tim Beaulen's avatar
Tim Beaulen committed
97
    QWidget::show();
98 99 100 101 102 103
}

// Here we try to keep the GUI from freezing for too long while we load the
// covers.
void CoverDialog::loadCovers()
{
104
    CoverDataMapIterator it, end;
105 106
    int i = 0;

107 108 109 110 111
    it  = CoverManager::begin();
    end = CoverManager::end();

    for(; it != end; ++it) {
        (void) new CoverIconViewItem(it.key(), m_covers);
112

113
        // TODO: Threading!
114 115 116 117 118 119 120 121
        if(++i == 10) {
            i = 0;
            kapp->processEvents();
        }
    }
}

// TODO: Add a way to show cover art for tracks with no artist.
122
void CoverDialog::slotArtistClicked(QListWidgetItem *item)
123 124
{
    m_covers->clear();
125 126 127
    if (!item) {
        return;
    }
128 129 130 131 132
    if(dynamic_cast<AllArtistsListViewItem *>(item)) {
        // All artists.
        loadCovers();
    }
    else {
133
        QString artist = item->text().toLower();
134

135 136 137 138 139 140 141 142
        CoverDataMapIterator it, end;

        it  = CoverManager::begin();
        end = CoverManager::end();

        for(; it != end; ++it) {
            if(it.value()->artist == artist)
                (void) new CoverIconViewItem(it.key(), m_covers);
143 144 145 146
        }
    }
}

147
void CoverDialog::slotContextRequested(const QPoint &pt)
148
{
Laurent Montel's avatar
Laurent Montel committed
149
    static KMenu *menu = 0;
150

151 152
    QListWidgetItem* item = m_covers->currentItem();

153 154 155 156
    if(!item)
        return;

    if(!menu) {
Laurent Montel's avatar
Laurent Montel committed
157
        menu = new KMenu(this);
158
        menu->addAction(i18n("Remove Cover"), this, SLOT(removeSelectedCover()));
159 160
    }

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
    QPoint globalPt = m_covers->mapToGlobal(pt);
    menu->popup(globalPt);
}

void CoverDialog::slotSearchPatternChanged(const QString& pattern)
{
    m_covers->clear();

    QListWidgetItem* item = m_artists->currentItem();

    // If the expression is cleared, then use slotArtistClicked.
    if (pattern.isEmpty()) {
        slotArtistClicked(item);
    }

    else {
        QRegExp filter(pattern, Qt::CaseInsensitive, QRegExp::Wildcard);
        QString artist = item->text().toLower();

        CoverDataMapIterator it, end;

        it  = CoverManager::begin();
        end = CoverManager::end();

        // Here, only show cover that match the search pattern.
        if (dynamic_cast<AllArtistsListViewItem *>(item)) {

            for(; it != end; ++it) {
                if (filter.indexIn(it.value()->artist) != -1) {

                    (void) new CoverIconViewItem(it.key(), m_covers);
                }
            }
        }

        // Here, only show the covers that match the search pattern and
        // that have the same artist as the currently selected one.
        else {

            for(; it != end; ++it) {
                if (it.value()->artist == artist
202 203
                        && ((filter.indexIn(it.value()->artist) != -1)
                        || (filter.indexIn(it.value()->album) != -1))) {
204 205 206 207 208 209

                    (void) new CoverIconViewItem(it.key(), m_covers);
                }
            }
        }
    }
210 211 212 213
}

void CoverDialog::removeSelectedCover()
{
Michael Pyne's avatar
Michael Pyne committed
214
    CoverIconViewItem *coverItem = m_covers->currentItem();
215 216

    if(!coverItem || !coverItem->isSelected()) {
217
        kWarning() << "No item selected for removeSelectedCover.\n";
218 219 220 221
        return;
    }

    if(!CoverManager::removeCover(coverItem->id()))
222
        kError() << "Unable to remove selected cover: " << coverItem->id() << endl;
223 224 225 226
    else
        delete coverItem;
}

227
// vim: set et sw=4 tw=0 sta: