From 4bedfd6609c6efe5dc327d305feac8985d4658e3 Mon Sep 17 00:00:00 2001 From: Alexander Stippich Date: Sat, 9 Feb 2019 17:41:46 +0100 Subject: Add string formatting function to property info Summary: Adds the ability to format the metadata value for displaying purposes individually for each property. Currently, users of KFileMetaData must implement their own custom formatting functions. All custom formatting functions from Baloo-Widgets and Dolphin are copied into KFileMetaData. This can be extended later. This adds a dependency on KCoreAddons to KFileMetaData. FEATURE: 398581 Test Plan: tests pass Reviewers: broulik, bruns, mgallien, #frameworks Reviewed By: bruns Subscribers: ngraham, kde-frameworks-devel, #baloo Tags: #frameworks, #baloo Differential Revision: https://phabricator.kde.org/D17245 --- CMakeLists.txt | 5 +++ autotests/propertyinfotest.cpp | 29 ++++++++++++++ autotests/propertyinfotest.h | 1 + src/CMakeLists.txt | 2 + src/formatstrings.cpp | 86 ++++++++++++++++++++++++++++++++++++++++++ src/formatstrings_p.h | 50 ++++++++++++++++++++++++ src/propertyinfo.cpp | 27 +++++++++++++ src/propertyinfo.h | 7 ++++ 8 files changed, 207 insertions(+) create mode 100644 src/formatstrings.cpp create mode 100644 src/formatstrings_p.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fa481a9..7ef0a40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,11 @@ set_package_properties(KF5Archive PROPERTIES DESCRIPTION "KDE Frameworks 5: Arch URL "https://download.kde.org/stable/frameworks/" TYPE OPTIONAL PURPOSE "Archive is needed to build ODF and OOXML 2007 extractors") +find_package(KF5 ${KF5_DEP_VERSION} COMPONENTS CoreAddons) +set_package_properties(KF5CoreAddons PROPERTIES DESCRIPTION "KDE Frameworks 5: Core Addons Framework" + URL "https://download.kde.org/stable/frameworks/" TYPE REQUIRED + PURPOSE "Needed for the formatting of properties for display purposes") + find_package(KF5 ${KF5_DEP_VERSION} REQUIRED COMPONENTS I18n) find_package(Poppler 0.12.1 COMPONENTS Qt5) diff --git a/autotests/propertyinfotest.cpp b/autotests/propertyinfotest.cpp index ae8b1b8..e203dcd 100644 --- a/autotests/propertyinfotest.cpp +++ b/autotests/propertyinfotest.cpp @@ -45,4 +45,33 @@ void PropertyInfoTest::testNameIdMapping() } } +void PropertyInfoTest::testFormatAsDisplayString() +{ + auto emptyProperty = PropertyInfo::fromName(QStringLiteral("no valid property name")); + QCOMPARE(emptyProperty.formatAsDisplayString(QVariant("empty")), QStringLiteral("empty")); + + PropertyInfo year(Property::DiscNumber); + QCOMPARE(year.formatAsDisplayString(QVariant(2018)), QStringLiteral("2018")); + + QStringList artistList = {"Artist1", "Artist2"}; + PropertyInfo artist(Property::Artist); + QCOMPARE(artist.formatAsDisplayString(QVariant(artistList)), QStringLiteral("Artist1, Artist2")); + + QStringList authorList = {"Author1"}; + PropertyInfo author(Property::Author); + QCOMPARE(artist.formatAsDisplayString(QVariant(authorList)), QStringLiteral("Author1")); + + PropertyInfo duration(Property::Duration); + QCOMPARE(duration.formatAsDisplayString(QVariant(1800)), QStringLiteral("0:30:00")); + + PropertyInfo sampleRate(Property::SampleRate); + QCOMPARE(sampleRate.formatAsDisplayString(QVariant(44100)), QString(QLocale().toString(44.1) + QStringLiteral(" kHz"))); + + PropertyInfo bitRate(Property::BitRate); + QCOMPARE(bitRate.formatAsDisplayString(QVariant(128000)), QStringLiteral("128 kB/s")); + + PropertyInfo orientation(Property::ImageOrientation); + QCOMPARE(orientation.formatAsDisplayString(QVariant(5)), QStringLiteral("Transposed")); +} + QTEST_GUILESS_MAIN(PropertyInfoTest) diff --git a/autotests/propertyinfotest.h b/autotests/propertyinfotest.h index 677ade1..15e6a10 100644 --- a/autotests/propertyinfotest.h +++ b/autotests/propertyinfotest.h @@ -30,6 +30,7 @@ class PropertyInfoTest : public QObject Q_OBJECT private Q_SLOTS: void testNameIdMapping(); + void testFormatAsDisplayString(); }; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 52fa8e5..c3cbe8c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,6 +13,7 @@ set(KF5FileMetaData_SRCS writerplugin.cpp writercollection.cpp externalwriter.cpp + formatstrings.cpp ) ecm_qt_declare_logging_category(KF5FileMetaData_SRCS HEADER kfilemetadata_debug.h IDENTIFIER KFILEMETADATA_LOG CATEGORY_NAME kf5.kfilemetadata) @@ -34,6 +35,7 @@ target_link_libraries(KF5FileMetaData Qt5::Core PRIVATE KF5::I18n + KF5::CoreAddons ) if(TAGLIB_FOUND) diff --git a/src/formatstrings.cpp b/src/formatstrings.cpp new file mode 100644 index 0000000..b0bfdf8 --- /dev/null +++ b/src/formatstrings.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2018 Alexander Stippich + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "formatstrings_p.h" + +#include +#include + +using namespace KFileMetaData; + +QString FormatStrings::toStringFunction(const QVariant& value) +{ + return value.toString(); +} + +QString FormatStrings::joinStringListFunction(const QVariant& value) +{ + return value.toStringList().join(i18nc("Separation between multiple entries in a list", ", ")); +} + +QString FormatStrings::formatDate(const QVariant& value) +{ + KFormat form; + QDateTime dt; + if (value.type() == QVariant::DateTime) { + dt = value.toDateTime(); + } else { + dt = QDateTime::fromString(value.toString(), Qt::ISODate); + } + if (dt.isValid()) { + return form.formatRelativeDateTime(dt, QLocale::LongFormat); + } + return QString(); +} + +QString FormatStrings::formatDuration(const QVariant& value) +{ + KFormat form; + return form.formatDuration(value.toInt() * 1000); +} + +QString FormatStrings::formatBitRate(const QVariant& value) +{ + KFormat form; + return i18nc("@label bitrate (per second)", "%1/s", form.formatByteSize(value.toInt(), 0, KFormat::MetricBinaryDialect)); +} + +QString FormatStrings::formatSampleRate(const QVariant& value) +{ + return i18nc("@label samplerate in kilohertz", "%1 kHz", QLocale().toString(value.toDouble() / 1000)); +} + +QString FormatStrings::formatOrientationValue(const QVariant& value) +{ + QString string; + switch (value.toInt()) { + case 1: string = i18nc("Description of image orientation", "Unchanged"); break; + case 2: string = i18nc("Description of image orientation", "Horizontally flipped"); break; + case 3: string = i18nc("Description of image orientation", "180° rotated"); break; + case 4: string = i18nc("Description of image orientation", "Vertically flipped"); break; + case 5: string = i18nc("Description of image orientation", "Transposed"); break; + case 6: string = i18nc("Description of image orientation, counter clock-wise rotated", "90° rotated CCW "); break; + case 7: string = i18nc("Description of image orientation", "Transversed"); break; + case 8: string = i18nc("Description of image orientation, counter clock-wise rotated", "270° rotated CCW"); break; + default: + break; + } + return string; +} + diff --git a/src/formatstrings_p.h b/src/formatstrings_p.h new file mode 100644 index 0000000..125c31e --- /dev/null +++ b/src/formatstrings_p.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2018 Alexander Stippich + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef KFILEMETADATA_FORMATSTRINGS_P_H +#define KFILEMETADATA_FORMATSTRINGS_P_H + +#include +#include +#include + +namespace KFileMetaData { + +class Q_DECL_HIDDEN FormatStrings +{ +public: + static QString toStringFunction(const QVariant& value); + + static QString joinStringListFunction(const QVariant& value); + + static QString formatDate(const QVariant& value); + + static QString formatDuration(const QVariant& value); + + static QString formatBitRate(const QVariant& value); + + static QString formatSampleRate(const QVariant& value); + + static QString formatOrientationValue(const QVariant& value); + +}; + +} + +#endif diff --git a/src/propertyinfo.cpp b/src/propertyinfo.cpp index 5439a58..56fc596 100644 --- a/src/propertyinfo.cpp +++ b/src/propertyinfo.cpp @@ -24,6 +24,8 @@ #include +#include "formatstrings_p.h" + using namespace KFileMetaData; class Q_DECL_HIDDEN PropertyInfo::Private @@ -34,6 +36,7 @@ public: QString displayName; QVariant::Type valueType; bool shouldBeIndexed; + QString (*formatAsString)(const QVariant& value) = nullptr; }; PropertyInfo::PropertyInfo(Property::Property property) @@ -41,6 +44,7 @@ PropertyInfo::PropertyInfo(Property::Property property) { d->prop = property; d->shouldBeIndexed = true; + d->formatAsString = &FormatStrings::toStringFunction; switch (property) { case Property::Album: @@ -53,12 +57,14 @@ PropertyInfo::PropertyInfo(Property::Property property) d->name = QStringLiteral("albumArtist"); d->displayName = i18nc("@label", "Album Artist"); d->valueType = QVariant::StringList; + d->formatAsString = &FormatStrings::joinStringListFunction; break; case Property::Artist: d->name = QStringLiteral("artist"); d->displayName = i18nc("@label", "Artist"); d->valueType = QVariant::StringList; + d->formatAsString = &FormatStrings::joinStringListFunction; break; case Property::AspectRatio: @@ -71,12 +77,14 @@ PropertyInfo::PropertyInfo(Property::Property property) d->name = QStringLiteral("author"); d->displayName = i18nc("@label", "Author"); d->valueType = QVariant::StringList; + d->formatAsString = &FormatStrings::joinStringListFunction; break; case Property::BitRate: d->name = QStringLiteral("bitRate"); d->displayName = i18nc("@label", "Bitrate"); d->valueType = QVariant::Int; + d->formatAsString = &FormatStrings::formatBitRate; break; case Property::Channels: @@ -117,12 +125,14 @@ PropertyInfo::PropertyInfo(Property::Property property) d->name = QStringLiteral("creationDate"); d->displayName = i18nc("@label", "Creation Date"); d->valueType = QVariant::String; + d->formatAsString = &FormatStrings::formatDate; break; case Property::Duration: d->name = QStringLiteral("duration"); d->displayName = i18nc("@label", "Duration"); d->valueType = QVariant::Int; + d->formatAsString = &FormatStrings::formatDuration; break; case Property::Empty: @@ -147,6 +157,7 @@ PropertyInfo::PropertyInfo(Property::Property property) d->name = QStringLiteral("genre"); d->displayName = i18nc("@label music genre", "Genre"); d->valueType = QVariant::StringList; + d->formatAsString = &FormatStrings::joinStringListFunction; d->shouldBeIndexed = false; break; @@ -160,6 +171,7 @@ PropertyInfo::PropertyInfo(Property::Property property) d->name = QStringLiteral("imageDateTime"); d->displayName = i18nc("@label EXIF", "Image Date Time"); d->valueType = QVariant::DateTime; + d->formatAsString = &FormatStrings::formatDate; break; case Property::ImageMake: @@ -180,12 +192,14 @@ PropertyInfo::PropertyInfo(Property::Property property) d->name = QStringLiteral("imageOrientation"); d->displayName = i18nc("@label EXIF", "Image Orientation"); d->valueType = QVariant::Int; + d->formatAsString = &FormatStrings::formatOrientationValue; break; case Property::Keywords: d->name = QStringLiteral("keywords"); d->displayName = i18nc("@label", "Keywords"); d->valueType = QVariant::StringList; + d->formatAsString = &FormatStrings::joinStringListFunction; d->shouldBeIndexed = false; break; @@ -206,6 +220,7 @@ PropertyInfo::PropertyInfo(Property::Property property) d->name = QStringLiteral("lyricist"); d->displayName = i18nc("@label", "Lyricist"); d->valueType = QVariant::StringList; + d->formatAsString = &FormatStrings::joinStringListFunction; d->shouldBeIndexed = false; break; @@ -225,6 +240,7 @@ PropertyInfo::PropertyInfo(Property::Property property) d->name = QStringLiteral("photoDateTimeOriginal"); d->displayName = i18nc("@label EXIF", "Photo Original Date Time"); d->valueType = QVariant::DateTime; + d->formatAsString = &FormatStrings::formatDate; break; case Property::PhotoExposureBiasValue: @@ -345,6 +361,7 @@ PropertyInfo::PropertyInfo(Property::Property property) d->name = QStringLiteral("sampleRate"); d->displayName = i18nc("@label", "Sample Rate"); d->valueType = QVariant::Int; + d->formatAsString = &FormatStrings::formatSampleRate; break; case Property::Subject: @@ -382,6 +399,7 @@ PropertyInfo::PropertyInfo(Property::Property property) d->name = QStringLiteral("performer"); d->displayName = i18nc("@label", "Performer"); d->valueType = QVariant::StringList; + d->formatAsString = &FormatStrings::joinStringListFunction; break; case Property::Ensemble: @@ -394,12 +412,14 @@ PropertyInfo::PropertyInfo(Property::Property property) d->name = QStringLiteral("arranger"); d->displayName = i18nc("@label", "Arranger"); d->valueType = QVariant::StringList; + d->formatAsString = &FormatStrings::joinStringListFunction; break; case Property::Conductor: d->name = QStringLiteral("conductor"); d->displayName = i18nc("@label", "Conductor"); d->valueType = QVariant::StringList; + d->formatAsString = &FormatStrings::joinStringListFunction; break; case Property::Compilation: @@ -503,6 +523,7 @@ PropertyInfo::PropertyInfo(Property::Property property) d->displayName = i18nc("@label translations last update", "Last Update"); d->valueType = QVariant::String; d->shouldBeIndexed = false; + d->formatAsString = &FormatStrings::formatDate; break; case Property::TranslationTemplateDate: @@ -510,6 +531,7 @@ PropertyInfo::PropertyInfo(Property::Property property) d->displayName = i18nc("@label date of template creation8", "Template Creation"); d->valueType = QVariant::String; d->shouldBeIndexed = false; + d->formatAsString = &FormatStrings::formatDate; break; case Property::OriginUrl: @@ -600,6 +622,11 @@ bool PropertyInfo::shouldBeIndexed() const return d->shouldBeIndexed; } +QString PropertyInfo::formatAsDisplayString(const QVariant &value) const +{ + return (d->formatAsString)(value); +} + PropertyInfo PropertyInfo::fromName(const QString& name) { static QHash propertyHash = { diff --git a/src/propertyinfo.h b/src/propertyinfo.h index c1767c4..3c426e8 100644 --- a/src/propertyinfo.h +++ b/src/propertyinfo.h @@ -85,6 +85,13 @@ public: */ static PropertyInfo fromName(const QString& name); + /** + * Returns the value of the property as a QString with added formatting, + * added units if needed, and translated enums. + * @since 5.56 + */ + QString formatAsDisplayString(const QVariant& value) const; + private: class Private; Private* d; -- cgit v1.1