File indexing completed on 2024-12-08 10:16:05
0001 /* 0002 SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #ifndef WIKIDATA_ITEM_H 0008 #define WIKIDATA_ITEM_H 0009 0010 #include <QColor> 0011 #include <QDebug> 0012 #include <QJsonObject> 0013 #include <QMetaType> 0014 #include <QVariant> 0015 0016 #include <cstdint> 0017 #include <vector> 0018 0019 namespace Wikidata { 0020 0021 template <typename T, char Prefix> 0022 class Identifier 0023 { 0024 public: 0025 explicit inline constexpr Identifier() {} 0026 explicit inline constexpr Identifier(T id) : m_id(id) {} 0027 explicit inline Identifier(const QString &id) : m_id(fromString(id).m_id) {} 0028 explicit inline Identifier(const QByteArray &id) : m_id(fromString(id).m_id) {} 0029 0030 inline constexpr bool isValid() const 0031 { 0032 return m_id > 0; 0033 } 0034 0035 inline constexpr bool operator<(Identifier other) const 0036 { 0037 return m_id < other.m_id; 0038 } 0039 inline constexpr bool operator==(Identifier other) const 0040 { 0041 return m_id == other.m_id; 0042 } 0043 inline constexpr bool operator!=(Identifier other) const 0044 { 0045 return m_id != other.m_id; 0046 } 0047 0048 inline QString toString() const 0049 { 0050 return QLatin1Char(Prefix) + QString::number(m_id); 0051 } 0052 0053 protected: 0054 T m_id = 0; 0055 0056 private: 0057 static inline Identifier fromString(const QString &id) 0058 { 0059 if (!id.startsWith(QLatin1Char(Prefix))) { 0060 return Identifier(); 0061 } 0062 return Identifier(QStringView(id).mid(1).toULongLong()); 0063 } 0064 static inline Identifier fromString(const QByteArray &id) 0065 { 0066 if (!id.startsWith(Prefix)) { 0067 return Identifier(); 0068 } 0069 return Identifier(id.mid(1).toULongLong()); 0070 } 0071 }; 0072 0073 /** Wikidata item identifier. */ 0074 class Q : public Identifier<uint64_t, 'Q'> 0075 { 0076 public: 0077 explicit inline constexpr Q() = default; 0078 explicit inline constexpr Q(uint64_t id) : Identifier(id) {} 0079 explicit inline Q(const QString &id) : Identifier(id) {} 0080 explicit inline Q(const QByteArray &id) : Identifier(id) {} 0081 }; 0082 0083 /** Wikidata property identifier. */ 0084 class P : public Identifier<uint32_t, 'P'> 0085 { 0086 public: 0087 enum Property : uint32_t { 0088 instanceOf = 31, 0089 logoImage = 154, 0090 partOf = 361, 0091 }; 0092 0093 explicit inline constexpr P() = default; 0094 /* implicit */ inline constexpr P(Property id) : Identifier(id) {} 0095 explicit inline constexpr P(uint32_t id) : Identifier(id) {} 0096 explicit inline P(const QString &id) : Identifier(id) {} 0097 }; 0098 0099 /** Wikidata item. */ 0100 class Item 0101 { 0102 public: 0103 explicit Item(); 0104 explicit Item(Q id, const QJsonObject &data); 0105 ~Item(); 0106 0107 inline constexpr bool isValid() const { return m_id.isValid(); } 0108 inline constexpr Q id() const { return m_id; } 0109 0110 template <typename T> 0111 inline T value(P property) const 0112 { 0113 return convertValue<T>(value(property)); 0114 } 0115 0116 template <typename T> 0117 inline std::vector<T> values(P property) const 0118 { 0119 const auto vals = values(property); 0120 std::vector<T> v; 0121 v.reserve(vals.size()); 0122 std::transform(vals.begin(), vals.end(), std::back_inserter(v), [](const QVariant &value) { return convertValue<T>(value); }); 0123 return v; 0124 } 0125 0126 private: 0127 std::vector<QVariant> values(P property) const; 0128 QVariant value(P property) const; 0129 0130 template <typename T> 0131 static inline T convertValue(const QVariant &v) 0132 { 0133 return v.value<T>(); 0134 } 0135 0136 Q m_id; 0137 QJsonObject m_data; 0138 }; 0139 0140 template <> 0141 inline QColor Item::convertValue<QColor>(const QVariant &v) 0142 { 0143 const auto s = v.toString(); 0144 if (s.size() == 6) { 0145 return QColor(QLatin1Char('#') + s); 0146 } 0147 return QColor(s); 0148 } 0149 0150 /** Commons image metadata. */ 0151 class Image 0152 { 0153 public: 0154 explicit Image(); 0155 explicit Image(const QJsonObject &obj); 0156 ~Image(); 0157 0158 QString name() const; 0159 uint64_t fileSize() const; 0160 uint32_t width() const; 0161 uint32_t height() const; 0162 QString mimeType() const; 0163 QString license() const; 0164 0165 private: 0166 QJsonObject imageInfo() const; 0167 QJsonObject m_data; 0168 }; 0169 0170 } 0171 0172 Q_DECLARE_METATYPE(Wikidata::Q) 0173 Q_DECLARE_METATYPE(Wikidata::P) 0174 0175 template <typename T, char Prefix> 0176 inline QDebug operator<<(QDebug debug, Wikidata::Identifier<T, Prefix> id) 0177 { 0178 QDebugStateSaver saver(debug); 0179 if (id.isValid()) { 0180 debug.noquote().nospace() << QStringLiteral("https://www.wikidata.org/wiki/") + id.toString(); 0181 } 0182 return debug; 0183 } 0184 0185 #endif // WIKIDATA_ITEM_H