playlistitem.cpp 9.66 KB
Newer Older
1 2 3 4 5
/***************************************************************************
                          playlistitem.cpp  -  description
                             -------------------
    begin                : Sun Feb 17 2002
    copyright            : (C) 2002 by Scott Wheeler
6
    email                : wheeler@kde.org
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include <kdebug.h>

#include "playlistitem.h"
#include "playlist.h"
22
#include "collectionlist.h"
23 24 25


////////////////////////////////////////////////////////////////////////////////
26
// PlaylistItem public methods
27 28
////////////////////////////////////////////////////////////////////////////////

29
PlaylistItem::~PlaylistItem()
30
{
31
    data->deleteUser();
32 33
}

34
void PlaylistItem::setFile(const QString &file)
35
{
36 37
    data->setFile(file);
    refresh();
38 39
}

40
Tag *PlaylistItem::getTag()
41
{
42
    return(data->getTag());
43 44
}

45
// QFileInfo-ish methods
46

47 48 49 50 51
QString PlaylistItem::fileName() const { return(data->fileName()); }
QString PlaylistItem::filePath() const { return(data->filePath()); }
QString PlaylistItem::absFilePath() const { return(data->absFilePath()); }
QString PlaylistItem::dirPath(bool absPath) const { return(data->dirPath(absPath)); }
bool PlaylistItem::isWritable() const { return(data->isWritable()); }
52 53

////////////////////////////////////////////////////////////////////////////////
54
// PlaylistItem public slots
55 56
////////////////////////////////////////////////////////////////////////////////

57
void PlaylistItem::refresh()
58
{
59 60 61
    // This signal will be received by the "parent" CollectionListItem which will
    // in turn call refreshImpl() for all of its children, including this item.
    emit(refreshed());
62 63
}

64 65 66 67 68 69
void PlaylistItem::refreshFromDisk()
{
    data->refresh();
    refresh();
}

70
////////////////////////////////////////////////////////////////////////////////
71
// PlaylistItem protected methods
72 73
////////////////////////////////////////////////////////////////////////////////

74 75 76 77 78
PlaylistItem::PlaylistItem(CollectionListItem *item, Playlist *parent) : QObject(parent), KListViewItem(parent)
{
    setup(item, parent);
}

79
PlaylistItem::PlaylistItem(CollectionListItem *item, Playlist *parent, QListViewItem *after) : QObject(parent), KListViewItem(parent, after)
80 81 82 83
{
    setup(item, parent);
}

84
PlaylistItem::PlaylistItem(Playlist *parent) : QObject(parent), KListViewItem(parent)
85
{
86
    setDragEnabled(true);
87 88 89 90 91 92 93
}

PlaylistItem::Data *PlaylistItem::getData()
{
    return(data);
}

94
void PlaylistItem::setData(Data *d)
95
{
96
    data = d;
97 98 99
}

////////////////////////////////////////////////////////////////////////////////
100
// PlaylistItem protected slots
101 102
////////////////////////////////////////////////////////////////////////////////

103
void PlaylistItem::refreshImpl()
104
{
105
    // This should be the only function that needs to be rewritten if the structure of    
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
    // PlaylistItemData changes.  Also, currently this also inserts things into the
    // album and artist registries of the Playlist.  If something like sorted insert
    // happens at some point it could either be implemented here or in a subclass of
    // QValueList.  And another note: the artist/album registry doesn't remove items
    // when they no longer exist in the list view.  I decided that this is too much work
    // for something not very useful at the moment, but at some point, a QValueList of
    // a subclass of QPair could track such things...

    // if the text has changed and the artist registry of the Playlist doens't contain
    // this artist, add it to the mentioned registry

    if(Cache::instance()->item(absFilePath())) {

	// ... do stuff relative to a cache hit.  At the moment this will never 
	// happen since the cache isn't yet implemented.

	// The current though is that "Tag" and "Cache::Item" should share a 
	// common virtual interface so that the below code could actually be 
	// used through that interface.  In this if block it would just be
	// decided what object the meta data was going to come from and then
	// something like metaData->getArtist() could be used, where metaData
	// is either a Tag or a Cache::Item.

        // And on further thought this should also be hidden in 
	// PlaylistItem::Data.  I'll work on that later.

    }
    else {
	
135 136 137 138 139 140
	setText(TrackColumn,       getTag()->track());
	setText(ArtistColumn,      getTag()->artist());
	setText(AlbumColumn,       getTag()->album());
	setText(TrackNumberColumn, getTag()->trackNumberString());
	setText(GenreColumn,       getTag()->genre());
	setText(YearColumn,        getTag()->yearString());
141
	setText(LengthColumn,      getTag()->lengthString());
142 143 144 145 146 147 148 149
	setText(FileNameColumn,    filePath());
    }
}

////////////////////////////////////////////////////////////////////////////////
// PlaylistItem private methods
////////////////////////////////////////////////////////////////////////////////

150 151 152 153 154 155 156 157 158 159 160 161
void PlaylistItem::setup(CollectionListItem *item, Playlist *parent)
{
    if(item) {
	data = item->getData()->newUser();
	item->addChildItem(this);
	refreshImpl();
	connect(this, SIGNAL(refreshed()), parent, SIGNAL(dataChanged()));
    }

    setDragEnabled(true);
}

162 163 164 165
int PlaylistItem::compare(QListViewItem *item, int column, bool ascending) const
{
    // reimplemented from QListViewItem

166 167 168 169 170 171
    // This is pretty ugly.  This needs to be a const method to match the
    // signature from QListViewItem::compare(), but for our purposes, we need
    // to be able to call non-const methods, so we're casting this to a 
    // non-const pointer.  Yuck.

    PlaylistItem *playlistItem = dynamic_cast<PlaylistItem *>(item);
172 173 174 175 176 177 178
    PlaylistItem *thisPlaylistItem = const_cast<PlaylistItem *>(this);

    // The following statments first check to see if you can sort based on the
    // specified column.  If the values for the two PlaylistItems are the same
    // in that column it then trys to sort based on columns 1, 2, 3 and 0,
    // (artist, album, track number, track name) in that order.

179 180 181
    if(playlistItem && thisPlaylistItem) {
        if(compare(thisPlaylistItem, playlistItem, column, ascending) != 0)
            return(compare(thisPlaylistItem, playlistItem, column, ascending));
182 183
        else {
            for(int i = ArtistColumn; i <= TrackNumberColumn; i++) {
184 185
                if(compare(thisPlaylistItem, playlistItem, i, ascending) != 0)
                    return(compare(thisPlaylistItem, playlistItem, i, ascending));
186
            }
187 188
            if(compare(thisPlaylistItem, playlistItem, TrackColumn, ascending) != 0)
                return(compare(thisPlaylistItem, playlistItem, TrackColumn, ascending));
189 190 191 192 193 194 195 196 197 198
            return(0);
        }
    }
    else
        return(0); // cast failed, something is wrong
}

int PlaylistItem::compare(PlaylistItem *firstItem, PlaylistItem *secondItem, int column, bool ascending) const
{
    if(column == TrackNumberColumn) {
199
        if(firstItem->getTag()->trackNumber() > secondItem->getTag()->trackNumber())
200
            return(1);
201
        else if(firstItem->getTag()->trackNumber() < secondItem->getTag()->trackNumber())
202 203 204 205 206
            return(-1);
        else
            return(0);
    }
    else if(column == LengthColumn) {
207
        if(firstItem->getTag()->seconds() > secondItem->getTag()->seconds())
208
            return(1);
209
        else if(firstItem->getTag()->seconds() < secondItem->getTag()->seconds())
210 211 212 213 214 215 216
            return(-1);
        else
            return(0);
    }
    else
        return(firstItem->key(column, ascending).compare(secondItem->key(column, ascending)));
}
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232

////////////////////////////////////////////////////////////////////////////////
// PlaylistItem::Data public methods
////////////////////////////////////////////////////////////////////////////////

PlaylistItem::Data *PlaylistItem::Data::newUser(const QFileInfo &file)
{
    return(new Data(file));
}

PlaylistItem::Data *PlaylistItem::Data::newUser()
{
    referenceCount++;
    return(this);
}

233 234 235 236 237 238 239 240 241
void PlaylistItem::Data::refresh()
{
    delete(cache);
    delete(tag);

    cache = 0;
    tag = 0;
}

242 243 244 245 246 247 248 249 250 251 252 253
void PlaylistItem::Data::deleteUser()
{
    // The delete(this) is safe because we control object creation through a
    // protected constructor and the newUser() methods.

    if(--referenceCount == 0)
        delete(this);
}

Tag *PlaylistItem::Data::getTag()
{
    if(!tag)
254
        tag = Tag::createTag(filePath());
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
    return(tag);
}

void PlaylistItem::Data::setFile(const QString &file)
{
    delete(tag);
    tag = 0;

    QFileInfo::setFile(file);
}

////////////////////////////////////////////////////////////////////////////////
// PlaylistItem::Data protected methods
////////////////////////////////////////////////////////////////////////////////

PlaylistItem::Data::Data(const QFileInfo &file) : QFileInfo(file)
{
    referenceCount = 1;

    // initialize pointers to null
    cache = 0;
    tag = 0;
}

PlaylistItem::Data::~Data()
{
    // Create our cache "on the way out" to avoid having lots of duplicate copies
    // of the same information in memory.  This checks to see if the item is in
    // the cache and 

    if(tag && !cache && !Cache::instance()->isEmpty() && !Cache::instance()->find(absFilePath()) )
	Cache::instance()->replace(absFilePath(), new CacheItem(*tag));

    delete(tag);
}

291
#include "playlistitem.moc"