1 /* 2 * Cantata 3 * 4 * Copyright (c) 2017-2020 Craig Drummond <craig.p.drummond@gmail.com> 5 * 6 * ---- 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; see the file COPYING. If not, write to 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 */ 23 24 #ifndef LIBRARY_DB_H 25 #define LIBRARY_DB_H 26 27 #include <QObject> 28 #include <QList> 29 #include <QMap> 30 #include <QElapsedTimer> 31 #include "mpd-interface/song.h" 32 #include <time.h> 33 34 class QSqlDatabase; 35 class QSqlQuery; 36 37 class LibraryDb : public QObject 38 { 39 Q_OBJECT 40 41 public: enableDebug()42 static void enableDebug() { dbgEnabled=true; } debugEnabled()43 static bool debugEnabled() { return dbgEnabled; } 44 45 static const QLatin1String constFileExt; 46 static const QLatin1String constNullGenre; 47 48 enum AlbumSort { 49 AS_AlArYr, 50 AS_AlYrAr, 51 AS_ArAlYr, 52 AS_ArYrAl, 53 AS_YrAlAr, 54 AS_YrArAl, 55 AS_Modified, 56 57 AS_Count 58 }; 59 60 static AlbumSort toAlbumSort(const QString &str); 61 static QString albumSortStr(AlbumSort m); 62 63 struct Genre 64 { 65 Genre(const QString &n=QString(), int ac=0) nameGenre66 : name(n), artistCount(ac) { } 67 QString name; 68 int artistCount; 69 70 bool operator<(const Genre &o) const 71 { 72 if (constNullGenre==name) { 73 return constNullGenre!=o.name; 74 } 75 return name.localeAwareCompare(o.name)<0; 76 } 77 }; 78 79 struct Artist 80 { 81 Artist(const QString &n=QString(), const QString &s=QString(), int ac=0) nameArtist82 : name(n), sort(s), albumCount(ac) { } 83 QString name; 84 QString sort; 85 int albumCount; 86 87 bool operator<(const Artist &o) const 88 { 89 const QString &field=sort.isEmpty() ? name : sort; 90 const QString &ofield=o.sort.isEmpty() ? o.name : o.sort; 91 92 return field.localeAwareCompare(ofield)<0; 93 } 94 }; 95 96 struct Album 97 { 98 Album(const QString &n=QString(), const QString &i=QString(), const QString &s=QString(), 99 const QString &a=QString(), const QString &as=QString(), 100 int y=0, int tc=0, int d=0, int lm=0, bool onlyUseId=false) nameAlbum101 : name(n), id(i), sort(s), artist(a), artistSort(as), year(y), trackCount(tc), duration(d), lastModified(lm), identifyById(onlyUseId) { } 102 QString name; 103 QString id; 104 QString sort; 105 QString artist; 106 QString artistSort; 107 int year; 108 int trackCount; 109 int duration; 110 int lastModified; 111 bool identifyById; // Should we jsut use albumId to locate tracks - Issue #1025 112 }; 113 114 LibraryDb(QObject *p, const QString &name); 115 ~LibraryDb() override; 116 117 void clear(); 118 void erase(); 119 virtual bool init(const QString &dbFile); 120 void insertSong(const Song &s); 121 QList<Genre> getGenres(); 122 QList<Artist> getArtists(const QString &genre=QString()); 123 QList<Album> getAlbums(const QString &artistId=QString(), const QString &genre=QString(), AlbumSort sort=AS_YrAlAr); 124 QList<Song> getTracks(const QString &artistId, const QString &albumId, const QString &genre=QString(), AlbumSort sort=AS_YrAlAr, bool useFilter=true); 125 QList<Song> getTracks(int rowFrom, int count); 126 int trackCount(); 127 QList<Song> songs(const QStringList &files, bool allowPlaylists=false) const; 128 QList<Album> getAlbumsWithArtistOrComposer(const QString &artist); 129 Album getRandomAlbum(const QString &genre, const QString &artist); 130 Album getRandomAlbum(const QStringList &genres, const QStringList &artists); 131 QSet<QString> get(const QString &type); 132 void getDetails(QSet<QString> &artists, QSet<QString> &albumArtists, QSet<QString> &composers, QSet<QString> &albums, QSet<QString> &genres); 133 bool songExists(const Song &song); 134 bool setFilter(const QString &f, const QString &genre=QString()); getFilter()135 const QString & getFilter() const { return filter; } getCurrentVersion()136 int getCurrentVersion() const { return currentVersion; } 137 138 Q_SIGNALS: 139 void libraryUpdated(); 140 void error(const QString &str); 141 142 public Q_SLOTS: 143 void updateStarted(time_t ver); 144 void insertSongs(QList<Song> *songs); 145 virtual void updateFinished(); 146 void abortUpdate(); 147 148 protected: 149 bool createTable(const QString &q); 150 static Song getSong(const QSqlQuery &query); 151 152 protected: 153 virtual void reset(); 154 void clearSongs(bool startTransaction=true); 155 156 protected: 157 static bool dbgEnabled; 158 159 QString dbName; 160 QString dbFileName; 161 time_t currentVersion; 162 time_t newVersion; 163 QSqlDatabase *db; 164 QSqlQuery *insertSongQuery; 165 QElapsedTimer timer; 166 QString filter; 167 QString genreFilter; 168 QString yearFilter; 169 QMap<QString, QSet<QString> > detailsCache; 170 }; 171 172 #endif 173