File indexing completed on 2024-12-29 04:49:58

0001 /*
0002     SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "extractordocumentprocessor.h"
0008 #include "extractorfilter.h"
0009 #include "extractorresult.h"
0010 #include "logging.h"
0011 
0012 #include <QJSEngine>
0013 #include <QJSValue>
0014 #include <QMetaProperty>
0015 
0016 using namespace KItinerary;
0017 
0018 ExtractorDocumentProcessor::~ExtractorDocumentProcessor() = default;
0019 
0020 bool ExtractorDocumentProcessor::canHandleData([[maybe_unused]] const QByteArray &encodedData, [[maybe_unused]] QStringView fileName) const
0021 {
0022     return false;
0023 }
0024 
0025 ExtractorDocumentNode ExtractorDocumentProcessor::createNodeFromData([[maybe_unused]] const QByteArray &encodedData) const
0026 {
0027     return {};
0028 }
0029 
0030 ExtractorDocumentNode ExtractorDocumentProcessor::createNodeFromContent(const QVariant &decodedData) const
0031 {
0032     ExtractorDocumentNode node;
0033     node.setContent(decodedData);
0034     return node;
0035 }
0036 
0037 void ExtractorDocumentProcessor::expandNode([[maybe_unused]] ExtractorDocumentNode &node, [[maybe_unused]] const ExtractorEngine *engine) const
0038 {
0039 }
0040 
0041 void ExtractorDocumentProcessor::reduceNode(ExtractorDocumentNode &node) const
0042 {
0043     for (const auto &child : node.childNodes()) {
0044         node.addResult(child.result());
0045         if (!child.usedExtractor().isEmpty()) {
0046             node.setUsedExtractor(child.usedExtractor());
0047         }
0048     }
0049 }
0050 
0051 void ExtractorDocumentProcessor::preExtract([[maybe_unused]] ExtractorDocumentNode &node, [[maybe_unused]] const ExtractorEngine *engine) const
0052 {
0053 }
0054 
0055 bool ExtractorDocumentProcessor::matches(const ExtractorFilter &filter, const ExtractorDocumentNode &node) const
0056 {
0057     // QObject content
0058     if (node.content().canConvert<QObject*>()) {
0059         const auto obj = node.content().value<QObject*>();
0060         if (!obj) {
0061             return false;
0062         }
0063         const auto value = obj->property(filter.fieldName().toUtf8().constData());
0064         return filter.matches(value.toString());
0065     }
0066 
0067     // Q_GADGET content
0068     const auto mo = QMetaType(node.content().userType()).metaObject();
0069     return matchesGadget(filter, mo, node.content().constData());
0070 }
0071 
0072 static bool matchesGadgetInternal(const ExtractorFilter &filter, QStringView propName, const QMetaObject *mo, const void *obj)
0073 {
0074     if (!mo) {
0075         return false;
0076     }
0077 
0078     const auto propNameIdx = propName.indexOf(QLatin1Char('.'));
0079     if (propNameIdx == 0 || propName.isEmpty()) {
0080         qCWarning(Log) << "invalid gadget property name:" << propName << filter.fieldName();
0081         return false;
0082     }
0083 
0084     const auto propIdx = mo->indexOfProperty(propName.left(propNameIdx < 0 ? propName.size() : propNameIdx).toUtf8().constData());
0085     if (propIdx < 0) {
0086         return false;
0087     }
0088     const auto prop = mo->property(propIdx);
0089     const auto value = prop.readOnGadget(obj);
0090 
0091     if (propNameIdx > 0) { // recursive matching
0092         const auto mo = QMetaType(value.userType()).metaObject();
0093         return matchesGadgetInternal(filter, propName.mid(propNameIdx + 1), mo, value.constData());
0094     }
0095     return filter.matches(value.toString());
0096 }
0097 
0098 bool ExtractorDocumentProcessor::matchesGadget(const ExtractorFilter &filter, const QMetaObject *mo, const void *obj)
0099 {
0100     return matchesGadgetInternal(filter, filter.fieldName(), mo, obj);
0101 }
0102 
0103 void ExtractorDocumentProcessor::postExtract([[maybe_unused]] ExtractorDocumentNode &node, [[maybe_unused]] const ExtractorEngine *engine) const
0104 {
0105 }
0106 
0107 QJSValue ExtractorDocumentProcessor::contentToScriptValue([[maybe_unused]] const ExtractorDocumentNode &node, QJSEngine *engine) const
0108 {
0109     return engine->toScriptValue(node.content());
0110 }
0111 
0112 void ExtractorDocumentProcessor::destroyNode([[maybe_unused]] ExtractorDocumentNode &node) const
0113 {
0114 }
0115 
0116 #include "moc_extractordocumentprocessor.cpp"