File indexing completed on 2024-05-12 15:55:22

0001 // SPDX-FileCopyrightText: 2003-2020 The KPhotoAlbum Development Team
0002 // SPDX-FileCopyrightText: 2021 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
0003 //
0004 // SPDX-License-Identifier: GPL-2.0-or-later
0005 
0006 #ifndef IMAGESEARCHINFO_H
0007 #define IMAGESEARCHINFO_H
0008 
0009 #include <DB/ImageDate.h>
0010 #include <DB/ImageInfoPtr.h>
0011 #include <DB/search/WildcardCategoryMatcher.h>
0012 #include <kpabase/StringSet.h>
0013 #include <kpabase/config-kpa-marble.h>
0014 #include <kpaexif/SearchInfo.h>
0015 
0016 #ifdef HAVE_MARBLE
0017 #include <Map/GeoCoordinates.h>
0018 #endif
0019 
0020 #include <QList>
0021 #include <QMap>
0022 namespace DB
0023 {
0024 
0025 class SimpleCategoryMatcher;
0026 class ImageInfo;
0027 class CategoryMatcher;
0028 
0029 class ImageSearchInfo
0030 {
0031 public:
0032     ImageSearchInfo();
0033     ImageSearchInfo(const ImageDate &date,
0034                     const QString &label, const QString &description);
0035     ImageSearchInfo(const ImageDate &date,
0036                     const QString &label, const QString &description,
0037                     const QString &fnPattern);
0038 
0039     ImageDate date() const;
0040 
0041     QString categoryMatchText(const QString &name) const;
0042     void setCategoryMatchText(const QString &name, const QString &value);
0043     void renameCategory(const QString &oldName, const QString &newName);
0044 
0045     QString label() const;
0046     QRegExp fnPattern() const;
0047     QString description() const;
0048 
0049     /**
0050      * @brief checkIfNull evaluates whether the filter is indeed empty and
0051      * sets isNull() to \c true if that is the case.
0052      * You only need to call this if you re-use an existing ImageSearchInfo
0053      * and set/reset search parameters.
0054      * @see ThumbnailView::toggleRatingFilter
0055      */
0056     void checkIfNull();
0057     bool isNull() const;
0058     bool match(ImageInfoPtr) const;
0059     QList<QList<SimpleCategoryMatcher *>> query() const;
0060 
0061     void addAnd(const QString &category, const QString &value);
0062     short rating() const;
0063     void setRating(short rating);
0064     /**
0065      * @brief toString generates a description of the ImageSearchInfo.
0066      * The idea is not to give a complete description, but rather something
0067      * useful for the breadcrumbs at the bottom of the main window.
0068      * @return a textual description of the ImageSearchInfo
0069      */
0070     QString toString() const;
0071 
0072     void setMegaPixel(short megapixel);
0073     void setMaxMegaPixel(short maxmegapixel);
0074     void setSearchRAW(bool m_searchRAW);
0075     void setSearchMode(int index);
0076 
0077     QVariantMap getLockData() const;
0078     static ImageSearchInfo loadLock(const QMap<QString, QVariant> &keyValuePairs);
0079 
0080     void debug();
0081     void debugMatcher() const;
0082     Utilities::StringSet findAlreadyMatched(const QString &group) const;
0083 
0084     void addExifSearchInfo(const Exif::SearchInfo info);
0085 
0086     // By default, an ImageSearchInfo is cacheable, but only one search
0087     // is cached per image.  For a search that's only going to be
0088     // performed once, don't try to cache the result.
0089     void setCacheable(bool cacheable);
0090     bool isCacheable() const;
0091 
0092 #ifdef HAVE_MARBLE
0093     Map::GeoCoordinates::LatLonBox regionSelection() const;
0094     void setRegionSelection(const Map::GeoCoordinates::LatLonBox &actRegionSelection);
0095 #endif
0096 
0097     QString freeformMatchText() const;
0098     /**
0099      * @brief setFreeformMatchText sets a freeform string to match on.
0100      * The idea is to provide a way to quickly drill down by entering unstructured text,
0101      * e.g. in the thumbnail view.
0102      *
0103      * Currently, this matches against:
0104      *  - description
0105      *  - label
0106      *  - relative filename
0107      *  - tag names
0108      * @param freeformMatchText a pattern suitable for a QRegularExpression match
0109      */
0110     void setFreeformMatchText(const QString &freeformMatchText);
0111 
0112 protected:
0113     void compile() const;
0114 
0115     QList<SimpleCategoryMatcher *> extractAndMatcher(CategoryMatcher *andMatcher) const;
0116     QList<QList<SimpleCategoryMatcher *>> convertMatcher(CategoryMatcher *) const;
0117 
0118 private:
0119     /**
0120      * @brief The CompiledDataPrivate struct encapsulates the non-copyable data members of the ImageSearchInfo.
0121      * It covers all category related search data (as covered by compile()), but not any other search fields.
0122      * Its copy constructor and copy operator invalidate the object,
0123      * This allows the ImageSearchInfo to just use the default copy/move constructors/operators.
0124      */
0125     struct CompiledDataPrivate {
0126         CompiledDataPrivate() = default;
0127         CompiledDataPrivate(const CompiledDataPrivate &other);
0128         CompiledDataPrivate(CompiledDataPrivate &&other) = default;
0129         ~CompiledDataPrivate();
0130         CompiledDataPrivate &operator=(const CompiledDataPrivate &other);
0131         CompiledDataPrivate &operator=(CompiledDataPrivate &&other) = default;
0132 
0133         bool valid = false;
0134         QList<CategoryMatcher *> categoryMatchers;
0135     };
0136     ImageDate m_date;
0137     QMap<QString, QString> m_categoryMatchText;
0138     QString m_label;
0139     QString m_description;
0140     WildcardCategoryMatcher m_freeformMatcher;
0141     QRegExp m_fnPattern;
0142     short m_rating = -1;
0143     short m_megapixel = 0;
0144     short m_max_megapixel = 0;
0145     int m_ratingSearchMode = 0;
0146     bool m_searchRAW = false;
0147     bool m_isNull = true;
0148     /**
0149      * @brief If a search is cacheable, its match result is stored in the ImageInfo.
0150      * Only one match result can be cached.
0151      * The matchGeneration is increased whenever the search info is changed, preventing stale results.
0152      */
0153     bool m_isCacheable = true;
0154     /**
0155      * @brief m_matchGeneration is used to determine whether a cached match result is still valid.
0156      * Remember to set it to nextGeneration() whenever the search info was changed and is cacheable!
0157      */
0158     int m_matchGeneration;
0159     mutable CompiledDataPrivate m_compiled;
0160 
0161     Exif::SearchInfo m_exifSearchInfo;
0162 
0163     bool doMatch(ImageInfoPtr) const;
0164 
0165 #ifdef HAVE_MARBLE
0166     Map::GeoCoordinates::LatLonBox m_regionSelection;
0167 #endif
0168     // When adding new instance variable, please notice that this class has an explicit written copy constructor.
0169 };
0170 }
0171 
0172 #endif /* IMAGESEARCHINFO_H */
0173 
0174 // vi:expandtab:tabstop=4 shiftwidth=4: