1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#pragma once
#include "track/trackid.h"
#include "track/trackfile.h"
// A track in the library is identified by a location and an id.
// The location is mandatory to identify the file, whereas the id
// only exists after the track has been inserted into the database.
//
// This class is intended to be used as a simple, almost immutable
// value object. Only the id can be set once.
class TrackRef final {
public:
// Converts a TrackFile and an optional TrackId into a TrackRef. This
// involves obtaining the file-related track properties from QFileInfo
// (see above) and should used consciously! The file info is refreshed
// implicitly if the canonical location if necessary.
static TrackRef fromFileInfo(
TrackFile fileInfo,
TrackId id = TrackId()) {
auto canonicalLocation = fileInfo.freshCanonicalLocation();
// All properties of the file info are now considered fresh
return TrackRef(
fileInfo.location(),
std::move(canonicalLocation),
std::move(id));
}
// Default constructor
TrackRef() {
DEBUG_ASSERT(verifyConsistency());
}
// Regular copy constructor
TrackRef(const TrackRef& other) = default;
// Custom copy constructor: Creates a copy of an existing TrackRef,
// but overwrite the TrackId with a custom value.
TrackRef(
const TrackRef& other,
TrackId id)
: m_location(other.m_location),
m_canonicalLocation(other.m_canonicalLocation),
m_id(id) {
DEBUG_ASSERT(verifyConsistency());
}
// The human-readable identifier of a track in Mixxx. The location is
// immutable and the starting point for accessing a track's file.
const QString& getLocation() const {
return m_location;
}
bool hasLocation() const {
return !getLocation().isEmpty();
}
// The unique identifier of a track's file at runtime and used
// for caching. The canonical location is empty for inexistent
// files.
const QString& getCanonicalLocation() const {
return m_canonicalLocation;
}
bool hasCanonicalLocation() const {
return !getCanonicalLocation().isEmpty();
}
// The primary key of a track in the Mixxx library. The id must only
// be set once after inserting into or after loading from the database.
// Tracks that have not been stored in the database don't have an id.
const TrackId& getId() const {
return m_id;
}
bool hasId() const {
return getId().isValid();
}
bool isValid() const {
return hasId() || hasCanonicalLocation();
}
protected:
// Initializing constructor
TrackRef(
const QString& location,
const QString& canonicalLocation,
TrackId id = TrackId())
: m_location(location),
m_canonicalLocation(canonicalLocation),
m_id(id) {
DEBUG_ASSERT(verifyConsistency());
}
private:
// Checks if all class invariants are met
bool verifyConsistency() const;
QString m_location;
QString m_canonicalLocation;
TrackId m_id;
};
inline
bool operator==(const TrackRef& lhs, const TrackRef& rhs) {
return (lhs.getId() == rhs.getId()) &&
(lhs.getLocation() == rhs.getLocation()) &&
(lhs.getCanonicalLocation() == rhs.getCanonicalLocation());
}
inline
bool operator!=(const TrackRef& lhs, const TrackRef& rhs) {
return !(lhs == rhs);
}
Q_DECLARE_METATYPE(TrackRef)
std::ostream& operator<<(std::ostream& os, const TrackRef& trackRef);
QDebug operator<<(QDebug debug, const TrackRef& trackRef);
inline uint qHash(
const TrackRef& key,
uint seed = 0) {
return qHash(
key.getLocation(), seed) ^
qHash(key.getId(), seed);
}
|