collectionlist.cpp 8.05 KB
Newer Older
1
/***************************************************************************
2
                          collectionlist.cpp  -  description
3
                             -------------------
4
    begin                : Fri Sep 13 2002
5
    copyright            : (C) 2002 by Scott Wheeler
6
    email                : wheeler@kde.org
7
 ***************************************************************************/
8 9 10 11 12 13 14 15 16 17

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

18
#include <kurldrag.h>
19
#include <klocale.h>
20
#include <kmessagebox.h>
21
#include <kdebug.h>
22 23
#include <kpopupmenu.h>
#include <kiconloader.h>
24

25

26
#include "collectionlist.h"
27
#include "splashscreen.h"
28

29 30 31 32
////////////////////////////////////////////////////////////////////////////////
// static methods
////////////////////////////////////////////////////////////////////////////////

33
CollectionList *CollectionList::m_list = 0;
34 35 36

CollectionList *CollectionList::instance()
{
37
    return m_list;
38 39
}

40
void CollectionList::initialize(QWidget *parent, bool restoreOnLoad)
41
{
42
    m_list = new CollectionList(parent);
43

44 45
    if(restoreOnLoad)
	for(QDictIterator<Tag>it(*Cache::instance()); it.current(); ++it)
46
	    new CollectionListItem(it.current()->fileInfo(), it.current()->absFilePath());
47 48 49 50 51 52
}

////////////////////////////////////////////////////////////////////////////////
// public methods
////////////////////////////////////////////////////////////////////////////////

53
PlaylistItem *CollectionList::createItem(const QFileInfo &file, const QString &absFilePath, QListViewItem *, bool)
54
{
55
    QString filePath;
56

57 58 59 60 61
    if(absFilePath.isNull())
	filePath = resolveSymLinks(file);
    else
	filePath = absFilePath;
    
62
    if(m_itemsDict.find(filePath))
63
	return 0;
64

65 66 67 68 69 70 71 72 73
    PlaylistItem *item = new CollectionListItem(file, filePath);
    
    if(!item->isValid()) {
	kdError() << "CollectinList::createItem() -- A valid tag was not created for \"" << file.filePath() << "\"" << endl;
	delete item;
	return 0;
    }
    
    return item;
74 75
}

76 77 78 79 80 81 82 83
////////////////////////////////////////////////////////////////////////////////
// public slots
////////////////////////////////////////////////////////////////////////////////

void CollectionList::clear()
{
    int result = KMessageBox::warningYesNo(this, 
			      i18n("Removing an item from the collection will also remove it from "
84 85 86
				   "all of your playlists. Are you sure you want to continue?\n\n"
				   "Note, however, that if the directory that these files are in is in "
				   "your \"scan on startup\" list, they will be readded on startup."));
87 88
    if(result == KMessageBox::Yes)			      
	Playlist::clear();
89 90

    emit signalCollectionChanged();
91 92
}

Scott Wheeler's avatar
Scott Wheeler committed
93 94
void CollectionList::slotCheckCache()
{
95 96
    PlaylistItemList invalidItems;

Scott Wheeler's avatar
Scott Wheeler committed
97
    for(QDictIterator<CollectionListItem>it(m_itemsDict); it.current(); ++it) {
98 99
	if(!it.current()->checkCurrent())
	    invalidItems.append(*it);
Scott Wheeler's avatar
Scott Wheeler committed
100 101
	kapp->processEvents();
    }
102 103

    clearItems(invalidItems);
Scott Wheeler's avatar
Scott Wheeler committed
104 105
}

106 107 108 109
////////////////////////////////////////////////////////////////////////////////
// protected methods
////////////////////////////////////////////////////////////////////////////////

110 111
CollectionList::CollectionList(QWidget *parent) : Playlist(parent, i18n("Collection List")),
						  m_itemsDict(5003)
112
{
113 114 115 116
    m_dirWatch = new KDirWatch();
    connect(m_dirWatch, SIGNAL(deleted(const QString &)), this, SLOT(slotRemoveItem(const QString &)));
    connect(m_dirWatch, SIGNAL(dirty(const QString &)), this, SLOT(slotRefreshItem(const QString &)));
    m_dirWatch->startScan();
117 118 119 120 121

    polish();

    rmbMenu()->insertSeparator();
    rmbMenu()->insertItem(SmallIcon("new"), i18n("Create Group From Selected Items"), this, SLOT(slotCreateGroup()));
122 123
}

124
CollectionList::~CollectionList()
125
{
Scott Wheeler's avatar
Scott Wheeler committed
126
    delete m_dirWatch;
127
}
128

