KItinerary

icaldocumentprocessor.cpp
1/*
2 SPDX-FileCopyrightText: 2020-2021 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "icaldocumentprocessor.h"
8#include "logging.h"
9#include "stringutil.h"
10
11#include <KItinerary/Event>
12#include <KItinerary/ExtractorDocumentNodeFactory>
13#include <KItinerary/ExtractorEngine>
14#include <KItinerary/ExtractorFilter>
15#include <KItinerary/ExtractorResult>
16#include <KItinerary/Place>
17
18#include <KCalendarCore/ICalFormat>
19#include <KCalendarCore/MemoryCalendar>
20
21#include <QJSEngine>
22#include <QJSValue>
23#include <QJsonArray>
24#include <QJsonDocument>
25#include <QMetaProperty>
26#include <QTimeZone>
27
28#include <cstring>
29
30using namespace KItinerary;
31
32bool IcalCalendarProcessor::canHandleData(const QByteArray &encodedData, QStringView fileName) const
33{
34 return StringUtil::startsWithIgnoreSpace(encodedData, "BEGIN:VCALENDAR") ||
37}
38
40{
43 if (format.fromRawString(calendar, encodedData)) {
44 calendar->setProductId(format.loadedProductId());
46 node.setContent(calendar);
47 return node;
48 } else {
49 qCDebug(Log) << "Failed to parse iCal content.";
50 }
51 return {};
52}
53
55{
56 const auto cal = node.content<KCalendarCore::Calendar::Ptr>();
57 for (const auto &event : cal->events()) {
58 auto child = engine->documentNodeFactory()->createNode(QVariant::fromValue(event), u"internal/event");
59 node.appendChild(child);
60 }
61}
62
63
65{
66 const auto event = node.content<KCalendarCore::Event::Ptr>();
67 return matchesGadget(filter, event.data());
68}
69
71{
72 const auto event = node.content<KCalendarCore::Event::Ptr>();
73 const auto appleStructuredData = event->nonKDECustomProperty("X-APPLE-STRUCTURED-DATA");
74 if (!appleStructuredData.isEmpty()) {
75 auto child = engine->documentNodeFactory()->createNode(QByteArray::fromBase64(appleStructuredData.toLatin1()));
76 node.appendChild(child);
77 }
78}
79
80void IcalEventProcessor::preExtract(ExtractorDocumentNode &node, [[maybe_unused]] const ExtractorEngine *engine) const
81{
82 const auto event = node.content<KCalendarCore::Event::Ptr>();
83 const auto data = event->customProperty("KITINERARY", "RESERVATION");
84 if (!data.isEmpty()) {
85 node.addResult(QJsonDocument::fromJson(data.toUtf8()).array());
86 }
87
88 if (!node.result().isEmpty() || event->recurs() || event->hasRecurrenceId()) {
89 return;
90 }
91
92 Event e;
93 e.setName(event->summary());
94 e.setDescription(event->description());
95 e.setUrl(event->url());
96
97 if (event->allDay()) {
98 e.setStartDate(QDateTime(event->dtStart().date(), {0, 0}, QTimeZone::LocalTime));
99 e.setEndDate(QDateTime(event->dtEnd().date(), {23, 59, 59}, QTimeZone::LocalTime));
100 } else {
101 e.setStartDate(event->dtStart());
102 e.setEndDate(event->dtEnd());
103 }
104
105 Place venue;
106 venue.setName(event->location()); // TODO attempt to detect addresses in here
107 if (event->hasGeo()) {
108 venue.setGeo({event->geoLatitude(), event->geoLongitude()});
109 }
110 e.setLocation(venue);
111
112 // TODO attachments?
113
115}
116
118{
119 if ((engine->hints() & ExtractorEngine::ExtractGenericIcalEvents) || node.result().size() != 1 || !node.usedExtractor().isEmpty()) {
120 return;
121 }
122
123 // remove the generic result again that we added above if no extractor script touched it
124 if (JsonLd::isA<Event>(node.result().result().at(0))) {
125 node.setResult({});
126 }
127}
128
bool fromRawString(const Calendar::Ptr &calendar, const QByteArray &string) override
An event.
Definition event.h:21
ExtractorDocumentNode createNode(const QByteArray &data, QStringView fileName={}, QStringView mimeType={}) const
Create a new document node from data.
A node in the extracted document object tree.
QJsonArray result
Result access for QJSEngine.
void setResult(ExtractorResult &&result)
Replace the existing results by result.
void appendChild(ExtractorDocumentNode &child)
Add another child node.
QJSValue content
The decoded content of this node.
void addResult(ExtractorResult &&result)
Add additional results from an extraction step.
QString usedExtractor() const
Extractor used for the result of this node, if any.
void setContent(const QVariant &content)
Set decoded content.
Semantic data extraction engine.
@ ExtractGenericIcalEvents
generate Event objects for generic ical events.
Hints hints() const
The currently set extraction hints.
const ExtractorDocumentNodeFactory * documentNodeFactory() const
Factory for creating new document nodes.
Determines whether an extractor is applicable to a given email.
ExtractorDocumentNode createNodeFromData(const QByteArray &encodedData) const override
Create a document node from raw data.
bool canHandleData(const QByteArray &encodedData, QStringView fileName) const override
Fast check whether the given encoded data can possibly be processed by this instance.
void expandNode(ExtractorDocumentNode &node, const ExtractorEngine *engine) const override
Create child nodes for node, as far as that's necessary for this document type.
void expandNode(ExtractorDocumentNode &node, const ExtractorEngine *engine) const override
Create child nodes for node, as far as that's necessary for this document type.
bool matches(const ExtractorFilter &filter, const ExtractorDocumentNode &node) const override
Checks whether the given filter matches node.
void preExtract(ExtractorDocumentNode &node, const ExtractorEngine *engine) const override
Called before extractors are applied to node.
void postExtract(ExtractorDocumentNode &node, const ExtractorEngine *engine) const override
Called after extractors have been applied to node.
QJSValue contentToScriptValue(const ExtractorDocumentNode &node, QJSEngine *engine) const override
Create a QJSValue for the node content.
Base class for places.
Definition place.h:69
bool canConvert(const QVariant &value)
Checks if the given value can be up-cast to T.
Definition datatypes.h:31
bool startsWithIgnoreSpace(const QByteArray &data, const char *pattern)
Same as QByteArray::startsWith, but ignoring leading whitespaces.
Classes for reservation/travel data models, data extraction and data augmentation.
Definition berelement.h:17
QByteArray fromBase64(const QByteArray &base64, Base64Options options)
QJSValue toScriptValue(const T &value)
QJsonValue at(qsizetype i) const const
bool isEmpty() const const
qsizetype size() const const
QJsonArray array() const const
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
T * data() const const
bool isEmpty() const const
bool endsWith(QChar ch) const const
CaseInsensitive
QTimeZone systemTimeZone()
QVariant fromValue(T &&value)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:49 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.