make use of std::locale based strings comparison
This commit is contained in:
@@ -71,8 +71,41 @@ void DisplayAlbums(NC::Menu<SearchConstraints> &menu);
|
|||||||
void DisplayPrimaryTags(NC::Menu<std::string> &menu);
|
void DisplayPrimaryTags(NC::Menu<std::string> &menu);
|
||||||
|
|
||||||
bool SortSongsByTrack(const MPD::Song &a, const MPD::Song &b);
|
bool SortSongsByTrack(const MPD::Song &a, const MPD::Song &b);
|
||||||
bool SortAllTracks(const MPD::Song &a, const MPD::Song &b);
|
|
||||||
bool SortSearchConstraints(const SearchConstraints &a, const SearchConstraints &b);
|
struct SortAllTracks {
|
||||||
|
const std::array<MPD::Song::GetFunction, 3> m_gets;
|
||||||
|
LocaleStringComparison m_cmp;
|
||||||
|
public:
|
||||||
|
SortAllTracks() : m_gets({{
|
||||||
|
&MPD::Song::getDate,
|
||||||
|
&MPD::Song::getAlbum,
|
||||||
|
&MPD::Song::getDisc
|
||||||
|
}}), m_cmp(std::locale(""), Config.ignore_leading_the) { }
|
||||||
|
bool operator()(const MPD::Song &a, const MPD::Song &b) {
|
||||||
|
for (auto get = m_gets.begin(); get != m_gets.end(); ++get) {
|
||||||
|
int ret = m_cmp(a.getTags(*get), b.getTags(*get));
|
||||||
|
if (ret != 0)
|
||||||
|
return ret < 0;
|
||||||
|
}
|
||||||
|
return a.getTrack() < b.getTrack();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SortSearchConstraints {
|
||||||
|
LocaleStringComparison m_cmp;
|
||||||
|
public:
|
||||||
|
SortSearchConstraints() : m_cmp(std::locale(""), Config.ignore_leading_the) { }
|
||||||
|
bool operator()(const SearchConstraints &a, const SearchConstraints &b) const {
|
||||||
|
int result;
|
||||||
|
result = m_cmp(a.PrimaryTag, b.PrimaryTag);
|
||||||
|
if (result != 0)
|
||||||
|
return result < 0;
|
||||||
|
result = m_cmp(a.Date, b.Date);
|
||||||
|
if (result != 0)
|
||||||
|
return result < 0;
|
||||||
|
return m_cmp(a.Album, b.Album) < 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +290,7 @@ void MediaLibrary::Update()
|
|||||||
Albums->addItem(SearchConstraints(*album, ""));
|
Albums->addItem(SearchConstraints(*album, ""));
|
||||||
}
|
}
|
||||||
if (!Albums->empty())
|
if (!Albums->empty())
|
||||||
std::sort(Albums->beginV(), Albums->endV(), SortSearchConstraints);
|
std::sort(Albums->beginV(), Albums->endV(), SortSearchConstraints());
|
||||||
if (Albums->size() > 1)
|
if (Albums->size() > 1)
|
||||||
{
|
{
|
||||||
Albums->addSeparator();
|
Albums->addSeparator();
|
||||||
@@ -300,7 +333,7 @@ void MediaLibrary::Update()
|
|||||||
}
|
}
|
||||||
Mpd.BlockIdle(0);
|
Mpd.BlockIdle(0);
|
||||||
if (!Albums->empty())
|
if (!Albums->empty())
|
||||||
std::sort(Albums->beginV(), Albums->endV(), SortSearchConstraints);
|
std::sort(Albums->beginV(), Albums->endV(), SortSearchConstraints());
|
||||||
Albums->refresh();
|
Albums->refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,7 +361,7 @@ void MediaLibrary::Update()
|
|||||||
Songs->addItem(*s, myPlaylist->checkForSong(*s));
|
Songs->addItem(*s, myPlaylist->checkForSong(*s));
|
||||||
|
|
||||||
if (Albums->current().value().Date == AllTracksMarker)
|
if (Albums->current().value().Date == AllTracksMarker)
|
||||||
std::sort(Songs->beginV(), Songs->endV(), SortAllTracks);
|
std::sort(Songs->beginV(), Songs->endV(), SortAllTracks());
|
||||||
else
|
else
|
||||||
std::sort(Songs->beginV(), Songs->endV(), SortSongsByTrack);
|
std::sort(Songs->beginV(), Songs->endV(), SortSongsByTrack);
|
||||||
|
|
||||||
@@ -572,7 +605,7 @@ MPD::SongList MediaLibrary::getSelectedSongs()
|
|||||||
Mpd.StartSearch(true);
|
Mpd.StartSearch(true);
|
||||||
Mpd.AddSearch(Config.media_lib_primary_tag, tag);
|
Mpd.AddSearch(Config.media_lib_primary_tag, tag);
|
||||||
auto songs = Mpd.CommitSearchSongs();
|
auto songs = Mpd.CommitSearchSongs();
|
||||||
std::sort(songs.begin(), songs.end(), SortAllTracks);
|
std::sort(songs.begin(), songs.end(), SortAllTracks());
|
||||||
result.insert(result.end(), songs.begin(), songs.end());
|
result.insert(result.end(), songs.begin(), songs.end());
|
||||||
};
|
};
|
||||||
for (auto it = Tags->begin(); it != Tags->end(); ++it)
|
for (auto it = Tags->begin(); it != Tags->end(); ++it)
|
||||||
@@ -915,34 +948,4 @@ bool SortSongsByTrack(const MPD::Song &a, const MPD::Song &b)
|
|||||||
return a.getTrack() < b.getTrack();
|
return a.getTrack() < b.getTrack();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SortAllTracks(const MPD::Song &a, const MPD::Song &b)
|
|
||||||
{
|
|
||||||
const std::array<MPD::Song::GetFunction, 3> gets = {{
|
|
||||||
&MPD::Song::getDate,
|
|
||||||
&MPD::Song::getAlbum,
|
|
||||||
&MPD::Song::getDisc
|
|
||||||
}};
|
|
||||||
CaseInsensitiveStringComparison cmp(Config.ignore_leading_the);
|
|
||||||
for (auto get = gets.begin(); get != gets.end(); ++get)
|
|
||||||
{
|
|
||||||
int ret = cmp(a.getTags(*get), b.getTags(*get));
|
|
||||||
if (ret != 0)
|
|
||||||
return ret < 0;
|
|
||||||
}
|
|
||||||
return a.getTrack() < b.getTrack();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SortSearchConstraints(const SearchConstraints &a, const SearchConstraints &b)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
CaseInsensitiveStringComparison cmp(Config.ignore_leading_the);
|
|
||||||
result = cmp(a.PrimaryTag, b.PrimaryTag);
|
|
||||||
if (result != 0)
|
|
||||||
return result < 0;
|
|
||||||
result = cmp(a.Date, b.Date);
|
|
||||||
if (result != 0)
|
|
||||||
return result < 0;
|
|
||||||
return cmp(a.Album, b.Album) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,9 +197,9 @@ void Playlist::EnterPressed()
|
|||||||
for (; begin != end; ++begin)
|
for (; begin != end; ++begin)
|
||||||
playlist.push_back(begin->value());
|
playlist.push_back(begin->value());
|
||||||
|
|
||||||
|
LocaleStringComparison cmp(std::locale(""), Config.ignore_leading_the);
|
||||||
std::function<void(MPD::SongList::iterator, MPD::SongList::iterator)> iter_swap, quick_sort;
|
std::function<void(MPD::SongList::iterator, MPD::SongList::iterator)> iter_swap, quick_sort;
|
||||||
auto song_cmp = [](const MPD::Song &a, const MPD::Song &b) -> bool {
|
auto song_cmp = [&cmp](const MPD::Song &a, const MPD::Song &b) -> bool {
|
||||||
CaseInsensitiveStringComparison cmp(Config.ignore_leading_the);
|
|
||||||
for (size_t i = 0; i < SortOptions; ++i)
|
for (size_t i = 0; i < SortOptions; ++i)
|
||||||
if (int ret = cmp(a.getTags((*SortDialog)[i].value().second), b.getTags((*SortDialog)[i].value().second)))
|
if (int ret = cmp(a.getTags((*SortDialog)[i].value().second), b.getTags((*SortDialog)[i].value().second)))
|
||||||
return ret < 0;
|
return ret < 0;
|
||||||
|
|||||||
@@ -448,6 +448,7 @@ void SearchEngine::Search()
|
|||||||
bool any_found = 1;
|
bool any_found = 1;
|
||||||
bool found = 1;
|
bool found = 1;
|
||||||
|
|
||||||
|
LocaleStringComparison cmp(std::locale(""), Config.ignore_leading_the);
|
||||||
for (auto it = list.begin(); it != list.end(); ++it)
|
for (auto it = list.begin(); it != list.end(); ++it)
|
||||||
{
|
{
|
||||||
if (SearchMode != &SearchModes[2]) // match to pattern
|
if (SearchMode != &SearchModes[2]) // match to pattern
|
||||||
@@ -535,8 +536,6 @@ void SearchEngine::Search()
|
|||||||
}
|
}
|
||||||
else // match only if values are equal
|
else // match only if values are equal
|
||||||
{
|
{
|
||||||
CaseInsensitiveStringComparison cmp(Config.ignore_leading_the);
|
|
||||||
|
|
||||||
if (!itsConstraints[0].empty())
|
if (!itsConstraints[0].empty())
|
||||||
any_found =
|
any_found =
|
||||||
!cmp(it->getArtist(), itsConstraints[0])
|
!cmp(it->getArtist(), itsConstraints[0])
|
||||||
@@ -573,10 +572,7 @@ void SearchEngine::Search()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (found && any_found)
|
if (found && any_found)
|
||||||
{
|
|
||||||
w->addItem(*it);
|
w->addItem(*it);
|
||||||
list[it-list.begin()] = 0;
|
|
||||||
}
|
|
||||||
found = 1;
|
found = 1;
|
||||||
any_found = 1;
|
any_found = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,33 +18,37 @@
|
|||||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <locale>
|
||||||
#include "comparators.h"
|
#include "comparators.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
bool CaseInsensitiveStringComparison::hasTheWord(const char *s) const
|
bool LocaleStringComparison::hasTheWord(const std::string &s) const
|
||||||
{
|
{
|
||||||
return (s[0] == 't' || s[0] == 'T')
|
return s.length() >= 4
|
||||||
|
&& (s[0] == 't' || s[0] == 'T')
|
||||||
&& (s[1] == 'h' || s[1] == 'H')
|
&& (s[1] == 'h' || s[1] == 'H')
|
||||||
&& (s[2] == 'e' || s[2] == 'E')
|
&& (s[2] == 'e' || s[2] == 'E')
|
||||||
&& (s[3] == ' ');
|
&& (s[3] == ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
int CaseInsensitiveStringComparison::operator()(const char *a, const char *b) const
|
int LocaleStringComparison::operator()(const std::string &a, const std::string &b) const
|
||||||
{
|
{
|
||||||
|
const char *ac = a.c_str();
|
||||||
|
const char *bc = b.c_str();
|
||||||
|
size_t ac_off = 0, bc_off = 0;
|
||||||
if (m_ignore_the)
|
if (m_ignore_the)
|
||||||
{
|
{
|
||||||
if (hasTheWord(a))
|
if (hasTheWord(a))
|
||||||
a += 4;
|
ac_off += 4;
|
||||||
if (hasTheWord(b))
|
if (hasTheWord(b))
|
||||||
b += 4;
|
bc_off += 4;
|
||||||
}
|
}
|
||||||
int dist;
|
return std::use_facet< std::collate<char> >(m_locale).compare(
|
||||||
while (!(dist = tolower(*a)-tolower(*b)) && *b)
|
ac+ac_off, ac+a.length(), bc+bc_off, bc+b.length()
|
||||||
++a, ++b;
|
);
|
||||||
return dist;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CaseInsensitiveSorting::CaseInsensitiveSorting(): cmp(Config.ignore_leading_the) { }
|
CaseInsensitiveSorting::CaseInsensitiveSorting(): cmp(std::locale(""), Config.ignore_leading_the) { }
|
||||||
|
|
||||||
bool CaseInsensitiveSorting::operator()(const MPD::Item &a, const MPD::Item &b) const
|
bool CaseInsensitiveSorting::operator()(const MPD::Item &a, const MPD::Item &b) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,31 +24,23 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include "mpdpp.h"
|
#include "mpdpp.h"
|
||||||
|
|
||||||
class CaseInsensitiveStringComparison
|
class LocaleStringComparison
|
||||||
{
|
{
|
||||||
|
std::locale m_locale;
|
||||||
bool m_ignore_the;
|
bool m_ignore_the;
|
||||||
|
|
||||||
bool hasTheWord(const char *s) const;
|
bool hasTheWord(const std::string &s) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CaseInsensitiveStringComparison(bool ignore_the) : m_ignore_the(ignore_the) { }
|
LocaleStringComparison(const std::locale &loc, bool ignore_the)
|
||||||
|
: m_locale(loc), m_ignore_the(ignore_the) { }
|
||||||
|
|
||||||
int operator()(const char *a, const char *b) const;
|
int operator()(const std::string &a, const std::string &b) const;
|
||||||
|
|
||||||
int operator()(const char *a, const std::string &b) const {
|
|
||||||
return (*this)(a, b.c_str());
|
|
||||||
}
|
|
||||||
int operator()(const std::string &a, const char *b) const {
|
|
||||||
return (*this)(a.c_str(), b);
|
|
||||||
}
|
|
||||||
int operator()(const std::string &a, const std::string &b) const {
|
|
||||||
return (*this)(a.c_str(), b.c_str());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CaseInsensitiveSorting
|
class CaseInsensitiveSorting
|
||||||
{
|
{
|
||||||
CaseInsensitiveStringComparison cmp;
|
LocaleStringComparison cmp;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CaseInsensitiveSorting();
|
CaseInsensitiveSorting();
|
||||||
|
|||||||
Reference in New Issue
Block a user