Commit a13bd443 authored by Kai Uwe Broulik's avatar Kai Uwe Broulik 🍇
Browse files

Add KFileMetadata extractor for PkPass files

Makes the pass' description, company, as well as the underlying
reservation description (e.g. flight number and airports) available
to the file metadata system.
parent 57366ae4
Pipeline #166153 passed with stage
in 1 minute and 22 seconds
......@@ -82,7 +82,7 @@ if (ANDROID)
else()
find_package(Qt5 REQUIRED COMPONENTS Widgets DBus)
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS DBusAddons QQC2DesktopStyle)
find_package(KF5 ${KF5_MIN_VERSION} OPTIONAL_COMPONENTS Solid Crash KIO)
find_package(KF5 ${KF5_MIN_VERSION} OPTIONAL_COMPONENTS Solid Crash FileMetaData KIO)
endif()
if (TARGET KF5::Crash)
set(HAVE_KCRASH TRUE)
......
......@@ -9,6 +9,9 @@ add_subdirectory(kandroidextras)
add_subdirectory(gpx)
add_subdirectory(app)
if (TARGET KF5::FileMetaData)
add_subdirectory(metadataextractor)
endif()
if (TARGET KF5::KIOWidgets)
add_subdirectory(thumbnailer)
endif()
# SPDX-FileCopyrightText: 2022 Kai Uwe Broulik <kde@broulik.de>
# SPDX-License-Identifier: BSD-3-Clause
add_library(kfilemetadata_itineraryextractor MODULE itineraryextractor.cpp)
target_link_libraries(kfilemetadata_itineraryextractor
KF5::FileMetaData
KF5::I18n
Qt::Gui
KPim::Itinerary
KPim::PkPass
)
set_target_properties(kfilemetadata_itineraryextractor PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/kf${QT_MAJOR_VERSION}/kfilemetadata")
install(TARGETS kfilemetadata_itineraryextractor
DESTINATION ${KDE_INSTALL_PLUGINDIR}/kf${QT_MAJOR_VERSION}/kfilemetadata)
/*
SPDX-FileCopyrightText: 2022 Kai Uwe Broulik <kde@broulik.de>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "itineraryextractor.h"
#include <KItinerary/ExtractorEngine>
#include <KItinerary/ExtractorPostprocessor>
#include <KItinerary/Datatypes>
#include <KItinerary/JsonLdDocument>
#include <KItinerary/Event>
#include <KItinerary/Flight>
#include <KItinerary/Reservation>
#include <KPkPass/Pass>
#include <KLocalizedString>
#include <QFileInfo>
#include <QJsonArray>
#include <optional>
using namespace KFileMetaData;
using namespace KItinerary;
ItineraryExtractor::ItineraryExtractor(QObject* parent)
: ExtractorPlugin(parent)
{
}
QStringList ItineraryExtractor::mimetypes() const
{
return QStringList{
QStringLiteral("application/vnd.apple.pkpass")
};
}
void KFileMetaData::ItineraryExtractor::extract(ExtractionResult *result)
{
QFileInfo fi(result->inputUrl());
if (!fi.exists()) {
return;
}
auto contextDt = fi.birthTime();
if (!contextDt.isValid()) {
contextDt = fi.lastModified();
}
const QScopedPointer<KPkPass::Pass> pass(KPkPass::Pass::fromFile(result->inputUrl(), nullptr));
if (pass.isNull()) {
return;
}
result->add(Property::Title, pass->description());
result->add(Property::Author, pass->organizationName());
ExtractorEngine engine;
engine.setContextDate(contextDt);
ExtractorPostprocessor postproc;
postproc.setValidationEnabled(true);
postproc.setContextDate(contextDt);
engine.setContent(QVariant::fromValue(pass.data()), result->inputMimetype());
const auto json = JsonLdDocument::fromJson(engine.extract());
postproc.process(json);
std::optional<Reservation> res;
for (const auto &jsonRes : json) {
if (JsonLd::isA<Event>(jsonRes)) { // promote Event to EventReservation
EventReservation ev;
ev.setReservationFor(jsonRes);
res = ev;
break;
} else if (JsonLd::canConvert<Reservation>(jsonRes)) {
res = JsonLd::convert<Reservation>(jsonRes);
break;
}
}
if (!res) {
return;
}
if (const QString reservationNumber = res->reservationNumber(); !reservationNumber.isEmpty()) {
result->add(Property::Comment, reservationNumber);
}
if (JsonLd::isA<Event>(res->reservationFor())) {
const auto event = res->reservationFor().value<Event>();
// simplified() as some event names have line breaks and other rubbish in them
if (const QString eventName = event.name().simplified(); !eventName.isEmpty()) {
// only if it's not the same as the Title
if (pass->description() != eventName) {
result->add(Property::Subject, eventName);
}
}
} else if (JsonLd::isA<Flight>(res->reservationFor())) {
const auto flight = res->reservationFor().value<Flight>();
result->add(Property::Subject, i18nc("Airline Flightnumber from Airport to Airport on Date",
"%1%2 from %3 to %4 on %5",
flight.airline().iataCode(),
flight.flightNumber(),
flight.departureAirport().iataCode(),
flight.arrivalAirport().iataCode(),
QLocale().toString(flight.departureDay(), QLocale::ShortFormat)));
}
}
/*
SPDX-FileCopyrightText: 2022 Kai Uwe Broulik <kde@broulik.de>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef ITINERARYCREATOR_H
#define ITINERARYCREATOR_H
#include <KFileMetaData/ExtractorPlugin>
namespace KFileMetaData
{
class ItineraryExtractor : public ExtractorPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.kde.kf5.kfilemetadata.ExtractorPlugin"
FILE "itineraryextractor.json")
Q_INTERFACES(KFileMetaData::ExtractorPlugin)
public:
explicit ItineraryExtractor(QObject *parent = nullptr);
public:
void extract(ExtractionResult *result) override;
QStringList mimetypes() const override;
};
}
#endif // ITINERARYCREATOR_H
{
"Name" : "ItineraryExtractor",
"Id" : "org.kde.itineraryextractor",
"MimeTypes" : {
"application/vnd.apple.pkpass": { "Version" : "0.0" }
}
}
SPDX-License-Identifier: CC0-1.0
SPDX-FileCopyrightText: none
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment