File indexing completed on 2025-01-19 03:53:24
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2007-04-09 0007 * Description : Collection location management - private containers. 0008 * 0009 * SPDX-FileCopyrightText: 2007-2009 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #ifndef DIGIKAM_COLLECTION_MANAGER_P_H 0016 #define DIGIKAM_COLLECTION_MANAGER_P_H 0017 0018 #include "collectionmanager.h" 0019 0020 // Qt includes 0021 0022 #include <QDir> 0023 #include <QDirIterator> 0024 #include <QCoreApplication> 0025 #include <QCryptographicHash> 0026 #include <QReadWriteLock> 0027 #include <QUrlQuery> 0028 #include <QThread> 0029 #include <QUuid> 0030 0031 // KDE includes 0032 0033 #include <klocalizedstring.h> 0034 0035 // Solid includes 0036 0037 #if defined(Q_CC_CLANG) 0038 # pragma clang diagnostic push 0039 # pragma clang diagnostic ignored "-Wnonportable-include-path" 0040 #endif 0041 0042 #include <solid/device.h> 0043 #include <solid/deviceinterface.h> 0044 #include <solid/devicenotifier.h> 0045 #include <solid/storageaccess.h> 0046 #include <solid/storagedrive.h> 0047 #include <solid/storagevolume.h> 0048 #include <solid/opticaldisc.h> 0049 #include <solid/predicate.h> 0050 0051 #if defined(Q_CC_CLANG) 0052 # pragma clang diagnostic pop 0053 #endif 0054 0055 // Local includes 0056 0057 #include "digikam_debug.h" 0058 #include "coredbaccess.h" 0059 #include "coredbchangesets.h" 0060 #include "coredbtransaction.h" 0061 #include "coredb.h" 0062 #include "collectionscanner.h" 0063 #include "collectionlocation.h" 0064 #include "filereadwritelock.h" 0065 0066 namespace Digikam 0067 { 0068 0069 class Q_DECL_HIDDEN AlbumRootLocation : public CollectionLocation 0070 { 0071 0072 public: 0073 0074 AlbumRootLocation() 0075 : available(false), 0076 hidden (false) 0077 { 0078 } 0079 0080 explicit AlbumRootLocation(const AlbumRootInfo& info) 0081 { 0082 qCDebug(DIGIKAM_DATABASE_LOG) << "Creating new Location " << info.specificPath << " uuid " << info.identifier; 0083 m_id = info.id; 0084 m_type = (Type)info.type; 0085 QString path = info.specificPath; 0086 m_caseSensitivity = (CaseSensitivity)info.caseSensitivity; 0087 0088 if ((path != QLatin1String("/")) && 0089 path.endsWith(QLatin1Char('/'))) 0090 { 0091 path.chop(1); 0092 } 0093 0094 specificPath = path; 0095 identifier = info.identifier; 0096 m_label = info.label; 0097 0098 m_path.clear(); 0099 0100 setStatus((CollectionLocation::Status)info.status); 0101 } 0102 0103 void setStatusFromFlags() 0104 { 0105 if (hidden) 0106 { 0107 m_status = CollectionLocation::LocationHidden; 0108 } 0109 else 0110 { 0111 if (available) 0112 { 0113 m_status = CollectionLocation::LocationAvailable; 0114 } 0115 else 0116 { 0117 m_status = CollectionLocation::LocationUnavailable; 0118 } 0119 } 0120 } 0121 0122 void setCaseSensitivity(CollectionLocation::CaseSensitivity c) 0123 { 0124 m_caseSensitivity = c; 0125 } 0126 0127 void setStatus(CollectionLocation::Status s) 0128 { 0129 m_status = s; 0130 0131 // status is exclusive, and Hidden wins 0132 // but really both states are independent 0133 // - a hidden location might or might not be available 0134 0135 if (m_status == CollectionLocation::LocationAvailable) 0136 { 0137 available = true; 0138 hidden = false; 0139 } 0140 else if (m_status == CollectionLocation::LocationHidden) 0141 { 0142 available = false; 0143 hidden = true; 0144 } 0145 else // Unavailable, Null, Deleted 0146 { 0147 available = false; 0148 hidden = false; 0149 } 0150 } 0151 0152 void setId(int id) 0153 { 0154 m_id = id; 0155 } 0156 0157 void setAbsolutePath(const QString& path) 0158 { 0159 m_path = path; 0160 } 0161 0162 void setType(Type type) 0163 { 0164 m_type = type; 0165 } 0166 0167 void setLabel(const QString& label) 0168 { 0169 m_label = label; 0170 } 0171 0172 public: 0173 0174 QString specificPath; 0175 bool available; 0176 bool hidden; 0177 }; 0178 0179 // ------------------------------------------------- 0180 0181 class Q_DECL_HIDDEN SolidVolumeInfo 0182 { 0183 0184 public: 0185 0186 SolidVolumeInfo() 0187 : isRemovable (false), 0188 isOpticalDisc(false), 0189 isMounted (false) 0190 { 0191 } 0192 0193 bool isNull() const 0194 { 0195 return path.isNull(); 0196 } 0197 0198 public: 0199 0200 QString udi; ///< Solid device UDI of the StorageAccess device 0201 QString path; ///< mount path of volume, with trailing slash 0202 QString uuid; ///< UUID as from Solid 0203 QString label; ///< volume label (think of CDs) 0204 bool isRemovable; ///< may be removed 0205 bool isOpticalDisc; ///< is an optical disk device as CD/DVD/BR 0206 bool isMounted; ///< is mounted on File System. 0207 }; 0208 0209 // ------------------------------------------------- 0210 0211 class Q_DECL_HIDDEN CollectionManager::Private 0212 { 0213 0214 public: 0215 0216 explicit Private(CollectionManager* const s); 0217 0218 /// hack for Solid's threading problems 0219 QList<SolidVolumeInfo> actuallyListVolumes(); 0220 void slotTriggerUpdateVolumesList(); 0221 QList<SolidVolumeInfo> volumesListCache; 0222 0223 0224 /// Access Solid and return a list of storage volumes 0225 QList<SolidVolumeInfo> listVolumes(); 0226 0227 /** 0228 * Find from a given list (usually the result of listVolumes) the volume 0229 * corresponding to the location 0230 */ 0231 SolidVolumeInfo findVolumeForLocation(const AlbumRootLocation* location, const QList<SolidVolumeInfo>& volumes); 0232 0233 /** 0234 * Find from a given list (usually the result of listVolumes) the volume 0235 * on which the file path specified by the url is located. 0236 */ 0237 SolidVolumeInfo findVolumeForUrl(const QUrl& fileUrl, const QList<SolidVolumeInfo>& volumes); 0238 0239 /// Create the volume identifier for the given volume info 0240 QString volumeIdentifier(const SolidVolumeInfo& info); 0241 0242 /// Create a volume identifier based on the path only 0243 QString volumeIdentifier(const QString& path); 0244 0245 /// Create a network share identifier based on the mountpaths 0246 QString networkShareIdentifier(const QStringList& paths); 0247 0248 /// Return the path, if location has a path-only identifier. Else returns a null string. 0249 QString pathFromIdentifier(const AlbumRootLocation* location); 0250 0251 /// Return the path, if location has a path-only identifier. Else returns a null string. 0252 QStringList networkShareMountPathsFromIdentifier(const AlbumRootLocation* location); 0253 0254 /// Create an MD5 hash of the top-level entries (file names, not file content) of the given path 0255 static QString directoryHash(const QString& path); 0256 0257 /// Check if a location for specified path exists, assuming the given list of locations was deleted 0258 bool checkIfExists(const QString& path, QList<CollectionLocation> assumeDeleted); 0259 0260 /// Make a user presentable description, regardless of current location status 0261 QString technicalDescription(const AlbumRootLocation* location); 0262 0263 /// Get the file UUID in the collection root if possible. 0264 QString getCollectionUUID(const QString& path); 0265 0266 /// Check or create the file UUID in the collection root if possible. 0267 bool checkCollectionUUID(AlbumRootLocation* const location, const QString& path); 0268 0269 public: 0270 0271 QReadWriteLock lock; 0272 QMap<int, AlbumRootLocation*> locations; 0273 bool changingDB; 0274 QStringList udisToWatch; 0275 bool watchEnabled; 0276 CollectionManager* s; 0277 }; 0278 0279 // ------------------------------------------------- 0280 0281 class Q_DECL_HIDDEN ChangingDB 0282 { 0283 0284 public: 0285 0286 explicit ChangingDB(CollectionManager::Private* const dd) 0287 : d(dd) 0288 { 0289 d->changingDB = true; 0290 } 0291 0292 ~ChangingDB() 0293 { 0294 d->changingDB = false; 0295 } 0296 0297 public: 0298 0299 CollectionManager::Private* const d; 0300 }; 0301 0302 } // namespace Digikam 0303 0304 #endif // DIGIKAM_COLLECTION_MANAGER_P_H