File indexing completed on 2024-05-12 05:47:29
0001 /* 0002 * SPDX-FileCopyrightText: 2012 Peter Penz <peter.penz19@gmail.com> 0003 * SPDX-FileCopyrightText: 2013 Vishesh Handa <me@vhanda.in> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "kbaloorolesprovider.h" 0009 0010 #include <Baloo/File> 0011 #include <KFileMetaData/PropertyInfo> 0012 #include <KFileMetaData/UserMetaData> 0013 0014 #include <QCollator> 0015 #include <QSize> 0016 0017 namespace 0018 { 0019 QString tagsFromValues(const QStringList &values) 0020 { 0021 if (values.size() == 1) { 0022 return values.at(0); 0023 } 0024 0025 QStringList alphabeticalOrderTags = values; 0026 QCollator coll; 0027 coll.setNumericMode(true); 0028 std::sort(alphabeticalOrderTags.begin(), alphabeticalOrderTags.end(), [&](const QString &s1, const QString &s2) { 0029 return coll.compare(s1, s2) < 0; 0030 }); 0031 return alphabeticalOrderTags.join(QLatin1String(", ")); 0032 } 0033 0034 using Property = KFileMetaData::Property::Property; 0035 // Mapping from the KFM::Property to the KFileItemModel roles. 0036 const QHash<Property, QByteArray> propertyRoleMap() { 0037 static const auto map = QHash<Property, QByteArray> { 0038 { Property::Rating, QByteArrayLiteral("rating") }, 0039 { Property::Comment, QByteArrayLiteral("comment") }, 0040 { Property::Title, QByteArrayLiteral("title") }, 0041 { Property::Author, QByteArrayLiteral("author") }, 0042 { Property::Publisher, QByteArrayLiteral("publisher") }, 0043 { Property::PageCount, QByteArrayLiteral("pageCount") }, 0044 { Property::WordCount, QByteArrayLiteral("wordCount") }, 0045 { Property::LineCount, QByteArrayLiteral("lineCount") }, 0046 { Property::Width, QByteArrayLiteral("width") }, 0047 { Property::Height, QByteArrayLiteral("height") }, 0048 { Property::ImageDateTime, QByteArrayLiteral("imageDateTime") }, 0049 { Property::ImageOrientation, QByteArrayLiteral("orientation") }, 0050 { Property::Artist, QByteArrayLiteral("artist") }, 0051 { Property::Genre, QByteArrayLiteral("genre") }, 0052 { Property::Album, QByteArrayLiteral("album") }, 0053 { Property::Duration, QByteArrayLiteral("duration") }, 0054 { Property::BitRate, QByteArrayLiteral("bitrate") }, 0055 { Property::AspectRatio, QByteArrayLiteral("aspectRatio") }, 0056 { Property::FrameRate, QByteArrayLiteral("frameRate") }, 0057 { Property::ReleaseYear, QByteArrayLiteral("releaseYear") }, 0058 { Property::TrackNumber, QByteArrayLiteral("track") } 0059 }; 0060 return map; 0061 } 0062 } 0063 0064 struct KBalooRolesProviderSingleton { 0065 KBalooRolesProvider instance; 0066 }; 0067 Q_GLOBAL_STATIC(KBalooRolesProviderSingleton, s_balooRolesProvider) 0068 0069 KBalooRolesProvider &KBalooRolesProvider::instance() 0070 { 0071 return s_balooRolesProvider->instance; 0072 } 0073 0074 KBalooRolesProvider::~KBalooRolesProvider() 0075 { 0076 } 0077 0078 QSet<QByteArray> KBalooRolesProvider::roles() const 0079 { 0080 return m_roles; 0081 } 0082 0083 QHash<QByteArray, QVariant> KBalooRolesProvider::roleValues(const Baloo::File &file, const QSet<QByteArray> &roles) const 0084 { 0085 QHash<QByteArray, QVariant> values; 0086 0087 using entry = std::pair<const KFileMetaData::Property::Property &, const QVariant &>; 0088 0089 const auto &propMap = file.properties(); 0090 auto rangeBegin = propMap.constKeyValueBegin(); 0091 0092 while (rangeBegin != propMap.constKeyValueEnd()) { 0093 auto key = (*rangeBegin).first; 0094 0095 auto rangeEnd = std::find_if(rangeBegin, propMap.constKeyValueEnd(), [key](const entry &e) { 0096 return e.first != key; 0097 }); 0098 0099 const QByteArray role = propertyRoleMap().value(key); 0100 if (role.isEmpty() || !roles.contains(role)) { 0101 rangeBegin = rangeEnd; 0102 continue; 0103 } 0104 0105 const KFileMetaData::PropertyInfo propertyInfo(key); 0106 auto distance = std::distance(rangeBegin, rangeEnd); 0107 if (distance > 1) { 0108 QVariantList list; 0109 list.reserve(static_cast<int>(distance)); 0110 std::for_each(rangeBegin, rangeEnd, [&list](const entry &s) { 0111 list.append(s.second); 0112 }); 0113 values.insert(role, propertyInfo.formatAsDisplayString(list)); 0114 } else { 0115 if (propertyInfo.valueType() == QMetaType::Type::QDateTime) { 0116 // Let dolphin format later Dates 0117 values.insert(role, (*rangeBegin).second); 0118 } else { 0119 values.insert(role, propertyInfo.formatAsDisplayString((*rangeBegin).second)); 0120 } 0121 } 0122 rangeBegin = rangeEnd; 0123 } 0124 0125 if (roles.contains("dimensions")) { 0126 bool widthOk = false; 0127 bool heightOk = false; 0128 0129 const int width = propMap.value(KFileMetaData::Property::Width).toInt(&widthOk); 0130 const int height = propMap.value(KFileMetaData::Property::Height).toInt(&heightOk); 0131 0132 if (widthOk && heightOk && width >= 0 && height >= 0) { 0133 values.insert("dimensions", QSize(width, height)); 0134 } 0135 } 0136 0137 KFileMetaData::UserMetaData::Attributes attributes; 0138 if (roles.contains("tags")) { 0139 attributes |= KFileMetaData::UserMetaData::Tags; 0140 } 0141 if (roles.contains("rating")) { 0142 attributes |= KFileMetaData::UserMetaData::Rating; 0143 } 0144 if (roles.contains("comment")) { 0145 attributes |= KFileMetaData::UserMetaData::Comment; 0146 } 0147 if (roles.contains("originUrl")) { 0148 attributes |= KFileMetaData::UserMetaData::OriginUrl; 0149 } 0150 0151 if (attributes == KFileMetaData::UserMetaData::None) { 0152 return values; 0153 } 0154 0155 KFileMetaData::UserMetaData md(file.path()); 0156 attributes = md.queryAttributes(attributes); 0157 0158 if (attributes & KFileMetaData::UserMetaData::Tags) { 0159 values.insert("tags", tagsFromValues(md.tags())); 0160 } 0161 if (attributes & KFileMetaData::UserMetaData::Rating) { 0162 values.insert("rating", QString::number(md.rating())); 0163 } 0164 if (attributes & KFileMetaData::UserMetaData::Comment) { 0165 values.insert("comment", md.userComment()); 0166 } 0167 if (attributes & KFileMetaData::UserMetaData::OriginUrl) { 0168 values.insert("originUrl", md.originUrl()); 0169 } 0170 0171 return values; 0172 } 0173 0174 KBalooRolesProvider::KBalooRolesProvider() 0175 { 0176 // Display roles filled from Baloo property cache 0177 for (const auto &role : propertyRoleMap()) { 0178 m_roles.insert(role); 0179 } 0180 m_roles.insert("dimensions"); 0181 0182 // Display roles provided by UserMetaData 0183 m_roles.insert(QByteArrayLiteral("tags")); 0184 m_roles.insert(QByteArrayLiteral("rating")); 0185 m_roles.insert(QByteArrayLiteral("comment")); 0186 m_roles.insert(QByteArrayLiteral("originUrl")); 0187 }