1 #pragma once
2 
3 #include <gtest/gtest_prod.h>
4 
5 #include <QDir>
6 #include <QList>
7 #include <QSharedPointer>
8 #include <QSqlDatabase>
9 
10 #include "library/crate/cratestorage.h"
11 #include "library/dao/analysisdao.h"
12 #include "library/dao/cuedao.h"
13 #include "library/dao/directorydao.h"
14 #include "library/dao/libraryhashdao.h"
15 #include "library/dao/playlistdao.h"
16 #include "library/dao/trackdao.h"
17 #include "preferences/usersettings.h"
18 #include "util/thread_affinity.h"
19 
20 // forward declaration(s)
21 class BaseTrackCache;
22 
23 // Manages the internal database.
24 class TrackCollection : public QObject,
25     public virtual /*implements*/ SqlStorage {
26     Q_OBJECT
27 
28   public:
29     TrackCollection(
30             QObject* parent,
31             const UserSettingsPointer& pConfig);
32     ~TrackCollection() override;
33 
34     void repairDatabase(
35             const QSqlDatabase& database) override;
36 
37     void connectDatabase(
38             const QSqlDatabase& database) override;
39     void disconnectDatabase() override;
40 
database()41     QSqlDatabase database() const {
42         DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this);
43         return m_database;
44     }
45 
crates()46     const CrateStorage& crates() const {
47         DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this);
48         return m_crates;
49     }
50 
getTrackDAO()51     TrackDAO& getTrackDAO() {
52         DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this);
53         return m_trackDao;
54     }
getPlaylistDAO()55     PlaylistDAO& getPlaylistDAO() {
56         DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this);
57         return m_playlistDao;
58     }
getDirectoryDAO()59     DirectoryDAO& getDirectoryDAO() {
60         DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this);
61         return m_directoryDao;
62     }
getAnalysisDAO()63     AnalysisDao& getAnalysisDAO() {
64         DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this);
65         return m_analysisDao;
66     }
67 
68     void connectTrackSource(QSharedPointer<BaseTrackCache> pTrackSource);
69     QWeakPointer<BaseTrackCache> disconnectTrackSource();
70 
getTrackSource()71     QSharedPointer<BaseTrackCache> getTrackSource() const {
72         DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this);
73         return m_pTrackSource;
74     }
75 
76     // This function returns a track ID of all file in the list not already visible,
77     // it adds and unhides the tracks as well.
78     QList<TrackId> resolveTrackIds(
79             const QList<TrackFile> &trackFiles,
80             TrackDAO::ResolveTrackIdFlags flags);
81     QList<TrackId> resolveTrackIdsFromUrls(
82             const QList<QUrl>& urls,
83             bool addMissing);
84     QList<TrackId> resolveTrackIdsFromLocations(
85             const QList<QString>& locations);
86 
87     bool insertCrate(const Crate& crate, CrateId* pCrateId = nullptr);
88     bool updateCrate(const Crate& crate);
89     bool deleteCrate(CrateId crateId);
90     bool addCrateTracks(CrateId crateId, const QList<TrackId>& trackIds);
91     bool removeCrateTracks(CrateId crateId, const QList<TrackId>& trackIds);
92 
93     bool updateAutoDjCrate(CrateId crateId, bool isAutoDjSource);
94 
95     TrackPointer getTrackById(
96             TrackId trackId) const;
97 
98     TrackPointer getTrackByRef(
99             const TrackRef& trackRef) const;
100     TrackId getTrackIdByRef(
101             const TrackRef& trackRef) const;
102 
103   signals:
104     // Forwarded signals from LibraryScanner
105     void scanTrackAdded(TrackPointer pTrack);
106 
107     // Forwarded signals from TrackDAO
108     void trackClean(TrackId trackId);
109     void trackDirty(TrackId trackId);
110     void tracksAdded(const QSet<TrackId>& trackIds);
111     void tracksChanged(const QSet<TrackId>& trackIds);
112     void tracksRemoved(const QSet<TrackId>& trackIds);
113     void multipleTracksChanged();
114 
115     void crateInserted(CrateId id);
116     void crateUpdated(CrateId id);
117     void crateDeleted(CrateId id);
118 
119     void crateTracksChanged(
120             CrateId crate,
121             const QList<TrackId>& tracksAdded,
122             const QList<TrackId>& tracksRemoved);
123     void crateSummaryChanged(
124             const QSet<CrateId>& crates);
125 
126   private:
127     friend class TrackCollectionManager;
128     friend class Upgrade;
129 
130     // No parent during database schema upgrade
TrackCollection(const UserSettingsPointer & pConfig)131     explicit TrackCollection(const UserSettingsPointer& pConfig)
132             : TrackCollection(nullptr, pConfig) {
133     }
134 
135     TrackPointer getOrAddTrack(
136             const TrackRef& trackRef,
137             bool* pAlreadyInLibrary = nullptr);
138     FRIEND_TEST(DirectoryDAOTest, relocateDirectory);
139     FRIEND_TEST(TrackDAOTest, detectMovedTracks);
140     TrackId addTrack(
141             const TrackPointer& pTrack,
142             bool unremove);
143 
144     bool hideTracks(const QList<TrackId>& trackIds);
145     bool unhideTracks(const QList<TrackId>& trackIds);
146     void hideAllTracks(const QDir& rootDir);
147 
148     bool purgeTracks(const QList<TrackId>& trackIds);
149     bool purgeAllTracks(const QDir& rootDir);
150 
151     bool addDirectory(const QString& dir);
152     bool removeDirectory(const QString& dir);
153     void relocateDirectory(const QString& oldDir, const QString& newDir);
154 
155     void saveTrack(Track* pTrack);
156 
157     QSqlDatabase m_database;
158 
159     PlaylistDAO m_playlistDao;
160     CrateStorage m_crates;
161     CueDAO m_cueDao;
162     DirectoryDAO m_directoryDao;
163     AnalysisDao m_analysisDao;
164     LibraryHashDAO m_libraryHashDao;
165     TrackDAO m_trackDao;
166 
167     QSharedPointer<BaseTrackCache> m_pTrackSource;
168 };
169