File indexing completed on 2025-02-16 13:03:42
0001 /* 0002 This file is part of the KFileMetaData project 0003 SPDX-FileCopyrightText: 2014 Vishesh Handa <me@vhanda.in> 0004 0005 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 0008 #include "propertyinfo.h" 0009 0010 #include <KLazyLocalizedString> 0011 #include <KLocalizedString> 0012 0013 #include "formatstrings_p.h" 0014 0015 #include <array> 0016 0017 #include <QLocale> 0018 0019 using namespace KFileMetaData; 0020 0021 class KFileMetaData::PropertyInfoData 0022 { 0023 using FormatFunction = QString (&)(const QVariant&); 0024 0025 public: 0026 const Property::Property prop; 0027 const bool shouldBeIndexed = false; 0028 const QString name; 0029 const KLazyLocalizedString displayName; 0030 const QVariant::Type valueType = QVariant::Invalid; 0031 const FormatFunction formatAsString = FormatStrings::toStringFunction; 0032 }; 0033 0034 const static PropertyInfoData staticEmptyPropertyInfo{ Property::Empty, false, QStringLiteral("empty"), kli18n("Empty"), QVariant::Invalid }; 0035 0036 const static std::array<PropertyInfoData, 78> staticPropertyInfo 0037 { 0038 PropertyInfoData{ Property::Album, true, QStringLiteral("album"), kli18nc("@label music album", "Album"), QVariant::String }, 0039 PropertyInfoData{ Property::AlbumArtist, true, QStringLiteral("albumArtist"), kli18nc("@label", "Album Artist"), QVariant::String }, 0040 PropertyInfoData{ Property::Artist, true, QStringLiteral("artist"), kli18nc("@label", "Artist"), QVariant::String }, 0041 PropertyInfoData{ Property::AspectRatio, false, QStringLiteral("aspectRatio"), kli18nc("@label", "Aspect Ratio"), QVariant::Double, FormatStrings::formatAspectRatio }, 0042 PropertyInfoData{ Property::Author, true, QStringLiteral("author"), kli18nc("@label", "Author"), QVariant::String }, 0043 PropertyInfoData{ Property::BitRate, false, QStringLiteral("bitRate"), kli18nc("@label", "Bitrate"), QVariant::Int, FormatStrings::formatBitRate }, 0044 PropertyInfoData{ Property::Channels, false, QStringLiteral("channels"), kli18nc("@label", "Channels"), QVariant::Int }, 0045 PropertyInfoData{ Property::Comment, false, QStringLiteral("comment"), kli18nc("@label", "Comment"), QVariant::String }, 0046 PropertyInfoData{ Property::Description, false, QStringLiteral("description"), kli18nc("@label", "Description"), QVariant::String }, 0047 PropertyInfoData{ Property::Composer, true, QStringLiteral("composer"), kli18nc("@label", "Composer"), QVariant::String }, 0048 PropertyInfoData{ Property::Copyright, false, QStringLiteral("copyright"), kli18nc("@label", "Copyright"), QVariant::String }, 0049 PropertyInfoData{ Property::CreationDate, false, QStringLiteral("creationDate"), kli18nc("@label", "Creation Date"), QVariant::DateTime, FormatStrings::formatDate }, 0050 PropertyInfoData{ Property::Duration, false, QStringLiteral("duration"), kli18nc("@label", "Duration"), QVariant::Int, FormatStrings::formatDuration }, 0051 PropertyInfoData{ Property::FrameRate, false, QStringLiteral("frameRate"), kli18nc("@label", "Frame Rate"), QVariant::Double, FormatStrings::formatAsFrameRate }, 0052 PropertyInfoData{ Property::Generator, false, QStringLiteral("generator"), kli18nc("@label", "Document Generated By"), QVariant::String }, 0053 PropertyInfoData{ Property::Genre, true, QStringLiteral("genre"), kli18nc("@label music genre", "Genre"), QVariant::String }, 0054 PropertyInfoData{ Property::Height, false, QStringLiteral("height"), kli18nc("@label", "Height"), QVariant::Int }, 0055 PropertyInfoData{ Property::ImageDateTime, false, QStringLiteral("imageDateTime"), kli18nc("@label EXIF", "Image Date Time"), QVariant::DateTime, FormatStrings::formatDate }, 0056 PropertyInfoData{ Property::Manufacturer, false, QStringLiteral("manufacturer"), kli18nc("@label EXIF", "Manufacturer"), QVariant::String }, 0057 PropertyInfoData{ Property::Model, false, QStringLiteral("model"), kli18nc("@label EXIF", "Model"), QVariant::String }, 0058 PropertyInfoData{ Property::ImageOrientation, false, QStringLiteral("imageOrientation"), kli18nc("@label EXIF", "Image Orientation"), QVariant::Int, FormatStrings::formatOrientationValue }, 0059 PropertyInfoData{ Property::Keywords, false, QStringLiteral("keywords"), kli18nc("@label", "Keywords"), QVariant::String }, 0060 PropertyInfoData{ Property::Language, false, QStringLiteral("language"), kli18nc("@label", "Language"), QVariant::String }, 0061 PropertyInfoData{ Property::LineCount, false, QStringLiteral("lineCount"), kli18nc("@label number of lines", "Line Count"), QVariant::Int }, 0062 PropertyInfoData{ Property::Lyricist, true, QStringLiteral("lyricist"), kli18nc("@label", "Lyricist"), QVariant::String }, 0063 PropertyInfoData{ Property::PageCount, false, QStringLiteral("pageCount"), kli18nc("@label", "Page Count"), QVariant::Int }, 0064 PropertyInfoData{ Property::PhotoApertureValue, false, QStringLiteral("photoApertureValue"), kli18nc("@label EXIF", "Aperture Value"), QVariant::Double, FormatStrings::formatAsFNumber }, 0065 PropertyInfoData{ Property::PhotoDateTimeOriginal, false, QStringLiteral("photoDateTimeOriginal"), kli18nc("@label EXIF", "Original Date Time"), QVariant::DateTime, FormatStrings::formatDate }, 0066 PropertyInfoData{ Property::PhotoExposureBiasValue, false, QStringLiteral("photoExposureBiasValue"), kli18nc("@label EXIF", "Exposure Bias"), QVariant::Double, FormatStrings::formatPhotoExposureBias }, 0067 PropertyInfoData{ Property::PhotoExposureTime, false, QStringLiteral("photoExposureTime"), kli18nc("@label EXIF", "Exposure Time"), QVariant::Double, FormatStrings::formatPhotoTime }, 0068 PropertyInfoData{ Property::PhotoFlash, false, QStringLiteral("photoFlash"), kli18nc("@label EXIF", "Flash"), QVariant::Int, FormatStrings::formatPhotoFlashValue }, 0069 PropertyInfoData{ Property::PhotoFNumber, false, QStringLiteral("photoFNumber"), kli18nc("@label EXIF", "F Number"), QVariant::Double, FormatStrings::formatAsFNumber }, 0070 PropertyInfoData{ Property::PhotoFocalLength, false, QStringLiteral("photoFocalLength"), kli18nc("@label EXIF", "Focal Length"), QVariant::Double, FormatStrings::formatAsMilliMeter }, 0071 PropertyInfoData{ Property::PhotoFocalLengthIn35mmFilm, false, QStringLiteral("photoFocalLengthIn35mmFilm"), kli18nc("@label EXIF", "Focal Length 35mm"), QVariant::Double, FormatStrings::formatAsMilliMeter }, 0072 PropertyInfoData{ Property::PhotoGpsLatitude, false, QStringLiteral("photoGpsLatitude"), kli18nc("@label EXIF", "GPS Latitude"), QVariant::Double, FormatStrings::formatAsDegree }, 0073 PropertyInfoData{ Property::PhotoGpsLongitude, false, QStringLiteral("photoGpsLongitude"), kli18nc("@label EXIF", "GPS Longitude"), QVariant::Double, FormatStrings::formatAsDegree }, 0074 PropertyInfoData{ Property::PhotoGpsAltitude, false, QStringLiteral("photoGpsAltitude"), kli18nc("@label EXIF", "GPS Altitude"), QVariant::Double, FormatStrings::formatAsMeter }, 0075 PropertyInfoData{ Property::PhotoISOSpeedRatings, false, QStringLiteral("photoISOSpeedRatings"), kli18nc("@label EXIF", "ISO Speed Rating"), QVariant::Int }, 0076 PropertyInfoData{ Property::PhotoMeteringMode, false, QStringLiteral("photoMeteringMode"), kli18nc("@label EXIF", "Metering Mode"), QVariant::Int }, 0077 PropertyInfoData{ Property::PhotoPixelXDimension, false, QStringLiteral("photoPixelXDimension"), kli18nc("@label EXIF", "X Dimension"), QVariant::Int }, 0078 PropertyInfoData{ Property::PhotoPixelYDimension, false, QStringLiteral("photoPixelYDimension"), kli18nc("@label EXIF", "Y Dimension"), QVariant::Int }, 0079 PropertyInfoData{ Property::PhotoSaturation, false, QStringLiteral("photoSaturation"), kli18nc("@label EXIF", "Saturation"), QVariant::Int }, 0080 PropertyInfoData{ Property::PhotoSharpness, false, QStringLiteral("photoSharpness"), kli18nc("@label EXIF", "Sharpness"), QVariant::Int }, 0081 PropertyInfoData{ Property::PhotoWhiteBalance, false, QStringLiteral("photoWhiteBalance"), kli18nc("@label EXIF", "White Balance"), QVariant::Int }, 0082 PropertyInfoData{ Property::Publisher, true, QStringLiteral("publisher"), kli18nc("@label", "Publisher"), QVariant::String }, 0083 PropertyInfoData{ Property::Label, true, QStringLiteral("label"), kli18nc("@label", "Label"), QVariant::String }, 0084 PropertyInfoData{ Property::ReleaseYear, false, QStringLiteral("releaseYear"), kli18nc("@label", "Release Year"), QVariant::Int }, 0085 PropertyInfoData{ Property::SampleRate, false, QStringLiteral("sampleRate"), kli18nc("@label", "Sample Rate"), QVariant::Int, FormatStrings::formatSampleRate }, 0086 PropertyInfoData{ Property::Subject, false, QStringLiteral("subject"), kli18nc("@label", "Subject"), QVariant::String }, 0087 PropertyInfoData{ Property::Title, true, QStringLiteral("title"), kli18nc("@label", "Title"), QVariant::String }, 0088 PropertyInfoData{ Property::TrackNumber, false, QStringLiteral("trackNumber"), kli18nc("@label music track number", "Track Number"), QVariant::Int }, 0089 PropertyInfoData{ Property::DiscNumber, false, QStringLiteral("discNumber"), kli18nc("@label music disc number", "Disc Number"), QVariant::Int }, 0090 PropertyInfoData{ Property::Location, true, QStringLiteral("location"), kli18nc("@label", "Location"), QVariant::String }, 0091 PropertyInfoData{ Property::Performer, true, QStringLiteral("performer"), kli18nc("@label", "Performer"), QVariant::String }, 0092 PropertyInfoData{ Property::Ensemble, true, QStringLiteral("ensemble"), kli18nc("@label", "Ensemble"), QVariant::String }, 0093 PropertyInfoData{ Property::Arranger, true, QStringLiteral("arranger"), kli18nc("@label", "Arranger"), QVariant::String }, 0094 PropertyInfoData{ Property::Conductor, true, QStringLiteral("conductor"), kli18nc("@label", "Conductor"), QVariant::String }, 0095 PropertyInfoData{ Property::Compilation, true, QStringLiteral("compilation"), kli18nc("@label", "Compilation"), QVariant::String }, 0096 PropertyInfoData{ Property::License, true, QStringLiteral("license"), kli18nc("@label", "License"), QVariant::String }, 0097 PropertyInfoData{ Property::Lyrics, true, QStringLiteral("lyrics"), kli18nc("@label", "Lyrics"), QVariant::String }, 0098 PropertyInfoData{ Property::Opus, false, QStringLiteral("opus"), kli18nc("@label", "Opus"), QVariant::Int }, 0099 PropertyInfoData{ Property::Rating, false, QStringLiteral("embeddedRating"), kli18nc("@label", "Rating"), QVariant::Int }, 0100 PropertyInfoData{ Property::ReplayGainAlbumPeak, false, QStringLiteral("replayGainAlbumPeak"), kli18nc("@label ReplayGain is the name of a standard", "ReplayGain Album Peak"), QVariant::Double, FormatStrings::formatDouble }, 0101 PropertyInfoData{ Property::ReplayGainAlbumGain, false, QStringLiteral("replayGainAlbumGain"), kli18nc("@label ReplayGain is the name of a standard", "ReplayGain Album Gain"), QVariant::Double, FormatStrings::formatDouble }, 0102 PropertyInfoData{ Property::ReplayGainTrackPeak, false, QStringLiteral("replayGainTrackPeak"), kli18nc("@label ReplayGain is the name of a standard", "ReplayGain Track Peak"), QVariant::Double, FormatStrings::formatDouble }, 0103 PropertyInfoData{ Property::ReplayGainTrackGain, false, QStringLiteral("replayGainTrackGain"), kli18nc("@label ReplayGain is the name of a standard", "ReplayGain Track Gain"), QVariant::Double, FormatStrings::formatDouble }, 0104 PropertyInfoData{ Property::Width, false, QStringLiteral("width"), kli18nc("@label", "Width"), QVariant::Int }, 0105 PropertyInfoData{ Property::WordCount, false, QStringLiteral("wordCount"), kli18nc("@label number of words", "Word Count"), QVariant::Int }, 0106 PropertyInfoData{ Property::TranslationUnitsTotal, false, QStringLiteral("translationUnitsTotal"), kli18nc("@label number of translatable strings", "Translatable Units"), QVariant::Int }, 0107 PropertyInfoData{ Property::TranslationUnitsWithTranslation, false, QStringLiteral("translationUnitsWithTranslation"), kli18nc("@label number of translated strings", "Translations"), QVariant::Int }, 0108 PropertyInfoData{ Property::TranslationUnitsWithDraftTranslation, false, QStringLiteral("translationUnitsWithDraftTranslation"), kli18nc("@label number of fuzzy translated strings", "Draft Translations"), QVariant::Int }, 0109 PropertyInfoData{ Property::TranslationLastAuthor, false, QStringLiteral("translationLastAuthor"), kli18nc("@label translation author", "Author"), QVariant::String }, 0110 PropertyInfoData{ Property::TranslationLastUpDate, false, QStringLiteral("translationLastUpDate"), kli18nc("@label translations last update", "Last Update"), QVariant::String, FormatStrings::formatDate }, 0111 PropertyInfoData{ Property::TranslationTemplateDate, false, QStringLiteral("translationTemplateDate"), kli18nc("@label date of template creation8", "Template Creation"), QVariant::String, FormatStrings::formatDate }, 0112 PropertyInfoData{ Property::OriginUrl, false, QStringLiteral("originUrl"), kli18nc("@label the URL a file was originally downloaded from", "Downloaded From"), QVariant::Url }, 0113 PropertyInfoData{ Property::OriginEmailSubject, false, QStringLiteral("originEmailSubject"), kli18nc("@label the subject of an email this file was attached to", "E-Mail Attachment Subject"), QVariant::String }, 0114 PropertyInfoData{ Property::OriginEmailSender, false, QStringLiteral("originEmailSender"), kli18nc("@label the sender of an email this file was attached to", "E-Mail Attachment Sender"), QVariant::String }, 0115 PropertyInfoData{ Property::OriginEmailMessageId, false, QStringLiteral("originEmailMessageId"), kli18nc("@label the message ID of an email this file was attached to", "E-Mail Attachment Message ID"), QVariant::String } 0116 }; 0117 0118 namespace { 0119 auto constexpr propertyDataById(Property::Property property) { 0120 for (const auto& p : staticPropertyInfo) { 0121 if (p.prop == property) 0122 return &p; 0123 } 0124 return &staticEmptyPropertyInfo; 0125 } 0126 } 0127 0128 PropertyInfo::PropertyInfo(Property::Property property) : d(propertyDataById(property)) {}; 0129 0130 PropertyInfo::PropertyInfo() : d(&staticEmptyPropertyInfo) {}; 0131 0132 PropertyInfo::PropertyInfo(const PropertyInfo& pi) 0133 : d(pi.d) 0134 { 0135 } 0136 0137 PropertyInfo::~PropertyInfo() = default; 0138 0139 PropertyInfo& PropertyInfo::operator=(const PropertyInfo& rhs) 0140 { 0141 d = rhs.d; 0142 return *this; 0143 } 0144 0145 bool PropertyInfo::operator==(const PropertyInfo& rhs) const 0146 { 0147 return d == rhs.d; 0148 } 0149 0150 QString PropertyInfo::displayName() const 0151 { 0152 return d->displayName.toString(); 0153 } 0154 0155 QString PropertyInfo::name() const 0156 { 0157 return d->name; 0158 } 0159 0160 Property::Property PropertyInfo::property() const 0161 { 0162 return d->prop; 0163 } 0164 0165 QVariant::Type PropertyInfo::valueType() const 0166 { 0167 return d->valueType; 0168 } 0169 0170 bool PropertyInfo::shouldBeIndexed() const 0171 { 0172 return d->shouldBeIndexed; 0173 } 0174 0175 QString PropertyInfo::formatAsDisplayString(const QVariant &value) const 0176 { 0177 if (value.type() == QVariant::List || value.type() == QVariant::StringList) { 0178 if (d->valueType == QVariant::String) { 0179 return QLocale().createSeparatedList(value.toStringList()); 0180 } else { 0181 QStringList displayList; 0182 const auto valueList = value.toList(); 0183 for (const auto& entry : valueList) { 0184 displayList << d->formatAsString(entry); 0185 } 0186 return QLocale().createSeparatedList(displayList); 0187 } 0188 } else { 0189 return d->formatAsString(value); 0190 } 0191 } 0192 0193 namespace { 0194 class LcPropertyName 0195 { 0196 public: 0197 LcPropertyName(const QString& n) : name(n) {}; 0198 QString name; 0199 }; 0200 0201 constexpr QChar trivialToLower(const QChar &c) { 0202 if (c.isUpper()) { 0203 return QChar::fromLatin1(c.toLatin1() ^ ('a' ^ 'A')); 0204 } 0205 return c; 0206 } 0207 0208 inline bool operator==(const LcPropertyName &a, const LcPropertyName &b) 0209 { 0210 if (a.name.size() != b.name.size()) { 0211 return false; 0212 } 0213 for (int i = 0; i < a.name.size(); i++) { 0214 if ((a.name[i] != b.name[i]) && (trivialToLower(a.name[i]) != trivialToLower(b.name[i]))) { 0215 return false; 0216 } 0217 } 0218 return true; 0219 } 0220 0221 inline size_t qHash(const LcPropertyName &key, size_t seed = 0) 0222 { 0223 size_t val = seed; 0224 for (const auto& c : key.name) { 0225 val ^= qHash(trivialToLower(c)); 0226 } 0227 return val; 0228 } 0229 0230 static const QHash<LcPropertyName, PropertyInfo> propertyHash = []() { 0231 QHash<LcPropertyName, PropertyInfo> infoHash; 0232 infoHash.reserve(staticPropertyInfo.size()); 0233 0234 for (const auto& info: staticPropertyInfo) { 0235 infoHash[info.name] = info.prop; 0236 } 0237 return infoHash; 0238 }(); 0239 } 0240 0241 PropertyInfo PropertyInfo::fromName(const QString& name) 0242 { 0243 return propertyHash.value(LcPropertyName(name)); 0244 } 0245 0246 QStringList PropertyInfo::allNames() 0247 { 0248 static QStringList sNames = []() { 0249 QStringList names; 0250 names.reserve(staticPropertyInfo.size()); 0251 for (auto info: staticPropertyInfo) { 0252 names.append(info.name); 0253 } 0254 return names; 0255 }(); 0256 return sNames; 0257 }