Logo Search packages:      
Sourcecode: madman version File versions  Download package

song_list_tools.cpp

/*
madman - a music manager
Copyright (C) 2003  Andreas Kloeckner <ak@ixion.net>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/




#include <qregexp.h>
#include <qapplication.h>
#include "database/song_list_tools.h"




// comparison helpers ---------------------------------------------------------
#define MAKE_STRING_SONG_LESS(CLASSNAME, FIELD) \
struct CLASSNAME \
{ \
  bool operator()(tSong *song1, tSong *song2) \
  { \
    return song1->FIELD().lower().localeAwareCompare(song2->FIELD().lower()) < 0; \
  } \
};

#define MAKE_CXX_STRING_SONG_LESS(CLASSNAME, FIELD) \
struct CLASSNAME \
{ \
  bool operator()(tSong *song1, tSong *song2) \
  { \
    return QString::fromUtf8(song1->FIELD().c_str()).lower().localeAwareCompare( \
        QString::fromUtf8(song2->FIELD().c_str()).lower()) < 0; \
  } \
};

#define MAKE_NUMERIC_SONG_LESS(CLASSNAME, FIELD) \
struct CLASSNAME \
{ \
  bool operator()(tSong *song1, tSong *song2) \
  { \
    return song1->FIELD() < song2->FIELD(); \
  } \
};

namespace 
{
  MAKE_STRING_SONG_LESS(tArtistLess, artist);
  MAKE_STRING_SONG_LESS(tPerformerLess, performer);
  MAKE_STRING_SONG_LESS(tTitleLess, title);
  MAKE_STRING_SONG_LESS(tAlbumLess, album);
  MAKE_STRING_SONG_LESS(tGenreLess, genre);
  MAKE_CXX_STRING_SONG_LESS(tFilenameLess, filenameOnly);
  MAKE_CXX_STRING_SONG_LESS(tPathLess, pathname);
  MAKE_STRING_SONG_LESS(tMimeTypeLess, mimeType);
  MAKE_NUMERIC_SONG_LESS(tDurationLess, duration);
  MAKE_NUMERIC_SONG_LESS(tFullPlayCountLess, fullPlayCount);
  MAKE_NUMERIC_SONG_LESS(tPartialPlayCountLess, partialPlayCount);
  MAKE_NUMERIC_SONG_LESS(tPlayCountLess, playCount);
  MAKE_NUMERIC_SONG_LESS(tLastPlayedLess, lastPlayed);
  MAKE_NUMERIC_SONG_LESS(tRatingLess, rating);
  MAKE_NUMERIC_SONG_LESS(tYearLess, year().toInt); // HACKY-WHACKY :)
  MAKE_NUMERIC_SONG_LESS(tSizeLess, fileSize);
  MAKE_NUMERIC_SONG_LESS(tExistsSinceLess, existsSince);
  MAKE_NUMERIC_SONG_LESS(tLastModifiedLess, lastModified);
  MAKE_NUMERIC_SONG_LESS(tUniqueIdLess, uniqueId);

  struct tTrackNumberLess 
  {
    bool operator()(tSong *song1, tSong *song2)
    {
      QRegExp extract_numbers("^\\s*([0-9]+)");

      if (extract_numbers.search(song1->trackNumber()) != -1)
      {
      int my_track = extract_numbers.cap(1).toInt();
      if (extract_numbers.search(song2->trackNumber()) != -1)
      {
        // both have track numbers, compare them
        int other_track = extract_numbers.cap(1).toInt();
        return my_track < other_track;
      }
      else
      {
        // other is smaller since it has no track number
        return false;
      }
      }
      else
      {
      if (extract_numbers.search(song2->trackNumber()) != -1)
        return true; // "this" is smaller since it has no track number
      else
        return false; // neither has a track number
      }
    }
  };
}




void sort(tSongList &list, tSongField field)
{
  switch (field)
  {
    // FIXME switch back to sort when bug in gcc is gone
    case FIELD_ARTIST : stable_sort(list.begin(), list.end(), tArtistLess()); break;
    case FIELD_PERFORMER : stable_sort(list.begin(), list.end(), tPerformerLess()); break;
    case FIELD_TITLE : stable_sort(list.begin(), list.end(), tTitleLess()); break;
    case FIELD_ALBUM : stable_sort(list.begin(), list.end(), tAlbumLess()); break;
    case FIELD_TRACKNUMBER : stable_sort(list.begin(), list.end(), tTrackNumberLess()); break;
    case FIELD_DURATION : stable_sort(list.begin(), list.end(), tDurationLess()); break;
    case FIELD_GENRE : stable_sort(list.begin(), list.end(), tGenreLess()); break;
    case FIELD_FULLPLAYCOUNT : stable_sort(list.begin(), list.end(), tFullPlayCountLess()); break;
    case FIELD_PARTIALPLAYCOUNT : stable_sort(list.begin(), list.end(), tPartialPlayCountLess()); break;
    case FIELD_PLAYCOUNT : stable_sort(list.begin(), list.end(), tPlayCountLess()); break;
    case FIELD_LASTPLAYED : stable_sort(list.begin(), list.end(), tLastPlayedLess()); break;
    case FIELD_RATING : stable_sort(list.begin(), list.end(), tRatingLess()); break;
    case FIELD_YEAR : stable_sort(list.begin(), list.end(), tYearLess()); break;
    case FIELD_FILE : stable_sort(list.begin(), list.end(), tFilenameLess()); break;
    case FIELD_PATH : stable_sort(list.begin(), list.end(), tPathLess()); break;
    case FIELD_SIZE : stable_sort(list.begin(), list.end(), tSizeLess()); break;
    case FIELD_EXISTSSINCE : stable_sort(list.begin(), list.end(), tExistsSinceLess()); break;
    case FIELD_LASTMODIFIED : stable_sort(list.begin(), list.end(), tLastModifiedLess()); break;
    case FIELD_MIMETYPE: stable_sort(list.begin(), list.end(), tMimeTypeLess()); break;
    case FIELD_UNIQUEID: stable_sort(list.begin(), list.end(), tUniqueIdLess()); break;
    default:
      throw tRuntimeError("Invalid field id while sorting SongSetEntryList");
  }
}




// song list summaries --------------------------------------------------------
tSongListSummary getSongListSummary(tSongList &list)
{
  tSongListSummary result;
  result.DurationTotal = 0;
  result.SizeTotal = 0;
  result.Count = list.size();

  FOREACH_CONST(first, list, tSongList)
  {
    result.DurationTotal += (*first)->duration();
    result.SizeTotal += (*first)->fileSize() / (1024. * 1024);
  }

  double duration = result.DurationTotal;
  result.DurationDays = int(duration / 3600. / 24.);
  duration -= result.DurationDays * 3600 * 24;
  result.DurationHours = int(duration / 3600);
  duration -= result.DurationHours * 3600;
  result.DurationMinutes = int(duration / 60);
  duration -= result.DurationMinutes * 60;
  result.DurationSeconds = int(duration);

  if (list.size())
    result.FirstFilename = QString::fromUtf8(list[0]->filename().c_str());
  return result;
}




QString     stringifySongListSummary(const tSongListSummary &sum)
{
  QString duration_string;
  if (sum.DurationDays)
    duration_string.sprintf("%d days %d:%02d:%02d", 
      sum.DurationDays, sum.DurationHours, sum.DurationMinutes, 
      sum.DurationSeconds);
  else if (sum.DurationHours)
    duration_string.sprintf("%d:%02d:%02d", 
      sum.DurationHours, sum.DurationMinutes, sum.DurationSeconds);
  else
    duration_string.sprintf("%2d:%02d", 
      sum.DurationMinutes, sum.DurationSeconds);

  QString result;
  if (sum.Count == 0)
  {
    result = qApp->translate("StatusMessages", "0 songs");
  }
  else if (sum.Count == 1)
  {
   result = qApp->translate("StatusMessages", "%1 - Duration %2, Size %3 ]")
      .arg(sum.FirstFilename)
      .arg(duration_string)
      .arg(qApp->translate("StatusMessages", "%1 MB").arg(sum.SizeTotal, 0, 'f', 2));
  }
  else
  {
    result = qApp->translate("StatusMessages", "%1 songs - Duration %2 - Size %3")
      .arg(sum.Count)
      .arg(duration_string)
      .arg(qApp->translate("StatusMessages", "%1 MB").arg(sum.SizeTotal, 0, 'f', 2));
  }
  return result;
}




QString     stringifySongListSummary(tSongList &list)
{
  return stringifySongListSummary(getSongListSummary(list));
}

Generated by  Doxygen 1.6.0   Back to index