File indexing completed on 2025-01-19 12:45:18
0001 /***************************************************************************** 0002 * Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com> * 0003 * * 0004 * This library is free software; you can redistribute it and/or * 0005 * modify it under the terms of the GNU Library General Public * 0006 * License as published by the Free Software Foundation; either * 0007 * version 2 of the License, or (at your option) any later version. * 0008 * * 0009 * This library is distributed in the hope that it will be useful, * 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0012 * Library General Public License for more details. * 0013 * * 0014 * You should have received a copy of the GNU Library General Public License * 0015 * along with this library; see the file COPYING.LIB. If not, write to * 0016 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * 0017 * Boston, MA 02110-1301, USA. * 0018 *****************************************************************************/ 0019 0020 #include <iostream> 0021 0022 #include <k4aboutdata.h> 0023 #include <kcmdlineargs.h> 0024 #include <kfilemetainfo.h> 0025 #include <klocalizedstring.h> 0026 #include <kconfiggroup.h> 0027 0028 #include <QByteArray> 0029 #include <QCoreApplication> 0030 #include <QDataStream> 0031 #include <QHash> 0032 #include <QString> 0033 #include <QTimer> 0034 0035 #define DISABLE_NEPOMUK_LEGACY 0036 #include "config-nepomuk.h" 0037 0038 #include <nepomuk/query/filequery.h> 0039 #include <nepomuk/query/comparisonterm.h> 0040 #include <nepomuk/query/andterm.h> 0041 #include <nepomuk/query/resourceterm.h> 0042 #include <nepomuk/query/resourcetypeterm.h> 0043 #include <nepomuk/query/optionalterm.h> 0044 #include <nepomuk/utils/utils.h> 0045 #include <nepomuk/types/property.h> 0046 #include <nepomuk/core/tag.h> 0047 #include <nepomuk/core/variant.h> 0048 #include <nepomuk/core/resourcemanager.h> 0049 0050 using namespace std; 0051 0052 class KFileMetaDataReaderApplication : public QCoreApplication 0053 { 0054 Q_OBJECT 0055 0056 public: 0057 KFileMetaDataReaderApplication(int &argc, char **argv); 0058 0059 private Q_SLOTS: 0060 void readAndSendMetaData(); 0061 0062 private: 0063 void sendMetaData(const QHash<QUrl, Nepomuk::Variant> &data); 0064 QHash<QUrl, Nepomuk::Variant> readFileMetaData(const QList<QUrl> &urls) const; 0065 QHash<QUrl, Nepomuk::Variant> readFileAndContextMetaData(const QList<QUrl> &urls) const; 0066 }; 0067 0068 KFileMetaDataReaderApplication::KFileMetaDataReaderApplication(int &argc, char **argv) : 0069 QCoreApplication(argc, argv) 0070 { 0071 QTimer::singleShot(0, this, SLOT(readAndSendMetaData())); 0072 } 0073 0074 void KFileMetaDataReaderApplication::readAndSendMetaData() 0075 { 0076 const KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); 0077 0078 QList<QUrl> urls; 0079 for (int i = 0; i < args->count(); ++i) { 0080 urls.append(args->url(i)); 0081 } 0082 0083 QHash<QUrl, Nepomuk::Variant> metaData; 0084 if (args->isSet("file")) { 0085 metaData = readFileMetaData(urls); 0086 } else { 0087 metaData = readFileAndContextMetaData(urls); 0088 } 0089 0090 sendMetaData(metaData); 0091 0092 quit(); 0093 } 0094 0095 void KFileMetaDataReaderApplication::sendMetaData(const QHash<QUrl, Nepomuk::Variant> &data) 0096 { 0097 QByteArray byteArray; 0098 QDataStream out(&byteArray, QIODevice::WriteOnly); 0099 0100 QHashIterator<QUrl, Nepomuk::Variant> it(data); 0101 while (it.hasNext()) { 0102 it.next(); 0103 0104 out << it.key(); 0105 0106 // Unlike QVariant no streaming operators are implemented for Nepomuk::Variant. 0107 // So it is required to manually encode the variant for the stream. 0108 // The decoding counterpart is located in KFileMetaDataReader. 0109 const Nepomuk::Variant &variant = it.value(); 0110 if (variant.isList()) { 0111 out << 0 << variant.toStringList(); 0112 } else if (variant.isResource()) { 0113 out << 1 << variant.toString(); 0114 } else { 0115 out << 2 << variant.variant(); 0116 } 0117 } 0118 0119 cout << byteArray.toBase64().constData(); 0120 } 0121 0122 QHash<QUrl, Nepomuk::Variant> KFileMetaDataReaderApplication::readFileMetaData(const QList<QUrl> &urls) const 0123 { 0124 QHash<QUrl, Nepomuk::Variant> data; 0125 0126 // Currently only the meta-data of one file is supported. 0127 // It might be an option to read all meta-data and show 0128 // ranges for each key. 0129 if (urls.count() == 1) { 0130 const QString path = urls.first().toLocalFile(); 0131 KFileMetaInfo metaInfo(path, QString(), KFileMetaInfo::Fastest); 0132 const QHash<QString, KFileMetaInfoItem> metaInfoItems = metaInfo.items(); 0133 foreach (const KFileMetaInfoItem &metaInfoItem, metaInfoItems) { 0134 const QString uriString = metaInfoItem.name(); 0135 const Nepomuk::Variant value(metaInfoItem.value()); 0136 data.insert(uriString, 0137 Nepomuk::Utils::formatPropertyValue(Nepomuk::Types::Property(), value)); 0138 } 0139 } 0140 0141 return data; 0142 } 0143 0144 QHash<QUrl, Nepomuk::Variant> KFileMetaDataReaderApplication::readFileAndContextMetaData(const QList<QUrl> &urls) const 0145 { 0146 QHash<QUrl, Nepomuk::Variant> metaData; 0147 0148 bool isNepomukIndexerActive = false; 0149 if (Nepomuk::ResourceManager::instance()->initialized()) { 0150 KConfig config("nepomukserverrc"); 0151 isNepomukIndexerActive = config.group("Service-nepomukfileindexer").readEntry("autostart", false); 0152 } else { 0153 // No context meta data can be read without enabled Nepomuk 0154 return readFileMetaData(urls); 0155 } 0156 0157 unsigned int rating = 0; 0158 QString comment; 0159 QList<Nepomuk::Tag> tags; 0160 0161 if (urls.count() == 1) { 0162 // Read the metadata of the file that are provided as properties 0163 // (e.g. image-size, artist, album, ...) 0164 bool useReadFromFileFallback = true; 0165 0166 Nepomuk::Resource file(urls.first()); 0167 if (file.isValid() && !file.resourceUri().isEmpty()) { 0168 QHash<QUrl, Nepomuk::Variant> variants = file.properties(); 0169 QHash<QUrl, Nepomuk::Variant>::const_iterator it = variants.constBegin(); 0170 while (it != variants.constEnd()) { 0171 Nepomuk::Types::Property prop(it.key()); 0172 metaData.insert(prop.uri(), Nepomuk::Utils::formatPropertyValue(prop, it.value(), 0173 QList<Nepomuk::Resource>() << file, 0174 Nepomuk::Utils::WithKioLinks)); 0175 ++it; 0176 } 0177 useReadFromFileFallback = !isNepomukIndexerActive || variants.isEmpty(); 0178 0179 rating = file.rating(); 0180 comment = file.description(); 0181 tags = file.tags(); 0182 } 0183 0184 if (useReadFromFileFallback) { 0185 // No metadata could be received with Nepomuk. Parse the file 0186 // itself as fallback to extract metadata. 0187 metaData = readFileMetaData(QList<QUrl>() << urls.first()); 0188 } 0189 } else { 0190 // Read the data for rating, comment and tags 0191 bool first = true; 0192 foreach (const QUrl &url, urls) { 0193 Nepomuk::Resource file(url); 0194 if (!file.isValid()) { 0195 continue; 0196 } 0197 0198 if (!first && rating != file.rating()) { 0199 rating = 0; // Reset rating 0200 } else if (first) { 0201 rating = file.rating(); 0202 } 0203 0204 if (!first && comment != file.description()) { 0205 comment.clear(); // Reset comment 0206 } else if (first) { 0207 comment = file.description(); 0208 } 0209 0210 if (!first && tags != file.tags()) { 0211 tags.clear(); // Reset tags 0212 } else if (first) { 0213 tags = file.tags(); 0214 } 0215 0216 first = false; 0217 } 0218 } 0219 0220 metaData.insert(QUrl("kfileitem#rating"), rating); 0221 metaData.insert(QUrl("kfileitem#comment"), comment); 0222 0223 QList<Nepomuk::Variant> tagVariants; 0224 foreach (const Nepomuk::Tag &tag, tags) { 0225 tagVariants.append(Nepomuk::Variant(tag)); 0226 } 0227 metaData.insert(QUrl("kfileitem#tags"), tagVariants); 0228 0229 return metaData; 0230 } 0231 0232 int main(int argc, char *argv[]) 0233 { 0234 K4AboutData aboutData("kfilemetadatareader", "kio4", ki18n("KFileMetaDataReader"), 0235 "1.0", 0236 ki18n("KFileMetaDataReader can be used to read metadata from a file"), 0237 K4AboutData::License_GPL, 0238 ki18n("(C) 2011, Peter Penz")); 0239 aboutData.addAuthor(ki18n("Peter Penz"), ki18n("Current maintainer"), "peter.penz19@gmail.com"); 0240 0241 KCmdLineArgs::init(argc, argv, &aboutData); 0242 0243 KCmdLineOptions options; 0244 options.add("file", ki18n("Only the meta data that is part of the file is read")); 0245 options.add("+[arg]", ki18n("List of URLs where the meta-data should be read from")); 0246 0247 KCmdLineArgs::addCmdLineOptions(options); 0248 0249 KFileMetaDataReaderApplication app(argc, argv); 0250 return app.exec(); 0251 } 0252 0253 #include "kfilemetadatareaderprocess.moc"