Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit 3597cced authored by Zack Rusin's avatar Zack Rusin

Implementing the random play as in other modern players - meaning that although

the next item will be random it will never be the item that has been already played so
before the same item is played twice every other item will be played at least once.

CCMAIL: 56459-done@bugs.kde.org

svn path=/trunk/kdemultimedia/juk/; revision=223344
parent 2727d339
......@@ -38,6 +38,8 @@
// Playlist::SharedSettings definition
////////////////////////////////////////////////////////////////////////////////
static bool s_visibleChanged = false;
/**
* Shared settings between the playlists.
*/
......@@ -177,7 +179,8 @@ void Playlist::SharedSettings::writeConfig()
////////////////////////////////////////////////////////////////////////////////
Playlist::Playlist(QWidget *parent, const QString &name) : KListView(parent, name.latin1()),
m_playlistName(name), m_playingItem(0), m_leftColumn(0)
m_playlistName(name), m_playingItem(0),
m_leftColumn(0)
{
setup();
......@@ -256,6 +259,8 @@ void Playlist::clearItem(PlaylistItem *item, bool emitChanged)
{
emit signalAboutToRemove(item);
m_members.remove(item->absFilePath());
if (!m_randomList.isEmpty() && !s_visibleChanged)
m_randomList.remove(item);
item->deleteLater();
if(emitChanged)
emit signalNumberOfItemsChanged(this);
......@@ -290,8 +295,14 @@ PlaylistItemList Playlist::items()
PlaylistItemList Playlist::visibleItems() const
{
PlaylistItemList list;
for(PlaylistItem *i = static_cast<PlaylistItem *>(firstChild()); i; i = static_cast<PlaylistItem *>(i->itemBelow()))
list.append(i);
for(PlaylistItem *i = static_cast<PlaylistItem *>(firstChild()); i; i = static_cast<PlaylistItem *>(i->itemBelow())) {
//This check should be removed at some point since those items should all be already visible
//at the time of writing there's a bug that leaves some invisible items in the list
if(i->isVisible())
list.append(i);
else
kdDebug()<<"File shouldn't be in the list"<< i->fileName()<<endl;
}
return list;
}
......@@ -314,17 +325,19 @@ PlaylistItem *Playlist::nextItem(PlaylistItem *current, bool random)
PlaylistItem *i;
if(random) {
PlaylistItemList l = visibleItems();
if(l.count() > 1) {
m_history.push(current);
srand(time(0));
i = current;
while(i == current)
i = l[rand() % l.count()];
}
else
i = 0;
if (m_randomList.count()<=1 || s_visibleChanged) {
m_randomList = visibleItems();
s_visibleChanged = false;//got the change
}
m_randomList.remove(current);
m_history.push(current);
i = current;
while(i == current) {
i = m_randomList[KApplication::random() % m_randomList.count()];
}
}
else
i = static_cast<PlaylistItem *>(current->itemBelow());
......@@ -337,8 +350,12 @@ PlaylistItem *Playlist::previousItem(PlaylistItem *current, bool random)
if(!current)
return 0;
if(random && !m_history.isEmpty())
return m_history.pop();
if(random && !m_history.isEmpty()) {
PlaylistItem * item = m_history.pop();
//should we add it to the random list ?
//m_randomList.append(item);
return item;
}
if(!current->itemAbove())
return current;
......@@ -375,6 +392,7 @@ void Playlist::updateLeftColumn()
void Playlist::setItemsVisible(const PlaylistItemList &items, bool visible)
{
s_visibleChanged = true;
for(PlaylistItemList::ConstIterator it = items.begin(); it != items.end(); ++it)
(*it)->setVisible(visible);
}
......@@ -384,11 +402,11 @@ void Playlist::setItemsVisible(const PlaylistItemList &items, bool visible)
////////////////////////////////////////////////////////////////////////////////
void Playlist::slotSetNext()
{
{
if(!selectedItems().isEmpty())
emit signalSetNext(selectedItems().first());
}
void Playlist::copy()
{
kapp->clipboard()->setData(dragObject(0), QClipboard::Clipboard);
......@@ -431,7 +449,7 @@ void Playlist::slotReload()
QFileInfo fileInfo(m_fileName);
if(!fileInfo.exists() || !fileInfo.isFile() || !fileInfo.isReadable())
return;
clear();
loadFile(m_fileName, fileInfo);
}
......@@ -459,6 +477,8 @@ void Playlist::deleteFromDisk(const PlaylistItemList &items)
for(PlaylistItemList::ConstIterator it = items.begin(); it != items.end(); ++it) {
if(QFile::remove((*it)->filePath())) {
emit signalAboutToRemove(*it);
if(!m_randomList.isEmpty() && !s_visibleChanged)
m_randomList.remove(*it);
delete *it;
}
else
......@@ -565,12 +585,12 @@ PlaylistItem *Playlist::createItem(const QFileInfo &file, const QString &absFile
filePath = resolveSymLinks(file);
else
filePath = absFilePath;
CollectionListItem *item = CollectionList::instance()->lookup(filePath);
if(!item) {
item = new CollectionListItem(file, filePath);
// If a valid tag was not created, destroy the CollectionListItem.
if(!item->isValid()) {
kdError() << "Playlist::createItem() -- A valid tag was not created for \"" << file.filePath() << "\"" << endl;
......@@ -585,6 +605,8 @@ PlaylistItem *Playlist::createItem(const QFileInfo &file, const QString &absFile
i = new PlaylistItem(item, this, after);
else
i = new PlaylistItem(item, this);
if(!m_randomList.isEmpty() && !s_visibleChanged)
m_randomList.append(i);
emit signalNumberOfItemsChanged(this);
connect(item, SIGNAL(destroyed()), i, SLOT(deleteLater()));
return i;
......@@ -596,7 +618,7 @@ PlaylistItem *Playlist::createItem(const QFileInfo &file, const QString &absFile
void Playlist::createItems(const PlaylistItemList &siblings)
{
PlaylistItem *previous = 0;
for(PlaylistItemList::ConstIterator it = siblings.begin(); it != siblings.end(); ++it) {
if(!m_members.insert(resolveSymLinks((*it)->absFilePath()))) {
......@@ -664,7 +686,7 @@ QString Playlist::resolveSymLinks(const QFileInfo &file)
return QFile::decodeName(real);
else
return file.filePath();
}
////////////////////////////////////////////////////////////////////////////////
......@@ -917,11 +939,11 @@ void Playlist::slotApplyModification(QListViewItem *item, const QString &text, i
if (selectedSongs.count() > 1)
{
if (KMessageBox::warningYesNo(0,
i18n("This will rename multiple files! Are you sure?"),
QString::null,
KStdGuiItem::yes(),
KStdGuiItem::no(),
"DontWarnMultipleTags") == KMessageBox::No)
i18n("This will rename multiple files! Are you sure?"),
QString::null,
KStdGuiItem::yes(),
KStdGuiItem::no(),
"DontWarnMultipleTags") == KMessageBox::No)
{
return;
}
......
......@@ -41,14 +41,14 @@ class Playlist : public KListView
Q_OBJECT
public:
/**
* Before creating a playlist directly, please see
/**
* Before creating a playlist directly, please see
* PlaylistSplitter::createPlaylist().
*/
Playlist(QWidget *parent, const QString &name = QString::null);
/**
* Before creating a playlist directly, please see
/**
* Before creating a playlist directly, please see
* PlaylistSplitter::openPlaylist().
*/
Playlist(const QFileInfo &playlistFile, QWidget *parent, const char *name = 0);
......@@ -58,7 +58,7 @@ public:
/**
* Saves the file to the currently set file name. If there is no filename
* currently set, the default behavior is to prompt the user for a file
* name.
* name.
*/
virtual void save();
virtual void saveAs();
......@@ -66,38 +66,38 @@ public:
virtual void clearItem(PlaylistItem *item, bool emitChanged = true);
virtual void clearItems(const PlaylistItemList &items);
/**
* All of the (media) files in the list.
/**
* All of the (media) files in the list.
*/
QStringList files() const;
/**
/**
* Returns a list of all of the \e visible items in the playlist.
*/
PlaylistItemList items();
/**
/**
* Returns a list of all of the items in the playlist.
*/
PlaylistItemList visibleItems() const;
/**
* Returns a list of the currently selected items.
*/
PlaylistItemList selectedItems() const;
/**
* Allow duplicate files in the playlist.
/**
* Allow duplicate files in the playlist.
*/
void setAllowDuplicates(bool allow);
/**
/**
* This is being used as a mini-factory of sorts to make the construction
* of PlaylistItems virtual. In this case it allows for the creation of
* both PlaylistItems and CollectionListItems.
*/
virtual PlaylistItem *createItem(const QFileInfo &file,
const QString &absFilePath = QString::null,
virtual PlaylistItem *createItem(const QFileInfo &file,
const QString &absFilePath = QString::null,
QListViewItem *after = 0);
void createItems(const PlaylistItemList &siblings);
......@@ -110,7 +110,7 @@ public:
bool isColumnVisible(int c) const;
/**
* If m_playlistName has no value -- i.e. the name has not been set to
* If m_playlistName has no value -- i.e. the name has not been set to
* something other than the filename, this returns the filename less the
* extension. If m_playlistName does have a value, this returns that.
*/
......@@ -118,13 +118,13 @@ public:
/**
* This sets a name for the playlist that is \e different from the file name.
*/
*/
void setName(const QString &n);
int count() const { return childCount(); }
/**
* This gets the next item to be played. This is static because often we
/**
* This gets the next item to be played. This is static because often we
* know about the playing item, but not to which list it belongs.
*/
PlaylistItem *nextItem(PlaylistItem *current, bool random = false);
......@@ -133,11 +133,11 @@ public:
KActionMenu *columnVisibleAction() const { return m_columnVisibleAction; }
void setPlaying(PlaylistItem *item, bool playing = true);
/**
* This forces an update of the left most visible column, but does not save
* the settings for this.
*/
*/
void updateLeftColumn();
static void setItemsVisible(const PlaylistItemList &items, bool visible = true);
......@@ -145,7 +145,7 @@ public:
public slots:
/**
* Remove the currently selected items from the playlist and disk.
*/
*/
void slotDeleteSelectedItems() { deleteFromDisk(selectedItems()); };
void slotSetNext();
......@@ -182,7 +182,7 @@ protected:
virtual void contentsDropEvent(QDropEvent *e);
virtual void contentsDragMoveEvent(QDragMoveEvent *e);
virtual void showEvent(QShowEvent *e);
/**
* Though it's somewhat obvious, this function will stat the file, so only use it when
* you're out of a performance critical loop.
......@@ -193,35 +193,35 @@ protected:
const KPopupMenu *rmbMenu() const { return m_rmbMenu; }
signals:
/**
* This signal is connected to PlaylistItem::refreshed() in the
* PlaylistItem class.
/**
* 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.
* primarily to notify the TagEditor of the new data.
*/
void signalSelectionChanged(const PlaylistItemList &selection);
/**
* This is connected to the PlaylistBox::Item to let it know when the
* This is connected to the PlaylistBox::Item to let it know when the
* playlist's name has changed.
*/
void signalNameChanged(const QString &fileName);
void signalNumberOfItemsChanged(Playlist *);
void signalDoubleClicked();
/**
* This signal is emitted just before a playlist item is removed from the
* This signal is emitted just before a playlist item is removed from the
* list.
*/
void signalAboutToRemove(PlaylistItem *item);
void signalFilesDropped(const QStringList &files, Playlist *);
void signalSetNext(PlaylistItem *item);
void signalSetNext(PlaylistItem *item);
void signalVisibleColumnsChanged();
private:
......@@ -259,7 +259,7 @@ private:
* file name.
*/
QString m_playlistName;
KPopupMenu *m_rmbMenu;
KPopupMenu *m_headerMenu;
KActionMenu *m_columnVisibleAction;
......@@ -269,6 +269,8 @@ private:
PlaylistItem *m_playingItem;
int m_leftColumn;
PlaylistItemList m_randomList;
};
QDataStream &operator<<(QDataStream &s, const Playlist &p);
......
......@@ -34,19 +34,19 @@ class CollectionListItem;
typedef QValueList<PlaylistItem *> PlaylistItemList;
/**
* Items for the Playlist and the baseclass for CollectionListItem.
* Items for the Playlist and the baseclass for CollectionListItem.
* The constructors and destructor are protected and new items should be
* created via Playlist::createItem(). Items should be removed by
* Playlist::clear(), Playlist::deleteFromDisk(), Playlist::clearItem() or
* Playlist::clearItem().
*/
class PlaylistItem : public QObject, public KListViewItem
class PlaylistItem : public QObject, public KListViewItem
{
friend class Playlist;
friend class CollectionList;
/**
/**
* Needs access to the destuctor, even though the destructor isn't used by QPtrStack.
*/
friend class QPtrStack<PlaylistItem>;
......@@ -65,7 +65,7 @@ public:
const Tag *tag() const;
// These are just forwarding methods to PlaylistItem::Data, a QFileInfo
// These are just forwarding methods to PlaylistItem::Data, a QFileInfo
// subclass.
QString fileName() const;
......@@ -80,7 +80,7 @@ public:
public slots:
/**
* This just refreshes from the in memory data. This may seem pointless at
* This just refreshes from the in memory data. This may seem pointless at
* first, but this data is shared between all of the list view items that are
* based on the same file, so if another one of those items changes its data
* it is important to refresh the others.
......@@ -94,9 +94,9 @@ public slots:
virtual void slotRefreshFromDisk();
protected:
/**
/**
* Items should always be created using Playlist::createItem() or through a
* subclss or friend class.
* subclss or friend class.
*/
PlaylistItem(CollectionListItem *item, Playlist *parent);
PlaylistItem(CollectionListItem *item, Playlist *parent, QListViewItem *after);
......@@ -141,8 +141,8 @@ private:
};
/**
* This is the data class for PlaylistItems. Several PlaylistItems that are
* based on the same file will share the m_data member. This has both the
* This is the data class for PlaylistItems. Several PlaylistItems that are
* based on the same file will share the m_data member. This has both the
* advantages of being memory efficient and allowing the PlaylistItems to stay
* synchronized.
*
......
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