1 // SPDX-FileCopyrightText: 2003-2020 The KPhotoAlbum Development Team
2 // SPDX-FileCopyrightText: 2021 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
3 //
4 // SPDX-License-Identifier: GPL-2.0-or-later
5 
6 #ifndef EXIFDATABASE_H
7 #define EXIFDATABASE_H
8 
9 #include <kpabase/FileNameList.h>
10 
11 #include <QList>
12 #include <QPair>
13 #include <QString>
14 
15 namespace DB
16 {
17 class UIDelegate;
18 class AbstractProgressIndicator;
19 }
20 namespace Exiv2
21 {
22 class ExifData;
23 }
24 
25 typedef QPair<int, int> Rational;
26 typedef QList<Rational> RationalList;
27 typedef QPair<DB::FileName, Exiv2::ExifData> DBExifInfo;
28 
29 namespace Exif
30 {
31 class DatabaseElement;
32 
33 // ============================================================================
34 // IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT
35 // ============================================================================
36 //
37 // It is the resposibility of the methods in here to bail out in case database
38 // support is not available ( !isAvailable() ). This is to simplify client code.
39 class Database
40 {
41 public:
42     typedef QList<DatabaseElement *> ElementList;
43     typedef QPair<QString, QString> Camera;
44     typedef QList<Camera> CameraList;
45     typedef QString Lens;
46     typedef QList<Lens> LensList;
47 
48     Database(const QString &sqliteFileName, DB::UIDelegate &uiDelegate);
49     Database(const Database &) = delete;
50     ~Database();
51 
52     Database &operator=(const Database &) = delete;
53 
54     static bool isAvailable();
55     /**
56      * @brief DBVersion is the exif search database schema version currently supported by KPhotoAlbum.
57      * @return the Exif Database version
58      */
59     static int DBVersion();
60 
61     /**
62      * @brief isUsable
63      * @return \c true, if the Exif database is available, open, and not in a failure state. \c false otherwise
64      */
65     bool isUsable() const;
66     /**
67      * @brief DBFileVersion is the database schema version used in the exif-info.db file.
68      * @return the database schema version used by the database file, or 0 on error.
69      */
70     int DBFileVersion() const;
71     /**
72      * @brief DBFileVersionGuaranteed reflects DBVersion of the last time the exif db has been built.
73      * It is just like the DBFileVersion() but concerning the data.
74      * The schema version is automatically updated to a newer schema, but normally the
75      * data in the exif database is not.
76      * In this situation, only newly added pictures are populated with the new fields, whereas
77      * existing pictures have empty values.
78      * However, once the user rebuilds the exif database, we can guarantee all entries in the
79      * database to conform to the new schema, and DBFileVersionGuaranteed() will be updated to the new value.
80      * @return 0 <= DBFileVersionGuaranteed() <= DBFileVersion()
81      */
82     int DBFileVersionGuaranteed() const;
83     /**
84      * @brief Adds a file and its exif data to the exif database.
85      * If the file already exists in the database, the new data replaces the existing data.
86      * @param filename
87      * @param data the exif data
88      * @return \c true, if the operation succeeded, \c false otherwise
89      */
90     bool add(const DB::FileName &filename, Exiv2::ExifData data);
91     /**
92      * @brief Adds a file to the exif database, reading its exif data from the file.
93      * @param fileName
94      * @return \c true, if the operation succeeded, \c false otherwise
95      */
96     bool add(const DB::FileName &fileName);
97     /**
98      * @brief Adds a list of files to the exif database, reading the exif data from the files.
99      * @param list
100      * @return \c true, if the operation succeeded, \c false otherwise
101      */
102     bool add(const DB::FileNameList &list);
103     /**
104      * @brief Removes a single file from the exif database.
105      * Removing a file that is not in the database is allowed.
106      * @param fileName
107      */
108     void remove(const DB::FileName &fileName);
109     /**
110      * @brief Removes a list of files from the exif database.
111      * Passing an empty list or a list that contains files that are not actually in the exif database is allowed.
112      * @param list
113      */
114     void remove(const DB::FileNameList &list);
115     /**
116      * @brief readFields searches the exif database for a given file and fills the element list with values.
117      * If the query fails or has no result, the ElementList is not changed.
118      * @param fileName
119      * @param fields a list of the DatabaseElements that you want to read.
120      * @return true, if the fileName is found in the database, false otherwise.
121      */
122     bool readFields(const DB::FileName &fileName, ElementList &fields) const;
123     DB::FileNameSet filesMatchingQuery(const QString &query) const;
124     CameraList cameras() const;
125     LensList lenses() const;
126 
127     /**
128      * @brief size
129      * @return The number of entries in the Exif database
130      */
131     int size() const;
132 
133     /**
134      * @brief Discards the current exif database and recreates it from the given files.
135      *
136      * Exiv2 seems to accept both image and movie files without ill effects
137      * (but does not actually return any usable metadata).
138      *
139      * Recreating the exif database can take a lot of time. To get a decent user experience in spite of that,
140      * the method updates the given AbstractProgressIndicator and calls QCoreApplication::processEvents()
141      * in regular intervals (if a QCoreApplication instance is available).
142      *
143      * To be on the safe side though, you should still filter out non-image files as long as there is no official support for movie files in exiv2.
144      * @param allImageFiles a list of all image files
145      * @param progressIndicator for quick usage from a GUI application, use a DB::ProgressIndicator<QProgressDialog>
146      */
147     void recreate(const DB::FileNameList &allImageFiles, DB::AbstractProgressIndicator &progressIndicator);
148     bool startInsertTransaction();
149     bool commitInsertTransaction();
150     bool abortInsertTransaction();
151 
152 private:
153     class DatabasePrivate;
154     DatabasePrivate *d_ptr;
155     Q_DECLARE_PRIVATE(Database)
156 };
157 }
158 
159 #endif /* EXIFDATABASE_H */
160 
161 // vi:expandtab:tabstop=4 shiftwidth=4:
162