Commit 9cf0c688 authored by Scott Wheeler's avatar Scott Wheeler

Went through documenting the Playlist API a bit more and doing some cleanups

in the API as I went along.

svn path=/trunk/kdemultimedia/juk/; revision=239948
parent bf2ed1ee
......@@ -222,7 +222,7 @@ CollectionListItem::CollectionListItem(const QFileInfo &file, const QString &pat
if(data()->tag()) {
slotRefresh();
connect(this, SIGNAL(signalRefreshed()), l, SIGNAL(signalDataChanged()));
l->emitNumberOfItemsChanged();
l->emitCountChanged();
// l->addWatched(m_path);
}
else
......
......@@ -99,8 +99,6 @@ protected:
*/
void addUnique(UniqueSetType t, const QString &value);
void emitNumberOfItemsChanged() { emit signalNumberOfItemsChanged(this); }
void addWatched(const QString &file) { m_dirWatch->addFile(file); }
void removeWatched(const QString &file) { m_dirWatch->removeFile(file); }
......
......@@ -250,7 +250,7 @@ void Playlist::clearItem(PlaylistItem *item, bool emitChanged)
m_randomList.remove(item);
item->deleteLater();
if(emitChanged)
emit signalNumberOfItemsChanged(this);
emit signalCountChanged(this);
}
void Playlist::clearItems(const PlaylistItemList &items)
......@@ -264,7 +264,7 @@ void Playlist::clearItems(const PlaylistItemList &items)
// kapp->processEvents();
kapp->eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
emit signalNumberOfItemsChanged(this);
emit signalCountChanged(this);
}
QStringList Playlist::files() const
......@@ -482,23 +482,12 @@ void Playlist::slotRenameFile()
KApplication::restoreOverrideCursor();
}
void Playlist::slotGuessTagInfoFile()
void Playlist::slotGuessTagInfo(TagGuesser::Type type)
{
KApplication::setOverrideCursor(Qt::waitCursor);
PlaylistItemList items = selectedItems();
for(PlaylistItemList::Iterator it = items.begin(); it != items.end(); ++it)
(*it)->guessTagInfoFromFile();
KApplication::restoreOverrideCursor();
}
void Playlist::slotGuessTagInfoInternet()
{
//not sure if the cursor stuff makes sense
//since guessing will be asynchronous anyway
KApplication::setOverrideCursor(Qt::waitCursor);
PlaylistItemList items = selectedItems();
for(PlaylistItemList::Iterator it = items.begin(); it != items.end(); ++it)
(*it)->guessTagInfoFromInternet();
(*it)->guessTagInfo(type);
KApplication::restoreOverrideCursor();
}
......@@ -516,7 +505,7 @@ void Playlist::slotReload()
// protected members
////////////////////////////////////////////////////////////////////////////////
void Playlist::deleteFromDisk(const PlaylistItemList &items)
void Playlist::removeFromDisk(const PlaylistItemList &items)
{
if(isVisible() && !items.isEmpty()) {
......@@ -544,7 +533,7 @@ void Playlist::deleteFromDisk(const PlaylistItemList &items)
}
}
emit signalNumberOfItemsChanged(this);
emit signalCountChanged(this);
}
}
......@@ -664,11 +653,11 @@ PlaylistItem *Playlist::createItem(const QFileInfo &file, const QString &absFile
i = new PlaylistItem(item, this);
if(!m_randomList.isEmpty() && !m_visibleChanged)
m_randomList.append(i);
emit signalNumberOfItemsChanged(this);
emit signalCountChanged(this);
connect(item, SIGNAL(destroyed()), i, SLOT(deleteLater()));
if(emitChanged)
emit signalNumberOfItemsChanged(this);
emit signalCountChanged(this);
return i;
}
......@@ -687,7 +676,7 @@ void Playlist::createItems(const PlaylistItemList &siblings)
connect((*it)->collectionItem(), SIGNAL(destroyed()), *it, SLOT(deleteLater()));
}
}
emit signalNumberOfItemsChanged(this);
emit signalCountChanged(this);
}
void Playlist::hideColumn(int c)
......@@ -835,7 +824,7 @@ void Playlist::polish()
connect(this, SIGNAL(selectionChanged()),
this, SLOT(slotEmitSelected()));
connect(this, SIGNAL(contextMenuRequested( QListViewItem *, const QPoint&, int)),
connect(this, SIGNAL(contextMenuRequested(QListViewItem *, const QPoint &, int)),
this, SLOT(slotShowRMBMenu(QListViewItem *, const QPoint &, int)));
connect(this, SIGNAL(itemRenamed(QListViewItem *, const QString &, int)),
this, SLOT(slotApplyModification(QListViewItem *, const QString &, int)));
......@@ -860,7 +849,7 @@ void Playlist::setup()
connect(header(), SIGNAL(indexChange(int, int, int)), this, SLOT(slotColumnOrderChanged(int, int, int)));
connect(this, SIGNAL(signalDataChanged()), this, SIGNAL(signalChanged()));
connect(this, SIGNAL(signalNumberOfItemsChanged(Playlist *)), this, SIGNAL(signalChanged()));
connect(this, SIGNAL(signalCountChanged(Playlist *)), this, SIGNAL(signalChanged()));
}
void Playlist::loadFile(const QString &fileName, const QFileInfo &fileInfo)
......@@ -894,7 +883,7 @@ void Playlist::loadFile(const QString &fileName, const QFileInfo &fileInfo)
file.close();
emit signalNumberOfItemsChanged(this);
emit signalCountChanged(this);
}
void Playlist::setPlaying(PlaylistItem *item, bool p)
......@@ -1108,7 +1097,7 @@ QDataStream &operator>>(QDataStream &s, Playlist &p)
after = p.createItem(info, *it, after, false);
}
p.emitNumberOfItemsChanged();
p.emitCountChanged();
return s;
}
......
......@@ -27,6 +27,7 @@
#include "sortedstringlist.h"
#include "playlistsearch.h"
#include "tagguesser.h"
class KPopupMenu;
class KActionMenu;
......@@ -46,6 +47,7 @@ class Playlist : public KListView
Q_OBJECT
public:
/**
* Before creating a playlist directly, please see
* PlaylistSplitter::createPlaylist().
......@@ -112,7 +114,16 @@ public:
void createItems(const PlaylistItemList &siblings);
/**
* Returns the file name associated with this playlist (an m3u file) or
* QString::null if no such file exists.
*/
QString fileName() const { return m_fileName; }
/**
* Sets the file name to be associated with this playlist; this file should
* have the "m3u" extension.
*/
void setFileName(const QString &n) { m_fileName = n; }
void hideColumn(int c);
......@@ -131,14 +142,31 @@ public:
*/
void setName(const QString &n);
/**
* Returns the number of items in the playlist.
*/
int count() const { return childCount(); }
/**
* This gets the next item to be played.
* Returns the next item to be played. If random is false this is just
* the next item in the playlist (or null if the current items is the last
* item in the list). If random is true, then it will select an item at
* random from this list (and try to be a bit clever about it to not repeat
* items before everything has been played at least once).
*/
PlaylistItem *nextItem(PlaylistItem *current, bool random = false);
/**
* Returns the item played before the currently playing item. If random is
* false, this is simply the item above the currently playing item in the
* list. If random is true this checks the history of recently played items.
*/
PlaylistItem *previousItem(PlaylistItem *current, bool random = false);
/**
* Returns the KActionMenu that allows this to be embedded in menus outside
* of the playlist.
*/
KActionMenu *columnVisibleAction() const { return m_columnVisibleAction; }
/**
......@@ -157,18 +185,39 @@ public:
*/
void updateLeftColumn();
/**
* Sets the items in the list to be either visible based on the value of
* visible. This is useful for search operations and such.
*/
static void setItemsVisible(const PlaylistItemList &items, bool visible = true);
/**
* Returns the search associated with this list, or an empty search if one
* has not yet been set.
*/
PlaylistSearch search() const { return m_search; }
/**
* Set the search associtated with this playlist.
*
* \note This does not cause the search to be rerun.
*/
void setSearch(const PlaylistSearch &s) { m_search = s; }
void emitNumberOfItemsChanged() { emit signalNumberOfItemsChanged(this); }
/**
* Emits a signal indicating that the number of items have changed. This
* is useful in conjunction with createItem() where emitChanged is false.
*
* In many situations it is not practical for speed reasons to trigger the
* actions associated with signalCountChanged() after each insertion.
*/
void emitCountChanged() { emit signalCountChanged(this); }
public slots:
/**
* Remove the currently selected items from the playlist and disk.
*/
void slotDeleteSelectedItems() { deleteFromDisk(selectedItems()); };
void slotRemoveSelectedItems() { removeFromDisk(selectedItems()); };
void slotSetNext();
/*
......@@ -187,8 +236,7 @@ public slots:
*/
virtual void slotRefresh();
void slotGuessTagInfoFile();
void slotGuessTagInfoInternet();
void slotGuessTagInfo(TagGuesser::Type type);
void slotRenameFile();
/**
......@@ -201,9 +249,11 @@ protected:
* Remove \a items from the playlist and disk. This will ignore items that
* are not actually in the list.
*/
void deleteFromDisk(const PlaylistItemList &items);
void removeFromDisk(const PlaylistItemList &items);
virtual bool eventFilter(QObject* watched, QEvent* e);
// the following are all reimplemented from base classes
virtual bool eventFilter(QObject *watched, QEvent *e);
virtual QDragObject *dragObject(QWidget *parent);
virtual QDragObject *dragObject() { return dragObject(this); }
virtual bool canDecode(QMimeSource *s);
......@@ -211,6 +261,7 @@ protected:
virtual void contentsDropEvent(QDropEvent *e);
virtual void showEvent(QShowEvent *e);
virtual bool acceptDrag(QDropEvent *e) const { return KURLDrag::canDecode(e); }
virtual void polish();
/**
* Though it's somewhat obvious, this function will stat the file, so only use it when
......@@ -218,23 +269,15 @@ protected:
*/
static QString resolveSymLinks(const QFileInfo &file);
KPopupMenu *rmbMenu() { return m_rmbMenu; }
const KPopupMenu *rmbMenu() const { return m_rmbMenu; }
virtual void polish();
KPopupMenu *rmbMenu() const { return m_rmbMenu; }
signals:
/**
* This signal is connected to PlaylistItem::refreshed() in the
* PlaylistItem class.
*/
void signalDataChanged();
/**
* This is emitted when the playlist selection is changed. This is used
* primarily to notify the TagEditor of the new data.
*/
void signalSelectionChanged(const PlaylistItemList &selection);
void signalDoubleClicked();
/**
* This is connected to the PlaylistBox::Item to let it know when the
......@@ -243,34 +286,78 @@ signals:
void signalNameChanged(const QString &fileName);
/**
* This signal is emited when items are added to or removed from the list.
* This signal is emitted when items are added to or removed from the list.
*
* \see signalDataChanged()
* \see signalChanged()
*/
void signalNumberOfItemsChanged(Playlist *);
void signalDoubleClicked();
void signalCountChanged(Playlist *);
/**
* This is the union of signalDataChanged() and signalNumberOfItemsChanged().
* It is emited with either quantity or value of the PlaylistItems are
* This signal is connected to PlaylistItem::refreshed() in the PlaylistItem
* class. It is emitted when a playlist item's data has been changed.
*
* \see signalCountChanged()
* \see signalChanged()
*/
void signalDataChanged();
/**
* This is the union of signalDataChanged() and signalCountChanged().
* It is emitted with either quantity or value of the PlaylistItems are
* changed.
*/
void signalChanged();
/**
* This signal is emitted just before a playlist item is removed from the
* list.
* list allowing for any cleanup that needs to happen. Typically this
* is used to remove the item from the history and safeguard against
* dangling pointers.
*/
void signalAboutToRemove(PlaylistItem *item);
/**
* This is emitted when \a files are dropped on a specific playlist.
*/
void signalFilesDropped(const QStringList &files, Playlist *);
/**
* Set the next item to be played in the current playlist. This is used by
* the "Play Next" feature.
*/
void signalSetNext(PlaylistItem *item);
/**
* This is emitted when the set of columns that is visible is changed.
*
* \see hideColumn()
* \see showColumn()
* \see isColumnVisible()
*/
void signalVisibleColumnsChanged();
private:
void setup();
/**
* Load the playlist from a file. \a fileName should be the absolute path.
* \a fileInfo should point to the same file as \a fileName. This is a
* little awkward API-wise, but keeps us from throwing away useful
* information.
*/
void loadFile(const QString &fileName, const QFileInfo &fileInfo);
/**
* Save the tag for an individual items.
* Save the tag for an individual item.
*/
void applyTag(QListViewItem *item, const QString &text, int column);
/**
* Returns the index of the left most visible column in the playlist.
*
* \see isColumnVisible()
*/
int leftMostVisibleColumn() const;
/**
......@@ -280,11 +367,23 @@ private:
class SharedSettings;
private slots:
/**
* This is just used to emit the selection as a list of PlaylistItems when
* the selection changes.
*/
void slotEmitSelected() { emit signalSelectionChanged(selectedItems()); }
/**
* Show the RMB menu. Matches the signature for the signal
* QListView::contextMenuRequested().
*/
void slotShowRMBMenu(QListViewItem *item, const QPoint &point, int column);
/**
* This slot applys the tag for
* This slot applys the tag for a specific item.
*
* \see applyTag()
*/
void slotApplyModification(QListViewItem *, const QString &text, int column);
......@@ -293,7 +392,19 @@ private slots:
* an appropriate position.
*/
void slotRenameTag();
/**
* Moves the column \a from to the position \a to. This matches the signature
* for the signal QHeader::indexChange().
*/
void slotColumnOrderChanged(int, int from, int to);
/**
* Toggles a columns visible status. Useful for KActions.
*
* \see hideColumn()
* \see showColumn()
*/
void slotToggleColumnVisible(int column);
private:
......
......@@ -51,8 +51,8 @@ const Tag *PlaylistItem::tag() const
return m_data->tag();
}
// some forwarding methods - these can't be inlined because the Data class
// isn't defined yet
// Some forwarding methods - these can't be inlined because the Data class
// isn't defined yet.
QString PlaylistItem::fileName() const
{
......@@ -79,37 +79,41 @@ bool PlaylistItem::isWritable() const
return m_data->fileInfo()->isWritable();
}
void PlaylistItem::guessTagInfoFromFile()
{
TagGuesser guesser(tag()->absFilePath());
if(!guesser.title().isNull())
tag()->setTrack(guesser.title());
if(!guesser.artist().isNull())
tag()->setArtist(guesser.artist());
if(!guesser.album().isNull())
tag()->setAlbum(guesser.album());
if(!guesser.track().isNull())
tag()->setTrackNumber(guesser.track().toInt());
if(!guesser.comment().isNull())
tag()->setComment(guesser.comment());
tag()->save();
slotRefresh();
}
void PlaylistItem::guessTagInfoFromInternet()
void PlaylistItem::guessTagInfo(TagGuesser::Type type)
{
switch(type) {
case TagGuesser::FileName:
{
TagGuesser guesser(tag()->absFilePath());
if(!guesser.title().isNull())
tag()->setTrack(guesser.title());
if(!guesser.artist().isNull())
tag()->setArtist(guesser.artist());
if(!guesser.album().isNull())
tag()->setAlbum(guesser.album());
if(!guesser.track().isNull())
tag()->setTrackNumber(guesser.track().toInt());
if(!guesser.comment().isNull())
tag()->setComment(guesser.comment());
tag()->save();
slotRefresh();
}
case TagGuesser::MusicBrainz:
{
#if HAVE_MUSICBRAINZ
MusicBrainzQuery *query = new MusicBrainzQuery(MusicBrainzQuery::File,
tag()->absFilePath());
connect(query, SIGNAL(signalDone(const MusicBrainzQuery::TrackList &)),
SLOT(slotTagGuessResults(const MusicBrainzQuery::TrackList &)));
KMainWindow *win = static_cast<KMainWindow *>(kapp->mainWidget());
connect(query, SIGNAL(signalStatusMsg(const QString &, int)),
win->statusBar(), SLOT(message(const QString &, int)));
query->start();
#endif //add message box teeling users musicbrainz is not installed or keep it quiet?
MusicBrainzQuery *query = new MusicBrainzQuery(MusicBrainzQuery::File,
tag()->absFilePath());
connect(query, SIGNAL(signalDone(const MusicBrainzQuery::TrackList &)),
SLOT(slotTagGuessResults(const MusicBrainzQuery::TrackList &)));
KMainWindow *win = static_cast<KMainWindow *>(kapp->mainWidget());
connect(query, SIGNAL(signalStatusMsg(const QString &, int)),
win->statusBar(), SLOT(message(const QString &, int)));
query->start();
#endif //add message box telling users musicbrainz is not installed or keep it quiet?
}
}
}
void PlaylistItem::renameFile()
......
......@@ -27,15 +27,15 @@
#include <qptrstack.h>
#include "musicbrainzquery.h"
#include "tagguesser.h"
#include "tag.h"
#include "cache.h"
#if HAVE_MUSICBRAINZ == 0
// a bit of a hack so that the slots type definition is still valid
namespace MusicBrainzQuery { typedef int TrackList; }
#endif
#include "tag.h"
#include "cache.h"
class Playlist;
class PlaylistItem;
class CollectionListItem;
......@@ -85,8 +85,7 @@ public:
bool isWritable() const;
void setPlaying(bool playing = true) { m_playing = playing; }
void guessTagInfoFromFile();
void guessTagInfoFromInternet();
void guessTagInfo(TagGuesser::Type type);
void renameFile();
public slots:
......
......@@ -347,14 +347,14 @@ void PlaylistSplitter::slotDeleteSelectedItems()
{
Playlist *p = visiblePlaylist();
if(p)
p->slotDeleteSelectedItems();
p->slotRemoveSelectedItems();
}
void PlaylistSplitter::slotAddToPlaylist(const QString &file, Playlist *list)
{
KApplication::setOverrideCursor(Qt::waitCursor);
addImpl(file, list);
list->emitNumberOfItemsChanged();
list->emitCountChanged();
KApplication::restoreOverrideCursor();
if(m_editor)
......@@ -374,7 +374,7 @@ void PlaylistSplitter::slotAddToPlaylist(const QStringList &files, Playlist *lis
KApplication::setOverrideCursor(Qt::waitCursor);
for(QStringList::ConstIterator it = files.begin(); it != files.end(); ++it)
addImpl(*it, list);
list->emitNumberOfItemsChanged();
list->emitCountChanged();
KApplication::restoreOverrideCursor();
if(m_editor)
......@@ -388,16 +388,9 @@ void PlaylistSplitter::slotSetSearchVisible(bool visible)
}
void PlaylistSplitter::slotGuessTagInfoFile()
void PlaylistSplitter::slotGuessTagInfo(TagGuesser::Type type)
{
visiblePlaylist()->slotGuessTagInfoFile();
if(m_editor)
m_editor->slotRefresh();
}
void PlaylistSplitter::slotGuessTagInfoInternet()
{
visiblePlaylist()->slotGuessTagInfoInternet();
visiblePlaylist()->slotGuessTagInfo(type);
if(m_editor)
m_editor->slotRefresh();
}
......@@ -592,7 +585,7 @@ void PlaylistSplitter::setupPlaylist(Playlist *p, bool raise, const char *icon,
connect(p, SIGNAL(returnPressed(QListViewItem *)),
this, SIGNAL(signalActivated()));
connect(p, SIGNAL(signalNumberOfItemsChanged(Playlist *)),
connect(p, SIGNAL(signalCountChanged(Playlist *)),
this, SLOT(slotPlaylistCountChanged(Playlist *)));
connect(p, SIGNAL(signalAboutToRemove(PlaylistItem *)),
......
......@@ -28,6 +28,7 @@
#include "collectionlist.h"
#include "stringhash.h"
#include "tageditor.h"
#include "tagguesser.h"
class KActionMenu;
class KDirWatch;
......@@ -180,8 +181,7 @@ public slots:
// Tagger slots
void slotSaveTag() { m_editor->save(); }
void slotGuessTagInfoFile();
void slotGuessTagInfoInternet();
void slotGuessTagInfo(TagGuesser::Type type);
void slotRenameFile();
// Playlist slots
......
......@@ -42,6 +42,9 @@ class FileNameScheme
class TagGuesser
{
public:
enum Type { FileName, MusicBrainz };
static QStringList schemeStrings();
static void setSchemeStrings(const QStringList &schemes);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment