diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -6,11 +6,13 @@ TEST_NAME "extractortest" LINK_LIBRARIES Qt5::Test ) -ecm_add_test(filemetadatawidgettest.cpp - TEST_NAME "filemetadatawidgettest" +ecm_add_tests( + filemetadatawidgettest.cpp + filemetadataitemcounttest.cpp LINK_LIBRARIES KF5::KIOCore KF5::KIOWidgets KF5::KIOFileWidgets + KF5::ConfigCore KF5::BalooWidgets KF5::FileMetaData Qt5::Test diff --git a/autotests/filemetadatawidgettest.h b/autotests/filemetadataitemcounttest.h copy from autotests/filemetadatawidgettest.h copy to autotests/filemetadataitemcounttest.h --- a/autotests/filemetadatawidgettest.h +++ b/autotests/filemetadataitemcounttest.h @@ -19,26 +19,23 @@ * along with this program. If not, see . */ -#ifndef FILEMETADATAWIDGETTEST_H -#define FILEMETADATAWIDGETTEST_H +#ifndef FILEMETADATAITEMCOUNTTEST_H +#define FILEMETADATAITEMCOUNTTEST_H #include -class FileMetadataWidgetTest : public QObject +class FileMetadataItemCountTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void init(); void cleanup(); - void shouldSignalOnceWithoutFile(); - void shouldSignalOnceWithEmptyFile(); - void shouldSignalOnceFile(); - void shouldSignalOnceFiles(); - + void testItemCount(); + private: - Baloo::FileMetaDataWidget* m_widget; + Baloo::FileMetaDataWidget* m_widget; }; -#endif // FILEMETADATAWIDGETTEST_H +#endif // FILEMETADATAITEMCOUNTTEST_H diff --git a/autotests/filemetadataitemcounttest.cpp b/autotests/filemetadataitemcounttest.cpp new file mode 100644 --- /dev/null +++ b/autotests/filemetadataitemcounttest.cpp @@ -0,0 +1,80 @@ +/* + * This file is part of the KDE Baloo Project + * Copyright 2018 Michael Heidelbach + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "filemetadataitemcounttest.h" +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +QTEST_MAIN(FileMetadataItemCountTest) + +void FileMetadataItemCountTest::initTestCase() +{ + qRegisterMetaType("KFileItemList"); + + QStandardPaths::setTestModeEnabled(true); + // Ensure show configuration + KConfig config("baloofileinformationrc", KConfig::NoGlobals); + KConfigGroup settings = config.group("Show"); + for (auto k: settings.keyList()) { + settings.writeEntry(k, true); + } +} + +void FileMetadataItemCountTest::init() +{ + m_widget = new Baloo::FileMetaDataWidget; +} + +void FileMetadataItemCountTest::cleanup() +{ + delete m_widget; +} + +void FileMetadataItemCountTest::testItemCount() +{ + int expectedItems = 19; + int widgetsPerItem = 2; + auto propCheck = [this, expectedItems, widgetsPerItem](){ + QList items = m_widget->findChildren(QString(), Qt::FindDirectChildrenOnly); + QCOMPARE(items.count(), expectedItems * widgetsPerItem); + }; + + connect(m_widget, &Baloo::FileMetaDataWidget::metaDataRequestFinished, propCheck); + QSignalSpy spy(m_widget, &Baloo::FileMetaDataWidget::metaDataRequestFinished); + m_widget->setItems(KFileItemList() + << QUrl::fromLocalFile(TESTS_SAMPLE_FILES_PATH + QDir::separator() + QStringLiteral("testtagged.mp3")) + ); + QVERIFY(spy.wait()); +} diff --git a/autotests/filemetadatawidgettest.h b/autotests/filemetadatawidgettest.h --- a/autotests/filemetadatawidgettest.h +++ b/autotests/filemetadatawidgettest.h @@ -36,9 +36,13 @@ void shouldSignalOnceWithEmptyFile(); void shouldSignalOnceFile(); void shouldSignalOnceFiles(); + void shouldShowProperties(); + void shouldShowCommonProperties(); + void shouldShowIntersectedProperties(); private: Baloo::FileMetaDataWidget* m_widget; + bool m_mayTestRating = false; }; #endif // FILEMETADATAWIDGETTEST_H diff --git a/autotests/filemetadatawidgettest.cpp b/autotests/filemetadatawidgettest.cpp --- a/autotests/filemetadatawidgettest.cpp +++ b/autotests/filemetadatawidgettest.cpp @@ -25,14 +25,54 @@ #include #include #include +#include +#include #include #include +#include +#include +#include +#include +#include +#include QTEST_MAIN(FileMetadataWidgetTest) void FileMetadataWidgetTest::initTestCase() { qRegisterMetaType("KFileItemList"); + + QStandardPaths::setTestModeEnabled(true); + // Ensure show configuration + KConfig config("baloofileinformationrc", KConfig::NoGlobals); + KConfigGroup settings = config.group("Show"); + for (auto k: settings.keyList()) { + settings.writeEntry(k, true); + } + + const QString exe = QStandardPaths::findExecutable(QStringLiteral("setfattr")); + + if (exe.isEmpty()) { + return; + } + + const QStringList args = {QStringLiteral("--name=user.baloo.rating") + , QStringLiteral("--value=5") + , QStringLiteral("%1/testtagged.mp3").arg(TESTS_SAMPLE_FILES_PATH) + , QStringLiteral("%1/testtagged.m4a").arg(TESTS_SAMPLE_FILES_PATH)}; + + QProcess process; + process.start(exe, args); + if (!process.waitForFinished(10000)) { + qDebug() << "setfattr timed out"; + return; + } + + if (process.exitStatus() == QProcess::NormalExit) { + m_mayTestRating = true; + } else { + qDebug() << "setfattr err:" << process.readAllStandardError(); + } } void FileMetadataWidgetTest::init() @@ -84,5 +124,105 @@ QVERIFY(spy.wait()); QCOMPARE(spy.count(), 1); QCOMPARE(m_widget->items().count(), 3); +} + +void FileMetadataWidgetTest::shouldShowProperties() +{ + auto propCheck = [this](){ + // simple property + QLabel* value; + value = m_widget->findChild("kfileitem#type"); + QVERIFY2(value, "Type data missing"); + QCOMPARE(value->text(), QLatin1String("MP3 audio")); + + if (m_mayTestRating) { + // editable property + KRatingWidget* rating = m_widget->findChild("rating"); + QVERIFY2(rating, "Rating data missing"); + QCOMPARE(rating->rating(), 5); + } else { + qDebug() << "Skipped 'Rating' test"; + } + // async property + value = m_widget->findChild("albumArtist"); + QCOMPARE(value->text(), QLatin1String("Bill Laswell")); + }; + + connect(m_widget, &Baloo::FileMetaDataWidget::metaDataRequestFinished, propCheck); + QSignalSpy spy(m_widget, &Baloo::FileMetaDataWidget::metaDataRequestFinished); + m_widget->setItems(KFileItemList() + << QUrl::fromLocalFile(TESTS_SAMPLE_FILES_PATH + QDir::separator() + QStringLiteral("testtagged.mp3")) + ); + QVERIFY(spy.wait()); +} + +void FileMetadataWidgetTest::shouldShowCommonProperties() +{ + auto propCheck = [this](){ + // simple property + QLabel* value = m_widget->findChild("kfileitem#type"); + QVERIFY(!value); + + value = m_widget->findChild("kfileitem#totalSize"); + // circumvent i18n formatting + QCOMPARE(value->text().left(3), QLatin1String("153")); + + // editable property + if (m_mayTestRating) { + KRatingWidget* rating = m_widget->findChild("rating"); + QCOMPARE(rating->rating(), 5); + } else { + qDebug() << "Skipped 'Rating' test"; + } + // async property + // FIXME: Make this pass + // QCOMPARE( map->value("Album Artist:"), QLatin1String("Bill Laswell")); + }; + + connect(m_widget, &Baloo::FileMetaDataWidget::metaDataRequestFinished, propCheck); + QSignalSpy spy(m_widget, &Baloo::FileMetaDataWidget::metaDataRequestFinished); + m_widget->setItems(KFileItemList() + << QUrl::fromLocalFile(TESTS_SAMPLE_FILES_PATH + QDir::separator() + QStringLiteral("testtagged.mp3")) + << QUrl::fromLocalFile(TESTS_SAMPLE_FILES_PATH + QDir::separator() + QStringLiteral("testtagged.m4a")) + ); + QVERIFY(spy.wait()); + QCOMPARE(spy.count(), 1); +} + +void FileMetadataWidgetTest::shouldShowIntersectedProperties() +{ + auto propCheck = [this](){ + // simple common property + QLabel* value = m_widget->findChild("kfileitem#type"); + QSKIP("Intersecting Type data is not implemented"); + QVERIFY2(value, "Type data is missing"); + if (value) { + QCOMPARE(value->text(), QLatin1String("MP3 audio")); + } + + value = m_widget->findChild("kfileitem#totalSize"); + // circumvent i18n formatting + QCOMPARE(value->text().left(2), QLatin1String("79")); + + // editable property + if (m_mayTestRating) { + KRatingWidget* rating = m_widget->findChild("rating"); + // FIXME: Should these really pass? It hides rating of 1 file. + // Same for userComment + QVERIFY(rating); + QCOMPARE(rating->rating(), 0); + } else { + qDebug() << "Skipped 'Rating' test"; + } + }; + connect(m_widget, &Baloo::FileMetaDataWidget::metaDataRequestFinished, propCheck); + QSignalSpy spy(m_widget, &Baloo::FileMetaDataWidget::metaDataRequestFinished); + m_widget->setItems(KFileItemList() + << QUrl::fromLocalFile(TESTS_SAMPLE_FILES_PATH + QDir::separator() + QStringLiteral("testtagged.mp3")) + << QUrl::fromLocalFile(TESTS_SAMPLE_FILES_PATH + QDir::separator() + QStringLiteral("test.mp3")) + ); + QVERIFY(spy.wait()); + QCOMPARE(spy.count(), 1); } + diff --git a/src/filemetadatawidget.cpp b/src/filemetadatawidget.cpp --- a/src/filemetadatawidget.cpp +++ b/src/filemetadatawidget.cpp @@ -29,15 +29,15 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace Baloo; @@ -115,61 +115,67 @@ void FileMetaDataWidget::Private::slotLoadingFinished() { + // Clear widget to avoid duplicates + deleteRows(); + for (auto w: q->findChildren(QString(), Qt::FindDirectChildrenOnly)) { + delete w; + } + + // Add widgets slotDataAvailable(); emit q->metaDataRequestFinished(m_provider->items()); } +QLabel* createLabel(const QString &key, QString itemLabel, FileMetaDataWidget* parent) { + itemLabel.append(QLatin1Char(':')); + QLabel* label = new QLabel(itemLabel, parent); + label->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + label->setForegroundRole(parent->foregroundRole()); + label->setFont(parent->font()); + label->setWordWrap(true); + label->setAlignment(Qt::AlignTop | Qt::AlignRight); + label->setObjectName(QStringLiteral("L_%1").arg(key)); + return label; +} + void FileMetaDataWidget::Private::slotDataAvailable() { deleteRows(); - + if (m_gridLayout == 0) { m_gridLayout = new QGridLayout(q); m_gridLayout->setMargin(0); m_gridLayout->setSpacing(q->fontMetrics().height() / 4); - } + } - // Filter the data + // Filter the data by 'baloofileinformationrc' config QVariantMap data = m_filter->filter( m_provider->data() ); m_widgetFactory->setNoLinks( m_provider->realTimeIndexing() ); - // Iterate through all remaining items embed the label - // and the value as new row in the widget int rowIndex = 0; - const QStringList keys = sortedKeys(data); - foreach (const QString& key, keys) { - const QVariant value = data[key]; - QString itemLabel = m_provider->label(key); - itemLabel.append(QLatin1Char(':')); - - // Create label - QLabel* label = new QLabel(itemLabel, q); - label->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); - label->setForegroundRole(q->foregroundRole()); - label->setFont(q->font()); - label->setWordWrap(true); - label->setAlignment(Qt::AlignTop | Qt::AlignRight); + // Iterate through all remaining items. + // Embed the label and the value as new row in the widget + for (const auto key: sortedKeys(data)) { + Row row; + row.label = createLabel(key, m_provider->label(key), q); // Create value-widget - QWidget* valueWidget = m_widgetFactory->createWidget(key, value, q); - - // Add the label and value-widget to grid layout - m_gridLayout->addWidget(label, rowIndex, 0, Qt::AlignRight); + const QVariant value = data[key]; + row.value = m_widgetFactory->createWidget(key, value, q); + row.value->setObjectName(key); + + // Add the label to grid layout const int spacerWidth = QFontMetrics(q->font()).size(Qt::TextSingleLine, " ").width(); m_gridLayout->addItem(new QSpacerItem(spacerWidth, 1), rowIndex, 1); - m_gridLayout->addWidget(valueWidget, rowIndex, 2, Qt::AlignLeft); + m_gridLayout->addWidget(row.label, rowIndex, 0, Qt::AlignRight); + m_gridLayout->addWidget(row.value, rowIndex, 2, Qt::AlignLeft); // Remember the label and value-widget as row - Row row; - row.label = label; - row.value = valueWidget; m_rows.append(row); - ++rowIndex; } q->updateGeometry(); - } void FileMetaDataWidget::Private::slotLinkActivated(const QString& link)