covermanager.h 8.85 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/**
 * Copyright (C) 2005, 2008 Michael Pyne <mpyne@kde.org>
 *
 * 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/>.
 */
16

Michael Pyne's avatar
Michael Pyne committed
17 18
#ifndef JUK_COVERMANAGER_H
#define JUK_COVERMANAGER_H
Michael Pyne's avatar
Michael Pyne committed
19

20 21
#include <ksharedptr.h>

22
#include <QObject>
Michael Pyne's avatar
Michael Pyne committed
23
#include <QMimeData>
24
#include <QString>
25 26

class CoverManagerPrivate;
27
class CoverProxy;
28
class QPixmap;
29
class QTimer;
30
class KJob;
31 32 33 34 35 36

template<class Key, class Value>
class QMap;

template<class T>
class QList;
37

38 39
class KUrl;

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
/**
 * This class saves the covers when its saveCovers() slot is called to avoid
 * making CoverManager a QObject and avoid moving the actual implementation
 * class (CoverManagerPrivate) to this .h file.  Used with a QTimer to save
 * the covers after changes are made.
 */
class CoverSaveHelper : public QObject
{
    Q_OBJECT

public:
    CoverSaveHelper(QObject *parent);
    void saveCovers();

private slots:
    void commitChanges();

private:
    QTimer *m_timer;
};

61 62 63 64 65 66
/**
 * This class holds the data on a cover.  This includes the path to the cover
 * representation on-disk, and the artist and album associated with the cover.
 * Don't assume that the artist or album information is filled out, it is
 * there to allow the CoverManager to try to automatically assign covers to
 * new tracks.
67
 *
68
 * @author Michael Pyne <mpyne@kde.org>
69 70 71 72 73 74 75 76 77 78 79
 * @see CoverManager
 */
class CoverData : public KShared
{
public:
    QPixmap pixmap() const;
    QPixmap thumbnail() const;

    QString artist;
    QString album;
    QString path;
80 81

    unsigned refCount; // Refers to number of tracks using this.
82 83 84 85
};

typedef KSharedPtr<CoverData> CoverDataPtr;
typedef unsigned long coverKey; ///< Type of the id for a cover.
86

87 88
typedef QMap<coverKey, CoverDataPtr> CoverDataMap;

89 90 91 92 93
// I can't believe this actually works...
typedef CoverDataMap::const_iterator CoverDataMapIterator;

typedef QList<coverKey> CoverList;

Michael Pyne's avatar
Michael Pyne committed
94 95 96 97 98 99 100
/**
 * This class is used to drag covers in JuK.  It adds a special mimetype that
 * contains the cover ID used for this cover, and also supports an image/png
 * mimetype for dragging to other applications.
 *
 * As of this writing the mimetype is application/x-juk-coverid
 *
101
 * @author Michael Pyne <mpyne@kde.org>
Michael Pyne's avatar
Michael Pyne committed
102
 */
Michael Pyne's avatar
Michael Pyne committed
103
class CoverDrag : public QMimeData
Michael Pyne's avatar
Michael Pyne committed
104
{
Michael Pyne's avatar
Michael Pyne committed
105
    Q_OBJECT
Michael Pyne's avatar
Michael Pyne committed
106

Michael Pyne's avatar
Michael Pyne committed
107 108
public:
    CoverDrag(coverKey id);
Michael Pyne's avatar
Michael Pyne committed
109

110
    static const char* mimetype();
Michael Pyne's avatar
Michael Pyne committed
111

Michael Pyne's avatar
Michael Pyne committed
112 113 114 115 116
    static bool isCover(const QMimeData *data);

    // CoverDrag stores QByteArray data for the cover id, this can convert it
    // back.
    static coverKey idFromData(const QMimeData *data);
Michael Pyne's avatar
Michael Pyne committed
117 118
};

119 120 121 122 123 124 125 126 127 128 129 130
/**
 * This class holds all of the cover art, and manages looking it up by artist
 * and/or album.  This class is similar to a singleton class, but instead all
 * of the methods are static.  This way you can invoke methods like this:
 * \code
 *   CoverManager::method()
 * \endcode
 * instead of using:
 * \code
 *   CoverManager::instance()->method()
 * \endcode
 *
131
 * @author Michael Pyne <mpyne@kde.org>
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
 */
class CoverManager
{
public:
    /// The set of different sizes you can request a pixmap as.
    typedef enum { Thumbnail, FullSize } Size;

    /**
     * Tries to match @p artist and @p album to a cover in the database.
     *
     * @param artist The artist to look for matching covers on.
     * @param album The album to look for matching covers on.
     * @return NoMatch if no match could be found, otherwise the id of the
     *         cover art that matches the given metadata.
     */
    static coverKey idFromMetadata(const QString &artist, const QString &album);

