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"