aboutsummaryrefslogtreecommitdiff
path: root/src/qmmpui
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2015-01-09 12:01:22 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2015-01-09 12:01:22 +0000
commitebd7f9bc697973366de8a6bf7265051e825e0680 (patch)
tree1feb9df1c5fe3493e9aa1dd8f5d6233a38ae9d3c /src/qmmpui
parentbc7ad688c646afd2a89e5c5ff58696f2df2c8605 (diff)
downloadqmmp-ebd7f9bc697973366de8a6bf7265051e825e0680.tar.gz
qmmp-ebd7f9bc697973366de8a6bf7265051e825e0680.tar.bz2
qmmp-ebd7f9bc697973366de8a6bf7265051e825e0680.zip
renaming experimental branch
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@4675 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src/qmmpui')
-rw-r--r--src/qmmpui/CMakeLists.txt28
-rw-r--r--src/qmmpui/aboutdialog.cpp6
-rw-r--r--src/qmmpui/groupedcontainer.cpp98
-rw-r--r--src/qmmpui/groupedcontainer_p.h5
-rw-r--r--src/qmmpui/normalcontainer.cpp48
-rw-r--r--src/qmmpui/normalcontainer_p.h5
-rw-r--r--src/qmmpui/playlistcontainer.cpp205
-rw-r--r--src/qmmpui/playlistcontainer_p.h10
-rw-r--r--src/qmmpui/playlistgroup.cpp10
-rw-r--r--src/qmmpui/playlistmanager.cpp10
-rw-r--r--src/qmmpui/playlistmanager.h4
-rw-r--r--src/qmmpui/playlistmodel.cpp351
-rw-r--r--src/qmmpui/playlistmodel.h34
-rw-r--r--src/qmmpui/playlisttask.cpp371
-rw-r--r--src/qmmpui/playlisttask_p.h52
-rw-r--r--src/qmmpui/playlisttrack.cpp54
-rw-r--r--src/qmmpui/playlisttrack.h33
-rw-r--r--src/qmmpui/qmmpuisettings.cpp4
-rw-r--r--src/qmmpui/qmmpuisettings.h2
-rw-r--r--src/qmmpui/tagupdater.cpp6
20 files changed, 755 insertions, 581 deletions
diff --git a/src/qmmpui/CMakeLists.txt b/src/qmmpui/CMakeLists.txt
index 14525d47e..18aab75ce 100644
--- a/src/qmmpui/CMakeLists.txt
+++ b/src/qmmpui/CMakeLists.txt
@@ -1,6 +1,6 @@
project(libqmmpui)
-cmake_minimum_required(VERSION 2.4.7)
+cmake_minimum_required(VERSION 2.8.6)
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 OLD)
@@ -59,6 +59,7 @@ SET(libqmmpui_SRCS
addurldialog.cpp
qmmpuiplugincache.cpp
tagupdater.cpp
+ playlisttask.cpp
)
SET(libqmmpui_HDRS
@@ -83,27 +84,6 @@ SET(libqmmpui_HDRS
qmmpuiplugincache_p.h
)
-SET(libqmmpui_MOC_HDRS
- uihelper.h
- filedialog.h
- qtfiledialog_p.h
- fileloader_p.h
- playlistmodel.h
- mediaplayer.h
- detailsdialog.h
- tageditor_p.h
- playlistmanager.h
- templateeditor.h
- jumptotrackdialog_p.h
- configdialog.h
- aboutdialog_p.h
- qmmpuisettings.h
- radioitemdelegate_p.h
- playlistdownloader.h
- addurldialog_p.h
- tagupdater_p.h
-)
-
SET(libqmmpui_DEVEL_HDRS
commandlinemanager.h
commandlineoption.h
@@ -145,11 +125,9 @@ QT4_WRAP_UI(libqmmpui_UIS_H ${libqmmpui_UIS})
QT4_ADD_RESOURCES(libqmmpui_RCC_SRCS translations/libqmmpui_locales.qrc txt/txt.qrc images/qmmpui_images.qrc)
-QT4_WRAP_CPP(libqmmpui_MOC_SRCS ${libqmmpui_MOC_HDRS})
-
include_directories(${CMAKE_CURRENT_BINARY_DIR})
-ADD_LIBRARY(qmmpui SHARED ${libqmmpui_SRCS} ${libqmmpui_MOC_SRCS} ${libqmmpui_RCC_SRCS} ${libqmmpui_UIS_H} ${libqmmpui_HDRS})
+ADD_LIBRARY(qmmpui SHARED ${libqmmpui_SRCS} ${libqmmpui_RCC_SRCS} ${libqmmpui_UIS_H} ${libqmmpui_HDRS})
target_link_libraries(qmmpui ${QT_LIBRARIES} -lqmmp)
add_dependencies(qmmpui libqmmp)
SET_TARGET_PROPERTIES(qmmpui PROPERTIES VERSION ${QMMP_VERSION} SOVERSION ${QMMP_SOVERSION})
diff --git a/src/qmmpui/aboutdialog.cpp b/src/qmmpui/aboutdialog.cpp
index 073a3187d..888f3ea68 100644
--- a/src/qmmpui/aboutdialog.cpp
+++ b/src/qmmpui/aboutdialog.cpp
@@ -1,5 +1,5 @@
-/***************************************************************************
-* Copyright (C) 2006-2013 by Ilya Kotov *
+/**************************************************************************
+* Copyright (C) 2006-2015 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -68,7 +68,7 @@ QString AboutDialog::loadAbout()
text.append(tr("Using Qt %1 (compiled with Qt %2)" ).arg(qVersion()).arg(QT_VERSION_STR) + "</p>");
text.append("<p>");
- text.append(tr("(c) %1-%2 Qmmp Development Team").arg(2006).arg(2014)+"<br>");
+ text.append(tr("(c) %1-%2 Qmmp Development Team").arg(2006).arg(2015)+"<br>");
text.append("<a href=\"http://qmmp.ylsoftware.com/\">http://qmmp.ylsoftware.com/</a><br>");
text.append("<a href=\"http://code.google.com/p/qmmp/\">http://code.google.com/p/qmmp/</a>");
text.append("</p>");
diff --git a/src/qmmpui/groupedcontainer.cpp b/src/qmmpui/groupedcontainer.cpp
index e98cf88f6..c6628a845 100644
--- a/src/qmmpui/groupedcontainer.cpp
+++ b/src/qmmpui/groupedcontainer.cpp
@@ -23,7 +23,6 @@
GroupedContainer::GroupedContainer()
{
- m_reverted = false;
m_update = true;
}
@@ -65,31 +64,26 @@ void GroupedContainer::addTrack(PlayListTrack *track)
void GroupedContainer::addTracks(QList<PlayListTrack *> tracks)
{
- PlayListGroup *group = m_groups.isEmpty() ? 0 : m_groups.last();
+ bool found = false;
- foreach (PlayListTrack *track, tracks)
+ for(int i = 0; i < tracks.count(); ++i)
{
- if(!group || track->groupName() != group->formattedTitle())
+ found = false;
+ for(int j = m_groups.count() - 1; j >= 0; --j)
{
- group = 0;
- foreach(PlayListGroup *g, m_groups)
+ if(m_groups.at(j)->formattedTitle() == tracks.at(i)->groupName())
{
- if(track->groupName() == g->formattedTitle())
- {
- group = g;
- break;
- }
+ found = true;
+ m_groups.at(j)->trackList.append(tracks[i]);
+ break;
}
}
- if(!group)
- {
- group = new PlayListGroup(track->groupName());
- m_groups.append(group);
- m_update = true;
- }
+ if(found)
+ continue;
- group->trackList.append(track);
+ m_groups << new PlayListGroup(tracks.at(i)->groupName());
+ m_groups.last()->trackList.append(tracks.at(i));
}
m_update = true;
}
@@ -123,11 +117,31 @@ void GroupedContainer::insertTrack(int index, PlayListTrack *track)
addTrack(track);
}
+void GroupedContainer::replaceTracks(QList<PlayListTrack *> tracks)
+{
+ foreach (PlayListGroup *g, m_groups)
+ {
+ g->trackList.clear();
+ }
+ clear();
+ addTracks(tracks);
+}
+
QList<PlayListGroup *> GroupedContainer::groups() const
{
return m_groups;
}
+QList<PlayListTrack *> GroupedContainer::tracks() const
+{
+ QList<PlayListTrack *> trackList;
+ for(int i = 0; i < m_groups.count(); ++i)
+ {
+ trackList.append(m_groups[i]->trackList);
+ }
+ return trackList;
+}
+
QList<PlayListItem *> GroupedContainer::items() const
{
updateCache();
@@ -389,55 +403,21 @@ void GroupedContainer::reverseList()
void GroupedContainer::randomizeList()
{
- QList<PlayListTrack *> tracks = takeAllTracks();
-
- for (int i = 0; i < tracks.size(); i++)
- tracks.swap(qrand()%tracks.size(),qrand()%tracks.size());
-
- addTracks(tracks);
-}
-
-void GroupedContainer::sort(int mode)
-{
- if(mode == PlayListModel::ARTIST || mode == PlayListModel::ALBUM
- || mode == PlayListModel::DATE || mode == PlayListModel::GROUP)
- {
- QList<PlayListTrack *> tracks = takeAllTracks();
- doSort(mode, tracks, m_reverted);
- addTracks(tracks);
- }
- else
+ for(int i = 0; i < m_groups.count(); ++i)
{
- foreach (PlayListGroup *g, m_groups)
+ for (int j = 0; j < m_groups[i]->trackList.size(); j++)
{
- doSort(mode, g->trackList, m_reverted);
+ m_groups[i]->trackList.swap(qrand() % m_groups[i]->trackList.size(),
+ qrand() % m_groups[i]->trackList.size());
}
- m_update = true;
}
- m_reverted = !m_reverted;
-}
-void GroupedContainer::sortSelection(int mode)
-{
- QList<PlayListTrack *> tracks = takeAllTracks();
- QList<PlayListTrack *> selected_tracks;
- QList<int> selected_indexes;
- for(int i = 0; i < tracks.count(); ++i)
+ for(int i = 0; i < m_groups.count(); ++i)
{
- if(tracks[i]->isSelected())
- {
- selected_tracks.append(tracks[i]);
- selected_indexes.append(i);
- }
+ m_groups.swap(qrand() % m_groups.size(), qrand() % m_groups.size());
}
- doSort(mode, selected_tracks, m_reverted);
-
- for (int i = 0; i < selected_indexes.count(); i++)
- tracks.replace(selected_indexes[i], selected_tracks[i]);
- addTracks(tracks);
-
- m_reverted = !m_reverted;
+ m_update = true;
}
void GroupedContainer::updateCache() const
diff --git a/src/qmmpui/groupedcontainer_p.h b/src/qmmpui/groupedcontainer_p.h
index 241b07fc4..449493144 100644
--- a/src/qmmpui/groupedcontainer_p.h
+++ b/src/qmmpui/groupedcontainer_p.h
@@ -37,7 +37,9 @@ public:
void addTrack(PlayListTrack *track);
void addTracks(QList<PlayListTrack *> tracks);
void insertTrack(int index, PlayListTrack *track);
+ void replaceTracks(QList<PlayListTrack *> tracks);
QList<PlayListGroup *> groups() const;
+ QList<PlayListTrack *> tracks() const;
QList<PlayListItem *> items() const;
int count() const;
int trackCount() const;
@@ -61,13 +63,10 @@ public:
void reverseList();
void randomizeList();
- void sort(int mode);
- void sortSelection(int mode);
private:
void updateCache() const;
QList<PlayListGroup *> m_groups;
- bool m_reverted;
mutable QList<PlayListItem *> m_items;
mutable bool m_update;
diff --git a/src/qmmpui/normalcontainer.cpp b/src/qmmpui/normalcontainer.cpp
index 4e585b9d6..b26b33d06 100644
--- a/src/qmmpui/normalcontainer.cpp
+++ b/src/qmmpui/normalcontainer.cpp
@@ -21,9 +21,7 @@
#include "normalcontainer_p.h"
NormalContainer::NormalContainer()
-{
- m_reverted = false;
-}
+{}
NormalContainer::~NormalContainer()
{
@@ -46,11 +44,25 @@ void NormalContainer::insertTrack(int index, PlayListTrack *track)
m_items.append(track);
}
+void NormalContainer::replaceTracks(QList<PlayListTrack *> tracks)
+{
+ m_items.clear();
+ addTracks(tracks);
+}
+
QList<PlayListGroup *> NormalContainer::groups() const
{
return QList<PlayListGroup *>();
}
+QList<PlayListTrack *> NormalContainer::tracks() const
+{
+ QList<PlayListTrack *> trackList;
+ for(int i = 0; i < m_items.count(); ++i)
+ trackList.append(dynamic_cast<PlayListTrack *>(m_items[i]));
+ return trackList;
+}
+
QList<PlayListItem *> NormalContainer::items() const
{
return m_items;
@@ -205,33 +217,3 @@ void NormalContainer::randomizeList()
for (int i = 0; i < m_items.size(); i++)
m_items.swap(qrand()%m_items.size(), qrand()%m_items.size());
}
-
-void NormalContainer::sort(int mode)
-{
- QList<PlayListTrack *> tracks = takeAllTracks();
- doSort(mode, tracks, m_reverted);
- addTracks(tracks);
- m_reverted = !m_reverted;
-}
-
-void NormalContainer::sortSelection(int mode)
-{
- QList<PlayListTrack *> tracks = takeAllTracks();
- QList<PlayListTrack *> selected_tracks;
- QList<int> selected_indexes;
- for(int i = 0; i < tracks.count(); ++i)
- {
- if(tracks[i]->isSelected())
- {
- selected_tracks.append(tracks[i]);
- selected_indexes.append(i);
- }
- }
- doSort(mode, selected_tracks, m_reverted);
-
- for (int i = 0; i < selected_indexes.count(); i++)
- tracks.replace(selected_indexes[i], selected_tracks[i]);
-
- addTracks(tracks);
- m_reverted = !m_reverted;
-}
diff --git a/src/qmmpui/normalcontainer_p.h b/src/qmmpui/normalcontainer_p.h
index c2aab57f1..803b8ada0 100644
--- a/src/qmmpui/normalcontainer_p.h
+++ b/src/qmmpui/normalcontainer_p.h
@@ -36,7 +36,9 @@ public:
void addTracks(QList<PlayListTrack *> tracks);
void insertTrack(int index, PlayListTrack *track);
+ void replaceTracks(QList<PlayListTrack *> tracks);
QList<PlayListGroup *> groups() const;
+ QList<PlayListTrack *> tracks() const;
QList<PlayListItem *> items() const;
int count() const;
int trackCount() const;
@@ -60,12 +62,9 @@ public:
void reverseList();
void randomizeList();
- void sort(int mode);
- void sortSelection(int mode);
private:
QList<PlayListItem *> m_items;
- bool m_reverted;
};
#endif // NORMALCONTAINER_P_H
diff --git a/src/qmmpui/playlistcontainer.cpp b/src/qmmpui/playlistcontainer.cpp
index 7772d1b3e..c7aaf3482 100644
--- a/src/qmmpui/playlistcontainer.cpp
+++ b/src/qmmpui/playlistcontainer.cpp
@@ -28,208 +28,3 @@ void PlayListContainer::addTrack(PlayListTrack *track)
{
addTracks(QList<PlayListTrack *> () << track);
}
-
-////===============THE BEGINNING OF SORT IMPLEMENTATION =======================////
-
-// First we'll implement bundle of static compare procedures
-// to sort items in different ways
-
-//by title
-static bool _titleLessComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QString::localeAwareCompare (s1->value(Qmmp::TITLE), s2->value(Qmmp::TITLE)) < 0;
-}
-
-static bool _titleGreaterComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QString::localeAwareCompare (s1->value(Qmmp::TITLE), s2->value(Qmmp::TITLE)) > 0;
-}
-//by album+disc
-static bool _discnumberLessComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QString::localeAwareCompare (s1->value(Qmmp::DISCNUMBER), s2->value(Qmmp::DISCNUMBER)) < 0;
-}
-
-static bool _discnumberGreaterComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QString::localeAwareCompare (s1->value(Qmmp::DISCNUMBER), s2->value(Qmmp::DISCNUMBER)) > 0;
-}
-//by album
-static bool _albumLessComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QString::localeAwareCompare (s1->value(Qmmp::ALBUM), s2->value(Qmmp::ALBUM)) < 0;
-}
-
-static bool _albumGreaterComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QString::localeAwareCompare (s1->value(Qmmp::ALBUM), s2->value(Qmmp::ALBUM)) > 0;
-}
-//by artist
-static bool _artistLessComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QString::localeAwareCompare (s1->value(Qmmp::ARTIST), s2->value(Qmmp::ARTIST)) < 0;
-}
-
-static bool _artistGreaterComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QString::localeAwareCompare (s1->value(Qmmp::ARTIST), s2->value(Qmmp::ARTIST)) > 0;
-}
-//by album artist
-static bool _albumArtistLessComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QString::localeAwareCompare (s1->value(Qmmp::ALBUMARTIST), s2->value(Qmmp::ALBUMARTIST)) < 0;
-}
-
-static bool _albumArtistGreaterComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QString::localeAwareCompare (s1->value(Qmmp::ALBUMARTIST), s2->value(Qmmp::ALBUMARTIST)) > 0;
-}
-//by path
-static bool _pathAndFilenameLessComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QString::localeAwareCompare (s1->url(), s2->url()) < 0;
-}
-
-static bool _pathAndFilenameGreaterComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QString::localeAwareCompare (s1->url(), s2->url()) > 0;
-}
-//by file name
-static bool _filenameLessComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- QFileInfo i_s1(s1->url());
- QFileInfo i_s2(s2->url());
- return QString::localeAwareCompare (i_s1.baseName(), i_s2.baseName()) < 0;
-}
-
-static bool _filenameGreaterComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- QFileInfo i_s1(s1->url());
- QFileInfo i_s2(s2->url());
- return QString::localeAwareCompare (i_s1.baseName(), i_s2.baseName()) > 0;
-}
-//by date
-static bool _dateLessComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return s1->value(Qmmp::YEAR).toInt() < s2->value(Qmmp::YEAR).toInt();
-}
-
-static bool _dateGreaterComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return s1->value(Qmmp::YEAR).toInt() > s2->value(Qmmp::YEAR).toInt();
-}
-//by track
-static bool _trackLessComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return s1->value(Qmmp::TRACK).toInt() < s2->value(Qmmp::TRACK).toInt();
-}
-
-static bool _trackGreaterComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return s1->value(Qmmp::TRACK).toInt() > s2->value(Qmmp::TRACK).toInt();
-}
-//by file creation date
-static bool _fileCreationDateLessComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QFileInfo(s1->value(Qmmp::URL)).created() < QFileInfo(s2->value(Qmmp::URL)).created();
-}
-
-static bool _fileCreationDateGreaterComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QFileInfo(s1->value(Qmmp::URL)).created() > QFileInfo(s2->value(Qmmp::URL)).created();
-}
-//by file modification date
-static bool _fileModificationDateLessComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QFileInfo(s1->value(Qmmp::URL)).lastModified() < QFileInfo(s2->value(Qmmp::URL)).lastModified();
-}
-
-static bool _fileModificationDateGreaterComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QFileInfo(s1->value(Qmmp::URL)).lastModified() > QFileInfo(s2->value(Qmmp::URL)).lastModified();
-}
-
-//by group
-static bool _groupLessComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QString::localeAwareCompare (s1->groupName(), s2->groupName()) < 0;
-}
-
-static bool _groupGreaterComparator(PlayListTrack* s1,PlayListTrack* s2)
-{
- return QString::localeAwareCompare (s1->groupName(), s2->groupName()) > 0;
-}
-
-void PlayListContainer::doSort(int sort_mode, QList<PlayListTrack*>& list_to_sort, bool reverted)
-{
- QList<PlayListTrack*>::iterator begin;
- QList<PlayListTrack*>::iterator end;
-
- begin = list_to_sort.begin();
- end = list_to_sort.end();
-
- bool(*compareLessFunc)(PlayListTrack*,PlayListTrack*) = 0;
- bool(*compareGreaterFunc)(PlayListTrack*,PlayListTrack*) = 0;
-
- switch (sort_mode)
- {
- case PlayListModel::TITLE:
- compareLessFunc = _titleLessComparator;
- compareGreaterFunc = _titleGreaterComparator;
- break;
- case PlayListModel::DISCNUMBER:
- compareLessFunc = _discnumberLessComparator;
- compareGreaterFunc = _discnumberGreaterComparator;
- break;
- case PlayListModel::ALBUM:
- compareLessFunc = _albumLessComparator;
- compareGreaterFunc = _albumGreaterComparator;
- break;
- case PlayListModel::ARTIST:
- compareLessFunc = _artistLessComparator;
- compareGreaterFunc = _artistGreaterComparator;
- break;
- case PlayListModel::ALBUMARTIST:
- compareLessFunc = _albumArtistLessComparator;
- compareGreaterFunc = _albumArtistGreaterComparator;
- break;
- case PlayListModel::FILENAME:
- compareLessFunc = _filenameLessComparator;
- compareGreaterFunc = _filenameGreaterComparator;
- break;
- case PlayListModel::PATH_AND_FILENAME:
- compareLessFunc = _pathAndFilenameLessComparator;
- compareGreaterFunc = _pathAndFilenameGreaterComparator;
- break;
- case PlayListModel::DATE:
- compareLessFunc = _dateLessComparator;
- compareGreaterFunc = _dateGreaterComparator;
- break;
- case PlayListModel::TRACK:
- compareLessFunc = _trackLessComparator;
- compareGreaterFunc = _trackGreaterComparator;
- break;
- case PlayListModel::FILE_CREATION_DATE:
- compareLessFunc = _fileCreationDateLessComparator;
- compareGreaterFunc = _fileCreationDateGreaterComparator;
- break;
- case PlayListModel::FILE_MODIFICATION_DATE:
- compareLessFunc = _fileModificationDateLessComparator;
- compareGreaterFunc = _fileModificationDateGreaterComparator;
- break;
- case PlayListModel::GROUP:
- compareLessFunc = _groupLessComparator;
- compareGreaterFunc = _groupGreaterComparator;
- break;
- default:
- compareLessFunc = _titleLessComparator;
- compareGreaterFunc = _titleGreaterComparator;
- }
-
- if(reverted)
- qStableSort(begin,end,compareGreaterFunc);
- else
- qStableSort(begin,end,compareLessFunc);
-}
-
-////=============== THE END OF SORT IMPLEMENTATION =======================////
diff --git a/src/qmmpui/playlistcontainer_p.h b/src/qmmpui/playlistcontainer_p.h
index b72aa4519..351a3b30f 100644
--- a/src/qmmpui/playlistcontainer_p.h
+++ b/src/qmmpui/playlistcontainer_p.h
@@ -41,8 +41,10 @@ public:
virtual void addTrack(PlayListTrack *track);
virtual void addTracks(QList<PlayListTrack *> tracks) = 0;
virtual void insertTrack(int index, PlayListTrack *track) = 0;
+ virtual void replaceTracks(QList<PlayListTrack *> tracks) = 0;
virtual QList<PlayListGroup *> groups() const = 0;
virtual QList<PlayListItem *> items() const = 0;
+ virtual QList<PlayListTrack *> tracks() const = 0;
virtual int count() const = 0;
virtual int trackCount() const = 0;
virtual QList<PlayListItem *> mid(int pos, int count) const = 0;
@@ -65,14 +67,6 @@ public:
virtual void reverseList() = 0;
virtual void randomizeList() = 0;
- virtual void sort(int mode) = 0;
- virtual void sortSelection(int mode) = 0;
-
-protected:
- /*!
- * This internal method performs sorting of \b list_to_sort list of items.
- */
- void doSort(int sort_mode, QList<PlayListTrack*>& list_to_sort, bool reverted);
};
#endif // PLAYLISTCONTAINER_P_H
diff --git a/src/qmmpui/playlistgroup.cpp b/src/qmmpui/playlistgroup.cpp
index d5d5ba42b..ad3a5bc16 100644
--- a/src/qmmpui/playlistgroup.cpp
+++ b/src/qmmpui/playlistgroup.cpp
@@ -31,14 +31,10 @@ PlayListGroup::~PlayListGroup()
{
PlayListTrack* mf = trackList.takeFirst();
- if (mf->flag() == PlayListTrack::FREE)
- {
+ if (mf->isUsed())
+ mf->deleteLater();
+ else
delete mf;
- }
- else if (mf->flag() == PlayListTrack::EDITING)
- {
- mf->setFlag(PlayListTrack::SCHEDULED_FOR_DELETION);
- }
}
}
diff --git a/src/qmmpui/playlistmanager.cpp b/src/qmmpui/playlistmanager.cpp
index e99a49a81..17dbd67e8 100644
--- a/src/qmmpui/playlistmanager.cpp
+++ b/src/qmmpui/playlistmanager.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2009-2014 by Ilya Kotov *
+ * Copyright (C) 2009-2015 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -166,7 +166,7 @@ PlayListModel *PlayListManager::createPlayList(const QString &name)
}
m_models.append(model);
connect(model, SIGNAL(nameChanged(QString)), SIGNAL(playListsChanged()));
- connect(model, SIGNAL(countChanged()), SLOT(onCountChanged()));
+ connect(model, SIGNAL(listChanged(int)), SLOT(onListChanged(int)));
emit playListAdded(m_models.indexOf(model));
selectPlayList(model);
return model;
@@ -314,7 +314,7 @@ void PlayListManager::readPlayLists()
foreach(PlayListModel *model, m_models)
{
connect(model, SIGNAL(nameChanged(QString)), SIGNAL(playListsChanged()));
- connect(model, SIGNAL(countChanged()), SLOT(onCountChanged()));
+ connect(model, SIGNAL(listChanged(int)), SLOT(onListChanged(int)));
}
}
@@ -373,9 +373,9 @@ void PlayListManager::writePlayLists()
}
}
-void PlayListManager::onCountChanged()
+void PlayListManager::onListChanged(int flags)
{
- if(m_ui_settings->autoSavePlayList())
+ if((flags & PlayListModel::STRUCTURE) && m_ui_settings->autoSavePlayList())
m_timer->start();
}
diff --git a/src/qmmpui/playlistmanager.h b/src/qmmpui/playlistmanager.h
index 6962fb2ba..4222273aa 100644
--- a/src/qmmpui/playlistmanager.h
+++ b/src/qmmpui/playlistmanager.h
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2009-2014 by Ilya Kotov *
+ * Copyright (C) 2009-2015 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -239,7 +239,7 @@ public slots:
private slots:
void writePlayLists();
- void onCountChanged();
+ void onListChanged(int flags);
private:
void readPlayLists();
diff --git a/src/qmmpui/playlistmodel.cpp b/src/qmmpui/playlistmodel.cpp
index c41bd11c1..52392ed64 100644
--- a/src/qmmpui/playlistmodel.cpp
+++ b/src/qmmpui/playlistmodel.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright(C) 2006-2014 by Ilya Kotov *
+ * Copyright(C) 2006-2015 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -27,6 +27,7 @@
#include "playlistcontainer_p.h"
#include "groupedcontainer_p.h"
#include "normalcontainer_p.h"
+#include "playlisttask_p.h"
#include "fileloader_p.h"
#include "playstate_p.h"
#include "detailsdialog.h"
@@ -46,6 +47,7 @@ PlayListModel::PlayListModel(const QString &name, QObject *parent)
m_stop_track = 0;
m_name = name;
m_loader = new FileLoader(this);
+ m_task = new PlayListTask(this);
if(m_ui_settings->isGroupsEnabled())
m_container = new GroupedContainer;
else
@@ -62,6 +64,7 @@ PlayListModel::PlayListModel(const QString &name, QObject *parent)
SLOT(insert(PlayListItem*, PlayListTrack*)), Qt::QueuedConnection);
connect(m_loader, SIGNAL(finished()), SLOT(preparePlayState()));
connect(m_loader, SIGNAL(finished()), SIGNAL(loaderFinished()));
+ connect(m_task, SIGNAL(finished()), SLOT(onTaskFinished()));
}
PlayListModel::~PlayListModel()
@@ -91,21 +94,21 @@ void PlayListModel::add(PlayListTrack *track)
{
m_container->addTrack(track);
m_total_length += track->length();
+ int flags = 0;
if(m_container->trackCount() == 1)
{
m_current_track = track;
m_current = m_container->indexOf(track);
- emit currentChanged();
+ flags |= CURRENT;
}
else if(m_ui_settings->isGroupsEnabled())
{
//update current index for grouped container only
m_current = m_container->indexOf(m_current_track);
}
- emit trackAdded(track);
- emit listChanged();
- emit countChanged();
+ flags |= STRUCTURE;
+ emit listChanged(flags);
}
void PlayListModel::add(QList<PlayListTrack *> tracks)
@@ -113,13 +116,15 @@ void PlayListModel::add(QList<PlayListTrack *> tracks)
if(tracks.isEmpty())
return;
+ int flags = 0;
+
m_container->addTracks(tracks);
if(m_container->trackCount() == tracks.count())
{
m_current_track = tracks.first();
m_current = m_container->indexOf(m_current_track);
- emit currentChanged();
+ flags |= CURRENT;
}
else if(m_ui_settings->isGroupsEnabled())
{
@@ -133,23 +138,32 @@ void PlayListModel::add(QList<PlayListTrack *> tracks)
emit trackAdded(track);
}
preparePlayState();
- emit listChanged();
- emit countChanged();
+ flags |= STRUCTURE;
+ emit listChanged(flags);
}
void PlayListModel::add(const QString &path)
{
- m_loader->add(path);
- loadPlaylist(path);
+ QStringList paths = PlayListParser::loadPlaylist(path);
+ if(paths.isEmpty())
+ m_loader->add(path);
+ else
+ m_loader->add(paths);
}
void PlayListModel::add(const QStringList &paths)
{
- m_loader->add(paths);
- foreach(QString str, paths)
+ QStringList urls, pl_urls;
+ foreach(QString path, paths)
{
- loadPlaylist(str);
+ pl_urls = PlayListParser::loadPlaylist(path); //is it playlist?
+ if(pl_urls.isEmpty())
+ urls.append(path);
+ else
+ urls.append(pl_urls);
+
}
+ m_loader->add(urls);
}
void PlayListModel::insert(int index, PlayListTrack *track)
@@ -157,11 +171,13 @@ void PlayListModel::insert(int index, PlayListTrack *track)
m_container->insertTrack(index, track);
m_total_length += track->length();
+ int flags = 0;
+
if(m_container->trackCount() == 1)
{
m_current_track = track;
m_current = m_container->indexOf(track);
- emit currentChanged();
+ flags |= CURRENT;
}
else
{
@@ -169,8 +185,8 @@ void PlayListModel::insert(int index, PlayListTrack *track)
m_current = m_container->indexOf(m_current_track);
}
emit trackAdded(track);
- emit listChanged();
- emit countChanged();
+ flags |= STRUCTURE;
+ emit listChanged(flags);
}
void PlayListModel::insert(PlayListItem *before, PlayListTrack *track)
@@ -183,6 +199,8 @@ void PlayListModel::insert(int index, QList<PlayListTrack *> tracks)
if(tracks.isEmpty())
return;
+ int flags = 0;
+
PlayListItem *prevItem = m_container->item(index);
foreach(PlayListTrack *track, tracks)
{
@@ -194,15 +212,15 @@ void PlayListModel::insert(int index, QList<PlayListTrack *> tracks)
{
m_current_track = track;
m_current = m_container->indexOf(track);
- emit currentChanged();
+ flags |= CURRENT;
}
emit trackAdded(track);
}
//update current index
m_current = m_container->indexOf(m_current_track);
preparePlayState();
- emit listChanged();
- emit countChanged();
+ flags |= STRUCTURE;
+ emit listChanged(flags);
}
void PlayListModel::insert(int index, const QString &path)
@@ -304,8 +322,7 @@ bool PlayListModel::setCurrent(int index)
}
m_current = index;
m_current_track = dynamic_cast<PlayListTrack*> (item);
- emit currentChanged();
- emit listChanged();
+ emit listChanged(CURRENT);
return true;
}
@@ -335,12 +352,14 @@ bool PlayListModel::next()
if(m_stop_track == currentTrack())
{
m_stop_track = 0;
- emit listChanged();
+ emit listChanged(STOP_AFTER);
return false;
}
- if (!isEmptyQueue())
+ if (!m_queued_songs.isEmpty())
{
- setCurrentToQueued();
+ m_current_track = m_queued_songs.dequeue();
+ m_current = m_container->indexOf(m_current_track);
+ emit listChanged(CURRENT | QUEUE);
return true;
}
@@ -365,14 +384,13 @@ void PlayListModel::clear()
m_queued_songs.clear();
m_total_length = 0;
m_play_state->resetState();
- emit listChanged();
- emit countChanged();
+ emit listChanged(STRUCTURE | QUEUE | STOP_AFTER | CURRENT | SELECTION);
}
void PlayListModel::clearSelection()
{
m_container->clearSelection();
- emit listChanged();
+ emit listChanged(SELECTION);
}
QList<PlayListItem *> PlayListModel::mid(int pos, int count) const
@@ -411,21 +429,21 @@ PlayListTrack *PlayListModel::findTrack(int number) const
void PlayListModel::setSelected(int index, bool selected)
{
m_container->setSelected(index, selected);
- emit listChanged();
+ emit listChanged(SELECTION);
}
void PlayListModel::setSelected(QList<PlayListTrack *> tracks, bool selected)
{
foreach(PlayListTrack *t, tracks)
t->setSelected(selected);
- emit listChanged();
+ emit listChanged(SELECTION);
}
void PlayListModel::setSelected(QList<PlayListItem *> items, bool selected)
{
foreach(PlayListItem *i, items)
i->setSelected(selected);
- emit listChanged();
+ emit listChanged(SELECTION);
}
void PlayListModel::setSelected(int first, int last, bool selected)
@@ -442,7 +460,7 @@ void PlayListModel::setSelected(int first, int last, bool selected)
continue;
i->setSelected(selected);
}
- emit listChanged();
+ emit listChanged(SELECTION);
}
void PlayListModel::removeSelected()
@@ -457,55 +475,9 @@ void PlayListModel::removeUnselected()
void PlayListModel::removeTrack (int i)
{
- bool current_changed = false;
- if ((i < count()) && (i >= 0))
- {
- PlayListTrack* track = m_container->track(i);
- if(!track)
- return;
- m_queued_songs.removeAll(track);
- m_container->removeTrack(track);
- if(m_stop_track == track)
- m_stop_track = 0;
- m_total_length -= track->length();
- m_total_length = qMax(0, m_total_length);
-
- if(m_current_track == track)
- {
- if(m_container->isEmpty())
- m_current_track = 0;
- else
- {
- current_changed = true;
- int current = qMin(i - 1, m_container->count() - 1);
- current = qMax(current, 0);
- m_current_track = m_container->track(current);
- if(!m_current_track)
- {
- m_current_track = current > 0 ? m_container->track(current-1) :
- m_container->track(1);
- }
- }
- }
-
- if (track->flag() == PlayListTrack::FREE)
- {
- delete track;
- track = NULL;
- }
- else if (track->flag() == PlayListTrack::EDITING)
- track->setFlag(PlayListTrack::SCHEDULED_FOR_DELETION);
-
-
- m_current = m_current_track ? m_container->indexOf(m_current_track) : -1;
- m_play_state->prepare();
-
- if(current_changed)
- emit currentChanged();
-
- emit listChanged();
- emit countChanged();
- }
+ int flags = removeTrackInternal(i);
+ if(flags)
+ emit listChanged(flags);
}
void PlayListModel::removeTrack (PlayListItem *track)
@@ -518,16 +490,14 @@ void PlayListModel::removeSelection(bool inverted)
{
int i = 0;
int select_after_delete = -1;
- PlayListTrack *prev_current_track = m_current_track;
+ int flags = 0;
while (!m_container->isEmpty() && i < m_container->count())
{
PlayListItem *item = m_container->item(i);
if (!item->isGroup() && item->isSelected() ^ inverted)
{
- blockSignals(true);
- removeTrack(i);
- blockSignals(false);
+ flags |= removeTrackInternal(i);
if(m_container->isEmpty())
continue;
@@ -538,33 +508,83 @@ void PlayListModel::removeSelection(bool inverted)
i++;
}
- if (select_after_delete >= m_container->count())
- select_after_delete = m_container->count() - 1;
+ select_after_delete = qMin(select_after_delete, m_container->count() - 1);
- if(select_after_delete != -1)
+ if(select_after_delete >= 0)
+ {
m_container->setSelected(select_after_delete, true);
+ flags |= SELECTION;
+ }
m_play_state->prepare();
- if(prev_current_track != m_current_track)
- emit currentChanged();
+ if(flags)
+ emit listChanged(flags);
+}
- emit listChanged();
- emit countChanged();
+int PlayListModel::removeTrackInternal(int i)
+{
+ if((i < 0) || (i >= count()))
+ return 0;
+
+ int flags = 0;
+ PlayListTrack* track = m_container->track(i);
+ if(!track)
+ return flags;
+ if(m_queued_songs.removeAll(track) > 0)
+ flags |= QUEUE;
+ m_container->removeTrack(track);
+ if(m_stop_track == track)
+ {
+ flags |= STOP_AFTER;
+ m_stop_track = 0;
+ }
+ if(track->isSelected())
+ flags |= SELECTION;
+
+ m_total_length -= track->length();
+ m_total_length = qMax(0, m_total_length);
+
+ if(m_current_track == track)
+ {
+ flags |= CURRENT;
+ if(m_container->isEmpty())
+ m_current_track = 0;
+ else
+ {
+ m_current = i > 0 ? qMin(i - 1, m_container->count() - 1) : 0;
+ if(!(m_current_track = m_container->track(m_current)))
+ {
+ m_current_track = m_current > 0 ? m_container->track(m_current - 1) :
+ m_container->track(1);
+ }
+ }
+ }
+
+ if (track->isUsed())
+ track->deleteLater();
+ else
+ delete track;
+
+ m_current = m_current_track ? m_container->indexOf(m_current_track) : -1;
+ m_play_state->prepare();
+
+ flags |= STRUCTURE;
+ return flags;
}
void PlayListModel::invertSelection()
{
for (int i = 0; i < m_container->count(); ++i)
m_container->setSelected(i, !m_container->isSelected(i));
- emit listChanged();
+ emit listChanged(SELECTION);
}
void PlayListModel::selectAll()
{
for (int i = 0; i < m_container->count(); ++i)
m_container->setSelected(i, true);
- emit listChanged();
+ emit listChanged(SELECTION);
}
void PlayListModel::showDetails(QWidget *parent)
@@ -576,9 +596,8 @@ void PlayListModel::showDetails(QWidget *parent)
if(!m_container->isSelected(i))
continue;
PlayListTrack *track = m_container->track(i);
- if(!track || track->flag() != PlayListTrack::FREE)
- continue;
- selected_tracks.append(track);
+ if(track)
+ selected_tracks.append(track);
}
if(!selected_tracks.isEmpty())
@@ -640,7 +659,7 @@ void PlayListModel::moveItems(int from, int to)
if(m_container->move(selected_indexes, from, to))
{
m_current = m_container->indexOf(m_current_track);
- emit listChanged();
+ emit listChanged(STRUCTURE);
}
}
@@ -714,9 +733,11 @@ QList<PlayListItem *> PlayListModel::items() const
void PlayListModel::addToQueue()
{
QList<PlayListTrack*> selected_tracks = selectedTracks();
+ blockSignals(true);
foreach(PlayListTrack* track, selected_tracks)
setQueued(track);
- emit listChanged();
+ blockSignals(false);
+ emit listChanged(QUEUE);
}
void PlayListModel::setQueued(PlayListTrack *item)
@@ -725,7 +746,7 @@ void PlayListModel::setQueued(PlayListTrack *item)
m_queued_songs.removeAll(item);
else
m_queued_songs.enqueue(item);
- emit listChanged();
+ emit listChanged(QUEUE);
}
bool PlayListModel::isQueued(PlayListTrack *f) const
@@ -733,11 +754,6 @@ bool PlayListModel::isQueued(PlayListTrack *f) const
return m_queued_songs.contains(f);
}
-void PlayListModel::setCurrentToQueued()
-{
- setCurrent(indexOf(m_queued_songs.dequeue()));
-}
-
bool PlayListModel::isEmptyQueue() const
{
return m_queued_songs.isEmpty();
@@ -764,7 +780,7 @@ void PlayListModel::randomizeList()
return;
m_container->randomizeList();
m_current = m_container->indexOf(m_current_track);
- emit listChanged();
+ emit listChanged(STRUCTURE);
}
void PlayListModel::reverseList()
@@ -773,25 +789,23 @@ void PlayListModel::reverseList()
return;
m_container->reverseList();
m_current = m_container->indexOf(m_current_track);
- emit listChanged();
+ emit listChanged(STRUCTURE);
}
void PlayListModel::sortSelection(int mode)
{
if(m_container->isEmpty())
return;
- m_container->sortSelection(mode);
- m_current = m_container->indexOf(m_current_track);
- emit listChanged();
+
+ m_task->sortSelection(m_container->tracks(), (PlayListModel::SortMode) mode);
}
void PlayListModel::sort(int mode)
{
if(m_container->isEmpty())
return;
- m_container->sort(mode);
- m_current = m_container->indexOf(m_current_track);
- emit listChanged();
+
+ m_task->sort(m_container->tracks(), (PlayListModel::SortMode) mode);
}
void PlayListModel::prepareForShufflePlaying(bool val)
@@ -817,13 +831,60 @@ void PlayListModel::prepareGroups(bool enabled)
m_container = container;
if(!m_container->isEmpty())
m_current = m_container->indexOf(m_current_track);
- emit listChanged();
+ emit listChanged(STRUCTURE);
+}
+
+void PlayListModel::onTaskFinished()
+{
+ if(m_task->isChanged(m_container)) //update unchanged container only
+ return;
+
+ if(m_task->type() == PlayListTask::SORT || m_task->type() == PlayListTask::SORT_SELECTION)
+ {
+ m_container->replaceTracks(m_task->takeResults(&m_current_track));
+ m_current = m_container->indexOf(m_current_track);
+ emit listChanged(STRUCTURE);
+ }
+ else if(m_task->type() == PlayListTask::REMOVE_INVALID
+ || m_task->type() == PlayListTask::REMOVE_DUPLICATES)
+ {
+ PlayListTrack *prev_current_track = m_current_track;
+ bool prev_count = m_container->count();
+
+ m_container->replaceTracks(m_task->takeResults(&m_current_track));
+
+ if(prev_count != m_container->count())
+ {
+ int flags = STRUCTURE;
+ m_current = m_container->indexOf(m_current_track);
+ if(prev_current_track != m_current_track)
+ flags |= CURRENT;
+
+ if(m_stop_track && !m_container->contains(m_stop_track))
+ {
+ m_stop_track = 0;
+ flags |= STOP_AFTER;
+ }
+
+ foreach (PlayListTrack *t, m_queued_songs)
+ {
+ if(!m_container->contains(t))
+ {
+ flags |= QUEUE;
+ m_queued_songs.removeAll(t);
+ }
+ }
+
+ emit listChanged(flags);
+ }
+ }
}
void PlayListModel::doCurrentVisibleRequest()
{
- emit currentChanged();
- emit listChanged();
+ //TODO check these signals
+ //emit currentChanged();
+ //emit listChanged();
}
void PlayListModel::loadPlaylist(const QString &f_name)
@@ -855,70 +916,25 @@ void PlayListModel::preparePlayState()
void PlayListModel::removeInvalidTracks()
{
- bool ok = false;
-
- for(int i = m_container->count() - 1; i >= 0; i--)
- {
- if(i >= m_container->count() || !isTrack(i))
- continue;
-
- PlayListTrack *track = m_container->track(i);
-
- if(track->url().contains("://"))
- ok = MetaDataManager::instance()->protocols().contains(track->url().section("://",0,0));
- else
- ok = MetaDataManager::instance()->supports(track->url());
- if(!ok)
- removeTrack(i);
-
- }
+ m_task->removeInvalidTracks(m_container->tracks(), m_current_track);
}
void PlayListModel::removeDuplicates()
{
- QStringList urls;
- bool modified = false;
- PlayListTrack *prev_current = m_current_track;
-
- for(int i = 0; i < m_container->count(); ++i)
- {
- if(!isTrack(i))
- continue;
-
- if(urls.contains(track(i)->url()))
- {
- blockSignals(true);
- removeTrack(i);
- blockSignals(false);
- modified = true;
- i--;
- }
- else
- {
- urls.append(track(i)->url());
- }
- }
-
- if(modified)
- {
- if(m_current_track != prev_current)
- emit currentChanged();
-
- emit listChanged();
- emit countChanged();
- }
+ m_task->removeDuplicates(m_container->tracks(), m_current_track);
}
void PlayListModel::clearQueue()
{
m_queued_songs.clear();
m_stop_track = 0;
- emit listChanged();
+ emit listChanged(QUEUE);
}
void PlayListModel::stopAfterSelected()
{
QList<PlayListTrack*> selected_tracks = selectedTracks();
+ int flags = STOP_AFTER;
if(!m_queued_songs.isEmpty())
{
m_stop_track = m_stop_track != m_queued_songs.last() ? m_queued_songs.last() : 0;
@@ -929,15 +945,18 @@ void PlayListModel::stopAfterSelected()
}
else if(selected_tracks.count() > 1)
{
+ blockSignals(true);
addToQueue();
+ blockSignals(false);
+ flags |= QUEUE;
m_stop_track = m_queued_songs.last();
}
else
return;
- emit listChanged();
+ emit listChanged(flags);
}
-void PlayListModel::updateGroups()
+void PlayListModel::rebuildGroups()
{
if(m_ui_settings->isGroupsEnabled())
prepareGroups(true);
diff --git a/src/qmmpui/playlistmodel.h b/src/qmmpui/playlistmodel.h
index 06333fb61..a4f411f34 100644
--- a/src/qmmpui/playlistmodel.h
+++ b/src/qmmpui/playlistmodel.h
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2006-2014 by Ilya Kotov *
+ * Copyright (C) 2006-2015 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -37,6 +37,7 @@ class PlayListFormat;
class PlayListModel;
class PlayListContainer;
class QmmpUiSettings;
+class PlayListTask;
/*! @brief Helper class that keeps track of a view's selected items.
*
@@ -214,10 +215,6 @@ public:
*/
bool isQueued(PlayListTrack* item) const;
/*!
- * Sets current song to the file that is nex in queue, if queue is empty - does nothing
- */
- void setCurrentToQueued();
- /*!
* Returns \b true if play queue is empty,otherwise returns - \b false.
*/
bool isEmptyQueue()const;
@@ -304,15 +301,21 @@ public:
PlayListTrack *findTrack(int number) const;
+
+ enum UpdateFlags
+ {
+ STRUCTURE = 0x01, //added/removed/moved
+ SELECTION = 0x02,
+ QUEUE = 0x04,
+ CURRENT = 0x08,
+ STOP_AFTER = 0x10
+ };
+
signals:
/*!
* Emitted when the state of PlayListModel has changed.
*/
- void listChanged();
- /*!
- * Emitted when current item has changed.
- */
- void currentChanged();
+ void listChanged(int flags);
/*!
* Emitted when new track has added.
* @param track Pointer of the new playlist track.
@@ -327,10 +330,6 @@ signals:
* Emitted when playlist loader thread has finished.
*/
void loaderFinished();
- /*!
- * Emitted when playlist items are added or removed.
- */
- void countChanged();
public slots:
/*!
@@ -466,7 +465,7 @@ public slots:
/*!
* Rebuilds groups
*/
- void updateGroups();
+ void rebuildGroups();
private:
/*!
@@ -483,6 +482,8 @@ private:
*/
void removeSelection(bool inverted = false);
+ int removeTrackInternal(int i);
+
private slots:
/*!
* Prepares play state object
@@ -498,6 +499,8 @@ private slots:
*/
void prepareGroups(bool enabled);
+ void onTaskFinished();
+
private:
PlayListTrack* m_current_track;
PlayListTrack* m_stop_track;
@@ -510,6 +513,7 @@ private:
QString m_name;
PlayListContainer *m_container;
QmmpUiSettings *m_ui_settings;
+ PlayListTask *m_task;
};
#endif
diff --git a/src/qmmpui/playlisttask.cpp b/src/qmmpui/playlisttask.cpp
index fc23618e5..f1859135e 100644
--- a/src/qmmpui/playlisttask.cpp
+++ b/src/qmmpui/playlisttask.cpp
@@ -18,14 +18,381 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
+#include <QFileInfo>
+#include <QDateTime>
+#include <QTime>
+#include <qmmp/metadatamanager.h>
+#include "qmmpuisettings.h"
+#include "playlisttrack.h"
#include "playlisttask_p.h"
-PlayListTask::PlayListTask(QObject *parent) :
- QRunnable(parent)
+struct TrackField
{
+ PlayListTrack *track;
+ QString value;
+ QString groupName;
+};
+
+struct GroupdField
+{
+ QList <TrackField *> fields;
+ QString groupName;
+};
+
+////===============THE BEGINNING OF SORT IMPLEMENTATION =======================////
+
+// First we'll implement bundle of static compare procedures
+// to sort items in different ways
+
+//by string
+static bool _stringLessComparator(TrackField* s1, TrackField* s2)
+{
+ return QString::localeAwareCompare (s1->value, s2->value) < 0;
+}
+
+static bool _stringGreaterComparator(TrackField* s1, TrackField* s2)
+{
+ return QString::localeAwareCompare (s1->value, s2->value) > 0;
+}
+//by number
+static bool _numberLessComparator(TrackField* s1, TrackField* s2)
+{
+ return s1->value.toInt() < s2->value.toInt();
+}
+
+static bool _numberGreaterComparator(TrackField* s1, TrackField* s2)
+{
+ return s1->value.toInt() > s2->value.toInt();
+}
+//by file creation date
+static bool _fileCreationDateLessComparator(TrackField* s1, TrackField* s2)
+{
+ return QFileInfo(s1->value).created() < QFileInfo(s2->value).created();
+}
+
+static bool _fileCreationDateGreaterComparator(TrackField* s1, TrackField* s2)
+{
+ return QFileInfo(s1->value).created() > QFileInfo(s2->value).created();
+}
+//by file modification date
+static bool _fileModificationDateLessComparator(TrackField* s1, TrackField* s2)
+{
+ return QFileInfo(s1->value).lastModified() < QFileInfo(s2->value).lastModified();
+}
+
+static bool _fileModificationDateGreaterComparator(TrackField* s1, TrackField* s2)
+{
+ return QFileInfo(s1->value).lastModified() > QFileInfo(s2->value).lastModified();
+}
+//by file name
+static bool _filenameLessComparator(TrackField* s1, TrackField* s2)
+{
+ QFileInfo i_s1(s1->value);
+ QFileInfo i_s2(s2->value);
+ return QString::localeAwareCompare (i_s1.baseName(), i_s2.baseName()) < 0;
+}
+
+static bool _filenameGreaterComparator(TrackField* s1, TrackField* s2)
+{
+ QFileInfo i_s1(s1->value);
+ QFileInfo i_s2(s2->value);
+ return QString::localeAwareCompare (i_s1.baseName(), i_s2.baseName()) > 0;
+}
+////=============== THE END OF SORT IMPLEMENTATION =======================////
+
+PlayListTask::PlayListTask(QObject *parent) : QThread(parent)
+{
+ m_reverted = true;
+ m_align_groups = false;
+ m_current_track = 0;
+ m_task = EMPTY;
+
+ m_sort_keys.insert(PlayListModel::TITLE, Qmmp::TITLE);
+ m_sort_keys.insert(PlayListModel::DISCNUMBER, Qmmp::DISCNUMBER);
+ m_sort_keys.insert(PlayListModel::ALBUM, Qmmp::ALBUM);
+ m_sort_keys.insert(PlayListModel::ARTIST, Qmmp::ARTIST);
+ m_sort_keys.insert(PlayListModel::ALBUMARTIST, Qmmp::ALBUMARTIST);
+ m_sort_keys.insert(PlayListModel::FILENAME, Qmmp::URL);
+ m_sort_keys.insert(PlayListModel::PATH_AND_FILENAME, Qmmp::URL);
+ m_sort_keys.insert(PlayListModel::DATE, Qmmp::YEAR);
+ m_sort_keys.insert(PlayListModel::TRACK, Qmmp::TRACK);
+ m_sort_keys.insert(PlayListModel::FILE_CREATION_DATE, Qmmp::URL);
+ m_sort_keys.insert(PlayListModel::FILE_MODIFICATION_DATE, Qmmp::URL);
+}
+
+PlayListTask::~PlayListTask()
+{}
+
+void PlayListTask::sort(QList<PlayListTrack *> tracks, int mode)
+{
+ if(isRunning())
+ return;
+ clear();
+ m_reverted = !m_reverted;
+ m_sort_mode = mode;
+ m_task = SORT;
+ m_input_tracks = tracks;
+ Qmmp::MetaData key = m_sort_keys.value(mode);
+
+ m_align_groups = QmmpUiSettings::instance()->isGroupsEnabled() && (mode != PlayListModel::GROUP);
+
+ foreach (PlayListTrack *t, tracks)
+ {
+ TrackField *f = new TrackField;
+ f->track = t;
+ f->value = (mode == PlayListModel::GROUP) ? t->groupName() : t->value(key);
+ if(m_align_groups)
+ f->groupName = t->groupName();
+ m_fields.append(f);
+ }
+
+ start();
+}
+
+void PlayListTask::sortSelection(QList<PlayListTrack *> tracks, int mode)
+{
+ if(isRunning())
+ return;
+ clear();
+ m_reverted = !m_reverted;
+ m_sort_mode = mode;
+ m_task = SORT_SELECTION;
+ m_tracks = tracks;
+ m_input_tracks = tracks;
+ Qmmp::MetaData key = m_sort_keys.value(mode);
+
+ for(int i = 0; i < tracks.count(); ++i)
+ {
+ if(!tracks[i]->isSelected())
+ continue;
+
+ TrackField *f = new TrackField;
+ f->track = tracks[i];
+ f->value = (mode == PlayListModel::GROUP) ? f->track->groupName() : f->track->value(key);
+ m_fields.append(f);
+ m_indexes.append(i);
+ }
+
+ start();
+}
+
+void PlayListTask::removeInvalidTracks(QList<PlayListTrack *> tracks, PlayListTrack *current_track)
+{
+ if(isRunning())
+ return;
+ clear();
+ m_task = REMOVE_INVALID;
+ m_input_tracks = tracks;
+ m_tracks = tracks;
+ m_current_track = current_track;
+
+ for(int i = 0; i < tracks.count(); ++i)
+ {
+ TrackField *f = new TrackField;
+ f->track = tracks[i];
+ f->value = f->track->value(Qmmp::URL);
+ m_fields.append(f);
+ }
+ MetaDataManager::instance()->prepareForAnotherThread();
+ start();
+}
+
+void PlayListTask::removeDuplicates(QList<PlayListTrack *> tracks, PlayListTrack *current_track)
+{
+ if(isRunning())
+ return;
+ clear();
+ m_task = REMOVE_DUPLICATES;
+ m_input_tracks = tracks;
+ m_tracks = tracks;
+ m_current_track = current_track;
+
+ for(int i = 0; i < tracks.count(); ++i)
+ {
+ TrackField *f = new TrackField;
+ f->track = tracks[i];
+ f->value = f->track->value(Qmmp::URL);
+ m_fields.append(f);
+ }
+ MetaDataManager::instance()->prepareForAnotherThread();
+ start();
}
void PlayListTask::run()
{
+ qDebug("PlayListTask: started");
+
+ if(m_task == SORT || m_task == SORT_SELECTION)
+ {
+ bool(*compareLessFunc)(TrackField*, TrackField*) = 0;
+ bool(*compareGreaterFunc)(TrackField*, TrackField*) = 0;
+
+ QList<TrackField*>::iterator begin = m_fields.begin();
+ QList<TrackField*>::iterator end = m_fields.end();
+
+ if(m_sort_mode == PlayListModel::FILE_CREATION_DATE)
+ {
+ compareLessFunc = _fileCreationDateLessComparator;
+ compareGreaterFunc = _fileCreationDateGreaterComparator;
+ }
+ else if(m_sort_mode == PlayListModel::FILE_MODIFICATION_DATE)
+ {
+ compareLessFunc = _fileModificationDateLessComparator;
+ compareGreaterFunc = _fileModificationDateGreaterComparator;
+ }
+ else if(m_sort_mode == PlayListModel::TRACK || m_sort_mode == PlayListModel::DATE)
+ {
+ compareLessFunc = _numberLessComparator;
+ compareGreaterFunc = _numberGreaterComparator;
+ }
+ else if(m_sort_mode == PlayListModel::FILENAME)
+ {
+ compareLessFunc = _filenameLessComparator;
+ compareGreaterFunc = _filenameGreaterComparator;
+ }
+ else
+ {
+ compareLessFunc = _stringLessComparator;
+ compareGreaterFunc = _stringGreaterComparator;
+ }
+
+ if(m_reverted)
+ qStableSort(begin,end,compareGreaterFunc);
+ else
+ qStableSort(begin,end,compareLessFunc);
+
+ //align track list by group name (optimization)
+ if(m_align_groups)
+ {
+ QList<GroupdField *> groups;
+ bool found = false;
+ for(int i = 0; i < m_fields.count(); ++i)
+ {
+ found = false;
+ for(int j = groups.count() - 1; j >= 0; j--)
+ {
+ if(groups[j]->groupName == m_fields[i]->groupName)
+ {
+ groups[j]->fields.append(m_fields[i]);
+ found = true;
+ break;
+ }
+ }
+
+ if(!found)
+ {
+ groups << new GroupdField;
+ groups.last()->fields.append(m_fields[i]);
+ groups.last()->groupName = m_fields[i]->groupName;
+ }
+ }
+
+ m_fields.clear();
+ for(int j = 0; j < groups.count(); ++j)
+ {
+ m_fields.append(groups[j]->fields);
+ }
+ qDeleteAll(groups);
+ groups.clear();
+ }
+ }
+ else if(m_task == REMOVE_INVALID)
+ {
+ TrackField *f = 0;
+ bool ok = false;
+ for(int i = 0; i < m_fields.count(); ++i)
+ {
+ f = m_fields.at(i);
+
+ if(f->value.contains("://"))
+ ok = MetaDataManager::instance()->protocols().contains(f->value.section("://",0,0)); //url
+ else
+ ok = MetaDataManager::instance()->supports(f->value); //local file
+
+ if(!ok)
+ m_indexes << i;
+ }
+ }
+ else if(m_task == REMOVE_DUPLICATES)
+ {
+ QStringList urls;
+ TrackField *f = 0;
+ for(int i = 0; i < m_fields.count(); ++i)
+ {
+ f = m_fields.at(i);
+
+ if(urls.contains(f->value))
+ {
+ m_indexes.append(i);
+ }
+ else
+ {
+ urls.append(f->value);
+ }
+ }
+ }
+ qDebug("PlayListTask: finished");
+}
+
+PlayListTask::TaskType PlayListTask::type() const
+{
+ return m_task;
+}
+
+bool PlayListTask::isChanged(PlayListContainer *container)
+{
+ if(m_input_tracks.count() != container->trackCount())
+ return true;
+
+ return m_input_tracks != container->tracks();
+}
+QList<PlayListTrack *> PlayListTask::takeResults(PlayListTrack **current_track)
+{
+ if(m_task == SORT)
+ {
+ foreach (TrackField *f, m_fields)
+ m_tracks.append(f->track);
+ }
+ else if(m_task == SORT_SELECTION)
+ {
+ for (int i = 0; i < m_indexes.count(); i++)
+ m_tracks.replace(m_indexes[i], m_fields[i]->track);
+ }
+ else if(m_task == REMOVE_INVALID || m_task == REMOVE_DUPLICATES)
+ {
+ int index = 0;
+ PlayListTrack *t = 0;
+ for (int i = m_indexes.count() - 1; i >= 0; i--)
+ {
+ index = m_indexes.at(i);
+ t = m_tracks.takeAt(index);
+ if(t == m_current_track)
+ {
+ if(m_tracks.isEmpty())
+ m_current_track = 0;
+ else if(index > 0 && index <= m_tracks.count())
+ m_current_track = m_tracks[index - 1];
+ else
+ m_current_track = m_tracks[0];
+ *current_track = m_current_track;
+ }
+ if(t->isUsed())
+ t->deleteLater();
+ else
+ delete t;
+ }
+ }
+ return m_tracks;
+}
+
+void PlayListTask::clear()
+{
+ qDeleteAll(m_fields);
+ m_fields.clear();
+ m_align_groups = false;
+ m_indexes.clear();
+ m_input_tracks.clear();
+ m_tracks.clear();
+ m_current_track = 0;
}
diff --git a/src/qmmpui/playlisttask_p.h b/src/qmmpui/playlisttask_p.h
index 39159cfdf..14442b06b 100644
--- a/src/qmmpui/playlisttask_p.h
+++ b/src/qmmpui/playlisttask_p.h
@@ -21,16 +21,60 @@
#ifndef PLAYLISTTASK_P_H
#define PLAYLISTTASK_P_H
-#include <QRunnable>
+#include <QThread>
#include <QObject>
+#include <QHash>
+#include <QList>
+#include "playlistmodel.h"
+#include "playlistcontainer_p.h"
-class PlayListTask : public QRunnable, public QObject
+class PlayListTrack;
+struct TrackField;
+
+
+class PlayListTask : public QThread
{
Q_OBJECT
public:
- explicit PlayListTask(QObject *parent = 0);
-void run();
+ enum TaskType
+ {
+ EMPTY = -1,
+ SORT = 0,
+ SORT_SELECTION,
+ REMOVE_INVALID,
+ REMOVE_DUPLICATES
+ };
+ explicit PlayListTask(QObject *parent);
+
+ ~PlayListTask();
+
+ void sort(QList<PlayListTrack *> tracks, int mode);
+ void sortSelection(QList<PlayListTrack *> tracks, int mode);
+ void removeInvalidTracks(QList<PlayListTrack *> tracks, PlayListTrack *current_track);
+ void removeDuplicates(QList<PlayListTrack *> tracks, PlayListTrack *current_track);
+
+ void run();
+
+ TaskType type() const;
+ bool isChanged(PlayListContainer *container);
+ QList<PlayListTrack *> takeResults(PlayListTrack **current_track);
+ PlayListTrack *currentTrack() const;
+
+
+
+private:
+ void clear();
+ QList <TrackField *> m_fields;
+ QList <PlayListTrack *> m_tracks;
+ QList <PlayListTrack *> m_input_tracks;
+ QList<int> m_indexes;
+ PlayListTrack *m_current_track;
+ int m_sort_mode;
+ TaskType m_task;
+ bool m_reverted;
+ bool m_align_groups;
+ QHash<int, Qmmp::MetaData> m_sort_keys;
};
diff --git a/src/qmmpui/playlisttrack.cpp b/src/qmmpui/playlisttrack.cpp
index 32a918ffd..e1bee339d 100644
--- a/src/qmmpui/playlisttrack.cpp
+++ b/src/qmmpui/playlisttrack.cpp
@@ -23,37 +23,46 @@
#include "qmmpuisettings.h"
#include "playlisttrack.h"
-PlayListTrack::PlayListTrack() : QMap<Qmmp::MetaData, QString>(), PlayListItem(), m_flag(FREE)
+PlayListTrack::PlayListTrack() : QMap<Qmmp::MetaData, QString>(), PlayListItem()
{
m_settings = QmmpUiSettings::instance();
m_length = 0;
+ m_refCount = 0;
+ m_sheduledForDeletion = false;
}
PlayListTrack::PlayListTrack(const PlayListTrack &other) : QMap<Qmmp::MetaData, QString>(other),
- PlayListItem(),m_flag(FREE)
+ PlayListItem()
{
m_settings = QmmpUiSettings::instance();
+ m_refCount = 0;
+ m_sheduledForDeletion = false;
+
m_formattedTitle = other.m_formattedTitle;
m_group = other.m_group;
m_formattedLength = other.m_formattedLength;
m_titleFormat = other.m_titleFormat;
m_groupFormat = other.m_groupFormat;
setSelected(other.isSelected());
- setFlag(other.flag());
m_length = other.m_length;
m_formattedLength = other.m_formattedLength;
}
PlayListTrack::PlayListTrack(FileInfo *info) : QMap<Qmmp::MetaData, QString>(info->metaData()),
- PlayListItem(), m_flag(FREE)
+ PlayListItem()
{
m_settings = QmmpUiSettings::instance();
setLength(m_length = info->length());
insert(Qmmp::URL, info->path());
+ m_refCount = 0;
+ m_sheduledForDeletion = false;
}
PlayListTrack::~PlayListTrack()
-{}
+{
+ if(m_refCount != 0)
+ qWarning("PlayListTrack: deleting busy track");
+}
void PlayListTrack::updateMetaData(const QMap <Qmmp::MetaData, QString> &metaData)
{
@@ -92,6 +101,31 @@ bool PlayListTrack::isGroup() const
return false;
}
+void PlayListTrack::beginUsage()
+{
+ m_refCount++;
+}
+
+void PlayListTrack::endUsage()
+{
+ m_refCount--;
+}
+
+void PlayListTrack::deleteLater()
+{
+ m_sheduledForDeletion = true;
+}
+
+bool PlayListTrack::isSheduledForDeletion() const
+{
+ return m_sheduledForDeletion;
+}
+
+bool PlayListTrack::isUsed() const
+{
+ return (m_refCount != 0);
+}
+
const QString PlayListTrack::formattedTitle()
{
if(m_formattedTitle.isEmpty() || m_titleFormat != m_settings->titleFormat())
@@ -130,16 +164,6 @@ const QString PlayListTrack::url() const
return value(Qmmp::URL);
}
-void PlayListTrack::setFlag(FLAGS f)
-{
- m_flag = f;
-}
-
-PlayListTrack::FLAGS PlayListTrack::flag() const
-{
- return m_flag;
-}
-
void PlayListTrack::formatTitle()
{
MetaDataFormatter f(m_settings->titleFormat());
diff --git a/src/qmmpui/playlisttrack.h b/src/qmmpui/playlisttrack.h
index e21b8f286..810be411a 100644
--- a/src/qmmpui/playlisttrack.h
+++ b/src/qmmpui/playlisttrack.h
@@ -34,19 +34,6 @@ class PlayListTrack : public QMap <Qmmp::MetaData, QString>, public PlayListItem
{
public:
/*!
- * Current state of playlist item.
- * FREE - instance is free and may be deleted
- * EDITING - instance is currently busy in some kind of operation(tags editing etc.)
- * and can't be deleted at the moment. Set flag SCHEDULED_FOR_DELETION for it
- * instead of delete operator call.
- */
- enum FLAGS
- {
- FREE = 0, /*!< instance is free and may be deleted */
- EDITING, /*!< instance is currently busy */
- SCHEDULED_FOR_DELETION /*!< instance is sheduled for deletion */
- };
- /*!
* Constructs an empty plalist item.
*/
PlayListTrack();
@@ -100,14 +87,19 @@ public:
* Returns \b false.
*/
bool isGroup() const;
+
+
+ void beginUsage();
+ void endUsage();
+ void deleteLater();
+
+
+ bool isSheduledForDeletion() const;
/*!
- * Returns current state of the playlist item.
- */
- FLAGS flag() const;
- /*!
- * Sets state of the playlist item.
+ * Indicates that instance is currently busy in some kind of operation (tags editing etc.)
+ * and can't be deleted at the moment. Call \b deleteLater() instead of delete operator call.
*/
- void setFlag(FLAGS);
+ bool isUsed() const;
private:
void formatTitle();
@@ -119,7 +111,8 @@ private:
QString m_groupFormat;
QmmpUiSettings *m_settings;
qint64 m_length;
- FLAGS m_flag;
+ int m_refCount;
+ bool m_sheduledForDeletion;
};
#endif
diff --git a/src/qmmpui/qmmpuisettings.cpp b/src/qmmpui/qmmpuisettings.cpp
index 37b56ec2c..67e5c0559 100644
--- a/src/qmmpui/qmmpuisettings.cpp
+++ b/src/qmmpui/qmmpuisettings.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2012-2014 by Ilya Kotov *
+ * Copyright (C) 2012-2015 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -146,7 +146,7 @@ void QmmpUiSettings::setGroupFormat(const QString &groupFormat)
m_group_format = groupFormat;
foreach(PlayListModel *model, PlayListManager::instance()->playLists())
{
- model->updateGroups();
+ model->rebuildGroups();
}
}
}
diff --git a/src/qmmpui/qmmpuisettings.h b/src/qmmpui/qmmpuisettings.h
index b51f778a5..f9d6fd99b 100644
--- a/src/qmmpui/qmmpuisettings.h
+++ b/src/qmmpui/qmmpuisettings.h
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2012 by Ilya Kotov *
+ * Copyright (C) 2012-2015 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
diff --git a/src/qmmpui/tagupdater.cpp b/src/qmmpui/tagupdater.cpp
index 02f0c4590..21bc6aaf9 100644
--- a/src/qmmpui/tagupdater.cpp
+++ b/src/qmmpui/tagupdater.cpp
@@ -24,7 +24,7 @@ TagUpdater::TagUpdater(QObject* o, QList<PlayListTrack *> tracks) : m_observable
{
m_tracks = tracks;
foreach(PlayListTrack *t, m_tracks)
- t->setFlag(PlayListTrack::EDITING);
+ t->beginUsage();
connect(m_observable, SIGNAL(destroyed(QObject *)),SLOT(updateTags()));
connect(m_observable, SIGNAL(destroyed(QObject *)),SLOT(deleteLater()));
}
@@ -33,7 +33,8 @@ void TagUpdater::updateTags()
{
foreach (PlayListTrack *t, m_tracks)
{
- if (t->flag() == PlayListTrack::SCHEDULED_FOR_DELETION)
+ t->endUsage();
+ if (!t->isUsed() && t->isSheduledForDeletion())
{
delete t;
t = 0;
@@ -41,7 +42,6 @@ void TagUpdater::updateTags()
else
{
t->updateMetaData();
- t->setFlag(PlayListTrack::FREE);
}
}
m_tracks.clear();