    /**
     * Returns the cover art for @p id.
     *
     * @param id The id of the cover.
     * @param size The size to return it as.  Note that FullSize doesn't
     *             necessarily mean the pixmap is large, so you may need to
     *             scale it up.
     * @return QPixmap::null if there is no cover art for @p id, otherwise the
     *         cover art.
     */
    static QPixmap coverFromId(coverKey id, Size size = Thumbnail);

161 162 163 164 165 166 167 168 169 170 171
    /**
     * Returns the cover art for @p ptr.  This function is intended for use
     * by CoverData.
     *
     * @param ptr The CoverData to get the cover of.  Note that it is a
     *            CoverData, not CoverDataPtr.
     * @param size The size to return it as.
     * @see CoverData
     */
    static QPixmap coverFromData(const CoverData &coverData, Size size = Thumbnail);

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
    /**
     * Returns the full suite of information known about the cover given by
     * @p id.
     *
     * @param id the id of the cover to retrieve info on.
     * @return 0 if there is no info on @p id, otherwise its information.
     */
    static CoverDataPtr coverInfo(coverKey id);

    /**
     * Adds @p large to the cover database, associating with it @p artist and
     * @p album.
     *
     * @param large The full size cover (the thumbnail is automatically
     *              generated).
     * @param artist The artist of the new cover.
     * @param album  The album of the new cover.
     */
    static coverKey addCover(const QPixmap &large, const QString &artist = "", const QString &album = "");

    /**
     * Adds the file pointed to by the local path @p path to the database,
     * associating it with @p artist and @p album.
     *
     * @param path The absolute path to the fullsize cover art.
     * @param artist The artist of the new cover.
     * @param album  The album of the new cover.
     */
200
    static coverKey addCover(const KUrl &path, const QString &artist = "", const QString &album = "");
201 202 203

    /**
     * Function to determine if @p id matches any covers in the database.
204
     *
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
     * @param id The id of the cover to search for.
     * @return true if the database has a cover identified by @p id, false
     *         otherwise.
     */
    static bool hasCover(coverKey id);

    /**
     * Removes the cover identified by @p id.
     *
     * @param id the id of the cover to remove.
     * @return true if the removal was successful, false if unsuccessful or if
     *         the cover didn't exist.
     */
    static bool removeCover(coverKey id);

    /**
     * Replaces the cover art for the cover identified by @p id with @p large.
     * Any other metadata such as artist and album is unchanged.
     *
     * @param id The id of the cover to replace.
     * @param large The full size cover art for the new cover.
     */
    static bool replaceCover(coverKey id, const QPixmap &large);

229 230 231 232 233 234 235 236
    /**
     * Saves the current CoverManager information to disk.  Changes are not
     * automatically written to disk due to speed issues, so you can
     * periodically call this function while running to reduce the chance of
     * lost data in the event of a crash.
     */
    static void saveCovers();

237 238 239 240 241 242 243 244 245 246
    /**
     * This is a hack, as we should be shut down automatically by
     * KStaticDeleter, but JuK is crashing for me on shutdown before
     * KStaticDeleter gets a chance to run, which is cramping my testing.
     */
    static void shutdown();

    /**
     * @return Iterator pointing to the first element in the cover database.
     */
247
    static CoverDataMapIterator begin();
248 249 250 251

    /**
     * @return Iterator pointing after the last element in the cover database.
     */
252
    static CoverDataMapIterator end();
253 254 255 256

    /**
     * @return A list of all of the id's listed in the database.
     */
257
    static CoverList keys();
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280

    /**
     * Associates @p path with the cover identified by @id.  No comparison of
     * metadata is performed to enforce this matching.
     *
     * @param path The absolute file path to the track.
     * @param id The identifier of the cover to use with @p path.
     */
    static void setIdForTrack(const QString &path, coverKey id);

    /**
     * Returns the identifier of the cover for the track at @p path.
     *
     * @param path The absolute file path to the track.
     * @return NoMatch if @p path doesn't have a cover, otherwise the id of
     *         its cover.
     */
    static coverKey idForTrack(const QString &path);

    /**
     * This identifier is used to indicate that no cover was found in the
     * database.
     */
281
    static const coverKey NoMatch;
282 283

    private:
284 285 286 287
    friend class CoverProxy; // Our QObject-wielding friend.

    /// Called by CoverProxy to notify of a completed job.
    static void jobComplete(KJob *job, bool completedSatisfactory);
288 289 290 291
    static CoverManagerPrivate *data();
    static QPixmap createThumbnail(const QPixmap &base);
};

Michael Pyne's avatar
Michael Pyne committed
292
#endif /* JUK_COVERMANAGER_H */
Michael Pyne's avatar
Michael Pyne committed
293

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