129
void CollectionList::decode(QMimeSource *s)
130
{
131 132 133 134 135 136 137 138 139
    KURL::List urls;
    
    if(!KURLDrag::decode(s, urls) || urls.isEmpty())
	return;
	
    QStringList files;
	
    for(KURL::List::Iterator it = urls.begin(); it != urls.end(); it++)
	files.append((*it).path());
140
	
141
    emit signalFilesDropped(files, this);
142 143 144 145 146 147
}

void CollectionList::contentsDropEvent(QDropEvent *e)
{
    if(e->source() == this)
	return;
148 149
    else
	decode(e);
150 151 152 153 154 155 156 157 158 159
}

void CollectionList::contentsDragMoveEvent(QDragMoveEvent *e)
{
    if(KURLDrag::canDecode(e) && e->source() != this)
	e->accept(true);
    else
	e->accept(false);
}

160 161
void CollectionList::addArtist(const QString &artist)
{
162 163 164
    if(artist.isEmpty())
	return;

165 166 167
    // Do a bit of caching since there will very often be "two in a row" insertions.
    static QString previousArtist;

168 169 170
    if(artist == previousArtist || m_artists.insert(artist))
	m_viewModeItems["artists"].insert(artist);
    else
171
	previousArtist = artist;
172

173 174 175 176
}

void CollectionList::addAlbum(const QString &album)
{
177 178 179
    if(album.isEmpty())
	return;

180 181 182
    // Do a bit of caching since there will very often be "two in a row" insertions.
    static QString previousAlbum;

183 184 185
    if(album == previousAlbum || m_albums.insert(album))
	m_viewModeItems["albums"].insert(album);
    else
186
	previousAlbum = album;
187
}
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202

////////////////////////////////////////////////////////////////////////////////
// private slots
////////////////////////////////////////////////////////////////////////////////

void CollectionList::slotRemoveItem(const QString &file)
{
    clearItem(m_itemsDict[file]);
}

void CollectionList::slotRefreshItem(const QString &file)
{
    m_itemsDict[file]->slotRefresh();
}

203 204
void CollectionList::slotCreateGroup()
{
205
    emit signalRequestPlaylistCreation(selectedItems());
206 207
}

208 209 210 211 212 213 214 215
////////////////////////////////////////////////////////////////////////////////
// CollectionListItem public slots
////////////////////////////////////////////////////////////////////////////////

void CollectionListItem::slotRefresh()
{
    slotRefreshImpl();
    
216 217
    CollectionList::instance()->addArtist(text(ArtistColumn));
    CollectionList::instance()->addAlbum(text(AlbumColumn));	
218

219
    // This is connected to slotRefreshImpl() for all of the items children.
220
    emit signalRefreshed();
221
}
222

223
////////////////////////////////////////////////////////////////////////////////
224
// CollectionListItem protected methods
225 226
////////////////////////////////////////////////////////////////////////////////

227 228
CollectionListItem::CollectionListItem(const QFileInfo &file, const QString &path) : PlaylistItem(CollectionList::instance()),
										     m_path(path)
229 230 231
{
    CollectionList *l = CollectionList::instance();
    if(l) {
232 233
	l->addToDict(m_path, this);
	setData(Data::newUser(file, m_path));
234 235 236 237 238 239 240 241
	if(data()->tag()) {
	    slotRefresh();
	    connect(this, SIGNAL(signalRefreshed()), l, SIGNAL(signalDataChanged()));
	    l->emitNumberOfItemsChanged();
	    // l->addWatched(m_path);
	}
	else
	    kdError() << "CollectionListItem::CollectionListItem() -- Tag() could not be created." << endl;
242 243
    }
    else
244 245
	kdError(65432) << "CollectionListItems should not be created before "
		       << "CollectionList::initialize() has been called." << endl;
246 247

    SplashScreen::increment();
248 249 250 251 252
}

CollectionListItem::~CollectionListItem()
{
    CollectionList *l = CollectionList::instance();
253
    if(l) {
254
	QString path = Playlist::resolveSymLinks(*data()->fileInfo());
255 256 257
//	l->removeWatched(m_path);
	l->removeFromDict(m_path);
    }
258 259 260 261
}

void CollectionListItem::addChildItem(PlaylistItem *child)
{
262 263
    connect(child, SIGNAL(signalRefreshed()), this, SLOT(slotRefresh()));
    connect(this, SIGNAL(signalRefreshed()), child, SLOT(slotRefreshImpl()));
264 265
}

266
bool CollectionListItem::checkCurrent()
267
{
Scott Wheeler's avatar
Scott Wheeler committed
268
    if(!data()->exists() || !data()->isFile())
269 270 271
	return false;

    if(!data()->tag()->current()) {
272
	data()->refresh();
273 274
	slotRefresh();
    }
275 276

    return true;
277 278
}

279
#include "collectionlist.moc"