[neon/backports-jammy/packagekit-qt/Neon/unstable] /: New upstream version 1.1.0

Matthias Klumpp null at kde.org
Wed Mar 15 04:29:33 GMT 2023


Git commit 57bd57396d4e28060bd4a257b3530baf7d7f0e2a by Matthias Klumpp.
Committed on 01/12/2022 at 19:54.
Pushed by carlosdem into branch 'Neon/unstable'.

New upstream version 1.1.0

A  +22   -0    .github/workflows/main.yml
M  +4    -2    CMakeLists.txt
M  +19   -0    NEWS
M  +1    -1    README.md
M  +15   -10   src/CMakeLists.txt
M  +68   -0    src/daemon.cpp
M  +2    -2    src/daemonprivate.cpp
M  +6    -6    src/modules/CMakeLists.txt
M  +2    -2    src/modules/packagekit-qt-config.cmake.in
M  +16   -2    src/offline.cpp
M  +2    -1    src/offline.h
M  +2    -1    src/offline_p.h
A  +11   -0    src/packagekitqt6.pc.in
M  +10   -1    src/transaction.cpp
M  +4    -0    src/transaction.h
M  +46   -14   src/transactionprivate.cpp
M  +23   -0    src/transactionprivate.h
A  +18   -0    tests/ci/Dockerfile-debian
A  +8    -0    tests/ci/Dockerfile-fedora
A  +14   -0    tests/ci/build_and_test.sh

https://invent.kde.org/neon/backports-jammy/packagekit-qt/commit/57bd57396d4e28060bd4a257b3530baf7d7f0e2a

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 0000000..790ae2e
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,22 @@
+name: Build and Test
+
+on: [push, pull_request]
+
+jobs:
+  build_and_test:
+    runs-on: ubuntu-latest
+
+    strategy:
+      matrix:
+        distro:
+          - fedora
+          - debian
+      fail-fast: false
+
+    steps:
+      - uses: actions/checkout at v2
+      - run: docker build -t packagekitqt-${{ matrix.distro }} -f tests/ci/Dockerfile-${{ matrix.distro }} .
+      - run: docker run -t -v `pwd`:/build packagekitqt-${{ matrix.distro }} ./tests/ci/build_and_test.sh
+        if: ${{ matrix.distro == 'fedora' }}
+      - run: docker run -t -v `pwd`:/build packagekitqt-${{ matrix.distro }} ./tests/ci/build_and_test.sh
+        if: ${{ matrix.distro == 'debian' }}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 08787de..091d0bf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ if (POLICY CMP0063)
   cmake_policy(SET CMP0063 NEW)
 endif()
 
-project(packagekit-qt VERSION 1.0.2)
+project(packagekit-qt VERSION 1.0.3)
 
 # Used to set installation paths
 set(CMAKE_AUTOMOC ON)
@@ -19,6 +19,8 @@ include(GNUInstallDirs)
 
 set(QPACKAGEKIT_API_LEVEL "1")
 
+find_package(QT NAMES Qt6 Qt5 NO_MODULE REQUIRED COMPONENTS Core DBus)
+
 add_definitions(
     -DQT_NO_KEYWORDS
     -DQT_NO_CAST_TO_ASCII
@@ -53,7 +55,7 @@ set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
 set (GETTEXT_PACKAGE "packagekit")
 set (VERSION "${QPACKAGEKIT_VERSION}")
 set (LOCALSTATEDIR "/var")
-set (CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/packagekitqt5/")
+set (CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/packagekitqt${QT_VERSION_MAJOR}/")
 
 add_definitions("-DLOCALSTATEDIR=\"${LOCALSTATEDIR}\"")
 set (CMAKE_CXX_STANDARD 11)
diff --git a/NEWS b/NEWS
index 21a43da..be91108 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,22 @@
+Version 1.1.0
+~~~~~~~~~~~~~
+Released: 2022-12-01
+
+Notes:
+ - Make PackageKit-Qt depend on Qt 5.10 (Aleix Pol)
+
+Features:
+ - Add build system support for Qt6 (Nicolas Fella)
+ - Add support for plural signals (Aleix Pol)
+ - Add initial GitHub Actions CI (Neal Gompa)
+
+Bugfixes:
+ - Prefer invoking methods by pointer rather than by name (Aleix Pol)
+ - Emit error if transaction is already done before watcher setup (#28) (Aleix Pol)
+ - offline: Address issues with dbus connections (Aleix Pol)
+ - Add the missing pkgconfig file for Qt 6 builds (Christophe Giboudeaux)
+ - Replace 404 Link by working one in README (Max Buchholz)
+
 Version 1.0.2
 ~~~~~~~~~~~~~
 Released: 2020-02-20
diff --git a/README.md b/README.md
index 0e93f18..338f13f 100644
--- a/README.md
+++ b/README.md
@@ -5,4 +5,4 @@ Qt bindings for PackageKit
 PackageKit is a DBUS abstraction layer that allows the session user to manage
 packages in a secure way using a cross-distro, cross-architecture API.
 
-For more information, please see http://www.packagekit.org
+For more information, please see https://www.freedesktop.org/software/PackageKit/
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 096ebd7..6e523b8 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,6 +1,6 @@
 # CMakeLists for PackageKit-Qt library
 
-find_package(Qt5 5.6 REQUIRED COMPONENTS Core DBus)
+find_package(Qt${QT_VERSION_MAJOR} 5.10 REQUIRED COMPONENTS Core DBus)
 
 set(packagekitqt_HEADERS
     Daemon
@@ -40,25 +40,30 @@ endif ()
 set_source_files_properties(${PK_INTERFACE_XML} PROPERTIES NO_NAMESPACE true)
 set_source_files_properties(${PK_TRANSACTION_INTERFACE_XML} PROPERTIES NO_NAMESPACE true)
 
+if(${QT_VERSION_MAJOR} EQUAL 6)
+qt6_add_dbus_interface(packagekitqt_SRC ${PK_INTERFACE_XML} daemonproxy)
+qt6_add_dbus_interface(packagekitqt_SRC ${PK_TRANSACTION_INTERFACE_XML} transactionproxy)
+else()
 qt5_add_dbus_interface(packagekitqt_SRC ${PK_INTERFACE_XML} daemonproxy)
 qt5_add_dbus_interface(packagekitqt_SRC ${PK_TRANSACTION_INTERFACE_XML} transactionproxy)
+endif()
 
-add_library(packagekitqt5 ${packagekitqt_SRC} ${packagekitqt_HEADERS} ${packagekitqt_HEADERS_PRIVATE})
-set_target_properties(packagekitqt5 PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${QPACKAGEKIT_API_LEVEL})
+add_library(packagekitqt${QT_VERSION_MAJOR} ${packagekitqt_SRC} ${packagekitqt_HEADERS} ${packagekitqt_HEADERS_PRIVATE})
+set_target_properties(packagekitqt${QT_VERSION_MAJOR} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${QPACKAGEKIT_API_LEVEL})
 
-target_link_libraries(packagekitqt5 PUBLIC Qt5::DBus)
+target_link_libraries(packagekitqt${QT_VERSION_MAJOR} PUBLIC Qt${QT_VERSION_MAJOR}::DBus)
 
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/packagekitqt5.pc.in
-  ${CMAKE_CURRENT_BINARY_DIR}/packagekitqt5.pc
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/packagekitqt${QT_VERSION_MAJOR}.pc.in
+  ${CMAKE_CURRENT_BINARY_DIR}/packagekitqt${QT_VERSION_MAJOR}.pc
   @ONLY
 )
-target_include_directories(packagekitqt5 INTERFACE "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/packagekitqt5/PackageKit/;${CMAKE_INSTALL_INCLUDEDIR}/packagekitqt5>")
-install(TARGETS packagekitqt5 EXPORT PackageKitQtTargets DESTINATION ${CMAKE_INSTALL_LIBDIR})
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/packagekitqt5.pc
+target_include_directories(packagekitqt${QT_VERSION_MAJOR} INTERFACE "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/packagekitqt${QT_VERSION_MAJOR}/PackageKit/;${CMAKE_INSTALL_INCLUDEDIR}/packagekitqt${QT_VERSION_MAJOR}>")
+install(TARGETS packagekitqt${QT_VERSION_MAJOR} EXPORT PackageKitQtTargets DESTINATION ${CMAKE_INSTALL_LIBDIR})
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/packagekitqt${QT_VERSION_MAJOR}.pc
 	DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
 )
 install(FILES ${packagekitqt_HEADERS}
-        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/packagekitqt5/PackageKit/
+        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/packagekitqt${QT_VERSION_MAJOR}/PackageKit/
 )
 
 add_subdirectory(modules)
diff --git a/src/daemon.cpp b/src/daemon.cpp
index 8d9eed9..0cb921e 100644
--- a/src/daemon.cpp
+++ b/src/daemon.cpp
@@ -29,6 +29,69 @@
 Q_LOGGING_CATEGORY(PACKAGEKITQT_DAEMON, "packagekitqt.daemon")
 Q_LOGGING_CATEGORY(PACKAGEKITQT_OFFLINE, "packagekitqt.offline")
 
+Q_DECLARE_METATYPE(PackageKit::PkPackage);
+Q_DECLARE_METATYPE(QList<PackageKit::PkPackage>);
+Q_DECLARE_METATYPE(PackageKit::PkDetail);
+Q_DECLARE_METATYPE(QList<PackageKit::PkDetail>);
+
+const QDBusArgument &operator<<(QDBusArgument &argument, const PackageKit::PkPackage &pkg)
+{
+    argument.beginStructure();
+    argument << pkg.info;
+    argument << pkg.pid;
+    argument << pkg.summary;
+    argument.endStructure();
+    return argument;
+}
+
+const QDBusArgument &operator>>(const QDBusArgument &argument, PackageKit::PkPackage &pkg)
+{
+    argument.beginStructure();
+    argument >> pkg.info;
+    argument >> pkg.pid;
+    argument >> pkg.summary;
+    argument.endStructure();
+    return argument;
+}
+
+const QDBusArgument &operator>>(const QDBusArgument &argument, PackageKit::PkDetail &detail)
+{
+    argument.beginStructure();
+    argument >> detail.package_id;
+    argument >> detail.updates;
+    argument >> detail.obsoletes;
+    argument >> detail.vendor_urls;
+    argument >> detail.bugzilla_urls;
+    argument >> detail.cve_urls;
+    argument >> detail.restart;
+    argument >> detail.update_text;
+    argument >> detail.changelog;
+    argument >> detail.state;
+    argument >> detail.issued;
+    argument >> detail.updated;
+    argument.endStructure();
+    return argument;
+}
+
+const QDBusArgument &operator<<(QDBusArgument &argument, const PackageKit::PkDetail &detail)
+{
+    argument.beginStructure();
+    argument << detail.package_id;
+    argument << detail.updates;
+    argument << detail.obsoletes;
+    argument << detail.vendor_urls;
+    argument << detail.bugzilla_urls;
+    argument << detail.cve_urls;
+    argument << detail.restart;
+    argument << detail.update_text;
+    argument << detail.changelog;
+    argument << detail.state;
+    argument << detail.issued;
+    argument << detail.updated;
+    argument.endStructure();
+    return argument;
+}
+
 using namespace PackageKit;
 
 Daemon* Daemon::m_global = nullptr;
@@ -58,6 +121,11 @@ Daemon::Daemon(QObject *parent) :
                                          QLatin1String("PropertiesChanged"),
                                          this,
                                          SLOT(propertiesChanged(QString,QVariantMap,QStringList)));
+
+    qDBusRegisterMetaType<PackageKit::PkPackage>();
+    qDBusRegisterMetaType<QList<PackageKit::PkPackage>>();
+    qDBusRegisterMetaType<PackageKit::PkDetail>();
+    qDBusRegisterMetaType<QList<PackageKit::PkDetail>>();
 }
 
 void DaemonPrivate::setupSignal(const QMetaMethod &signal)
diff --git a/src/daemonprivate.cpp b/src/daemonprivate.cpp
index e423916..829ba22 100644
--- a/src/daemonprivate.cpp
+++ b/src/daemonprivate.cpp
@@ -92,7 +92,7 @@ void DaemonPrivate::getAllProperties()
     message << PK_OFFLINE_INTERFACE;
     QDBusConnection::systemBus().callWithCallback(message,
                                                   offline,
-                                                  SLOT(updateProperties(QVariantMap)));
+                                                  SLOT(initializeProperties(QVariantMap)));
 }
 
 void DaemonPrivate::propertiesChanged(const QString &interface, const QVariantMap &properties, const QStringList &invalidatedProperties)
@@ -102,7 +102,7 @@ void DaemonPrivate::propertiesChanged(const QString &interface, const QVariantMa
     if (interface == PK_NAME) {
         updateProperties(properties);
     } else if (interface == PK_OFFLINE_INTERFACE) {
-        offline->d_ptr->updateProperties(properties);
+        offline->d_ptr->updateProperties(interface, properties, invalidatedProperties);
     } else {
         qCWarning(PACKAGEKITQT_DAEMON) << "Unknown PackageKit interface:" << interface;
     }
diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt
index 9ff1b46..74221d0 100644
--- a/src/modules/CMakeLists.txt
+++ b/src/modules/CMakeLists.txt
@@ -2,13 +2,13 @@ include(CMakePackageConfigHelpers)
 
 configure_package_config_file(
   ${CMAKE_CURRENT_SOURCE_DIR}/packagekit-qt-config.cmake.in
-  ${CMAKE_CURRENT_BINARY_DIR}/packagekitqt5-config.cmake
-  INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/packagekitqt5/
+  ${CMAKE_CURRENT_BINARY_DIR}/packagekitqt${QT_VERSION_MAJOR}-config.cmake
+  INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/packagekitqt${QT_VERSION_MAJOR}/
 )
 
-write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/packagekitqt5-config-version.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion)
+write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/packagekitqt${QT_VERSION_MAJOR}-config-version.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion)
 
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/packagekitqt5-config.cmake
-        ${CMAKE_CURRENT_BINARY_DIR}/packagekitqt5-config-version.cmake
-        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/packagekitqt5/
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/packagekitqt${QT_VERSION_MAJOR}-config.cmake
+        ${CMAKE_CURRENT_BINARY_DIR}/packagekitqt${QT_VERSION_MAJOR}-config-version.cmake
+        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/packagekitqt${QT_VERSION_MAJOR}/
 )
diff --git a/src/modules/packagekit-qt-config.cmake.in b/src/modules/packagekit-qt-config.cmake.in
index 6dc5f24..7a55fa2 100644
--- a/src/modules/packagekit-qt-config.cmake.in
+++ b/src/modules/packagekit-qt-config.cmake.in
@@ -1,7 +1,7 @@
 @PACKAGE_INIT@
 
-check_required_components(Qt5DBus)
+check_required_components(Qt at QT_VERSION_MAJOR@DBus)
 
-SET(PackageKitQt5_LIBRARIES "PK::packagekitqt5")
+SET(PackageKitQt at QT_VERSION_MAJOR@_LIBRARIES "PK::packagekitqt at QT_VERSION_MAJOR@")
 
 include("${CMAKE_CURRENT_LIST_DIR}/PackageKitQtTargets.cmake")
diff --git a/src/offline.cpp b/src/offline.cpp
index 15a5218..01d0986 100644
--- a/src/offline.cpp
+++ b/src/offline.cpp
@@ -31,7 +31,7 @@ Offline::Offline(QObject *parent) : QObject(parent)
                                          DBUS_PROPERTIES,
                                          QLatin1String("PropertiesChanged"),
                                          this,
-                                         SLOT(propertiesChanged(QString,QVariantMap,QStringList)));
+                                         SLOT(updateProperties(QString,QVariantMap,QStringList)));
 }
 
 Offline::~Offline()
@@ -145,7 +145,7 @@ void Offline::getPrepared()
     });
 }
 
-void OfflinePrivate::updateProperties(const QVariantMap &properties)
+void OfflinePrivate::initializeProperties(const QVariantMap &properties)
 {
     Q_Q(Offline);
 
@@ -184,4 +184,18 @@ void OfflinePrivate::updateProperties(const QVariantMap &properties)
     }
 }
 
+void OfflinePrivate::updateProperties(const QString &interface, const QVariantMap &properties, const QStringList &invalidate)
+{
+    if(interface != PK_OFFLINE_INTERFACE) {
+        qCWarning(PACKAGEKITQT_OFFLINE) << "Cannot process" << interface << "as" << PK_OFFLINE_INTERFACE;
+        return;
+    }
+
+    if (!invalidate.isEmpty()) {
+        qCWarning(PACKAGEKITQT_OFFLINE) << "Properties could not be invalidated" << interface << invalidate;
+    }
+
+    initializeProperties(properties);
+}
+
 #include "moc_offline.cpp"
diff --git a/src/offline.h b/src/offline.h
index d6d3755..acf788a 100644
--- a/src/offline.h
+++ b/src/offline.h
@@ -132,7 +132,8 @@ protected:
     explicit Offline(QObject *parent = nullptr);
 
 private:
-    Q_PRIVATE_SLOT(d_func(), void updateProperties(QVariantMap))
+    Q_PRIVATE_SLOT(d_func(), void initializeProperties(QVariantMap))
+    Q_PRIVATE_SLOT(d_func(), void updateProperties(QString, QVariantMap, QStringList))
 
     OfflinePrivate *d_ptr;
 };
diff --git a/src/offline_p.h b/src/offline_p.h
index ac01cb0..91741cb 100644
--- a/src/offline_p.h
+++ b/src/offline_p.h
@@ -33,7 +33,8 @@ public:
     {
     }
 
-    void updateProperties(const QVariantMap &properties);
+    void initializeProperties(const QVariantMap &properties);
+    void updateProperties(const QString &interface, const QVariantMap &properties, const QStringList &invalidate);
 
     Offline *q_ptr;
     OrgFreedesktopPackageKitOfflineInterface iface;
diff --git a/src/packagekitqt6.pc.in b/src/packagekitqt6.pc.in
new file mode 100644
index 0000000..4a34881
--- /dev/null
+++ b/src/packagekitqt6.pc.in
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+libdir=@CMAKE_INSTALL_FULL_LIBDIR@
+includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
+
+Name: @LIBNAME@
+Description: PackageKit is a package management abstraction layer.
+Version: @PROJECT_VERSION@
+Requires: Qt6Core, Qt6DBus
+Libs: -L${libdir} -lpackagekitqt6
+Cflags: -I${includedir}/packagekitqt6
diff --git a/src/transaction.cpp b/src/transaction.cpp
index a17b93e..b256daf 100644
--- a/src/transaction.cpp
+++ b/src/transaction.cpp
@@ -119,6 +119,10 @@ void TransactionPrivate::setupSignal(const QMetaMethod &signal)
     } else if (signal == QMetaMethod::fromSignal(&Transaction::package)) {
         signalToConnect = SIGNAL(Package(uint,QString,QString));
         memberToConnect = SLOT(Package(uint,QString,QString));
+
+        if (!p->connection().connect(p->service(), p->path(), p->interface(), QStringLiteral("Packages"), q, SLOT(Packages(QList<PackageKit::PkPackage>)))) {
+            qWarning() << "Failed to connect Packages";
+        }
     } else if (signal == QMetaMethod::fromSignal(&Transaction::repoDetail)) {
         signalToConnect = SIGNAL(RepoDetail(QString,QString,bool));
         memberToConnect = SIGNAL(repoDetail(QString,QString,bool));
@@ -143,10 +147,15 @@ void TransactionPrivate::setupSignal(const QMetaMethod &signal)
     } else if (signal == QMetaMethod::fromSignal(&Transaction::updateDetail)) {
         signalToConnect = SIGNAL(UpdateDetail(QString,QStringList,QStringList,QStringList,QStringList,QStringList,uint,QString,QString,uint,QString,QString));
         memberToConnect = SLOT(UpdateDetail(QString,QStringList,QStringList,QStringList,QStringList,QStringList,uint,QString,QString,uint,QString,QString));
+
+        if (!p->connection().connect(p->service(), p->path(), p->interface(), QStringLiteral("UpdateDetails"), q, SLOT(UpdateDetails(QList<PackageKit::PkDetail>)))) {
+            qWarning() << "Failed to connect UpdateDetails";
+        }
     }
 
     if (signalToConnect && memberToConnect) {
-        QObject::connect(p, signalToConnect, q, memberToConnect);
+        bool b = QObject::connect(p, signalToConnect, q, memberToConnect);
+        Q_ASSERT(b);
     }
 }
 
diff --git a/src/transaction.h b/src/transaction.h
index 6f9e312..6461df5 100644
--- a/src/transaction.h
+++ b/src/transaction.h
@@ -34,6 +34,8 @@
 namespace PackageKit {
 
 class Details;
+struct PkPackage;
+struct PkDetail;
 
 /**
 * \class Transaction transaction.h Transaction
@@ -855,11 +857,13 @@ private:
     Q_PRIVATE_SLOT(d_func(), void mediaChangeRequired(uint mediaType, const QString &mediaId, const QString &mediaText))
     Q_PRIVATE_SLOT(d_func(), void finished(uint exitCode, uint runtime))
     Q_PRIVATE_SLOT(d_func(), void Package(uint info, const QString &pid, const QString &summary))
+    Q_PRIVATE_SLOT(d_func(), void Packages(QList<PackageKit::PkPackage>))
     Q_PRIVATE_SLOT(d_func(), void ItemProgress(const QString &itemID, uint status, uint percentage))
     Q_PRIVATE_SLOT(d_func(), void RepoSignatureRequired(const QString &pid, const QString &repoName, const QString &keyUrl, const QString &keyUserid, const QString &keyId, const QString &keyFingerprint, const QString &keyTimestamp, uint type))
     Q_PRIVATE_SLOT(d_func(), void requireRestart(uint type, const QString &pid))
     Q_PRIVATE_SLOT(d_func(), void transaction(const QDBusObjectPath &oldTid, const QString &timespec, bool succeeded, uint role, uint duration, const QString &data, uint uid, const QString &cmdline))
     Q_PRIVATE_SLOT(d_func(), void UpdateDetail(const QString &package_id, const QStringList &updates, const QStringList &obsoletes, const QStringList &vendor_urls, const QStringList &bugzilla_urls, const QStringList &cve_urls, uint restart, const QString &update_text, const QString &changelog, uint state, const QString &issued, const QString &updated))
+    Q_PRIVATE_SLOT(d_func(), void UpdateDetails(const QList<PackageKit::PkDetail> &dets))
     Q_PRIVATE_SLOT(d_func(), void destroy())
     Q_PRIVATE_SLOT(d_func(), void daemonQuit())
     Q_PRIVATE_SLOT(d_func(), void propertiesChanged(QString,QVariantMap,QStringList))
diff --git a/src/transactionprivate.cpp b/src/transactionprivate.cpp
index 38a4db6..ae0c367 100644
--- a/src/transactionprivate.cpp
+++ b/src/transactionprivate.cpp
@@ -49,9 +49,9 @@ void TransactionPrivate::setup(const QDBusObjectPath &transactionId)
                                                          tid.path(),
                                                          QDBusConnection::systemBus(),
                                                          q);
-    if (!Daemon::global()->hints().isEmpty()) {
-        q->setHints(Daemon::global()->hints());
-    }
+    QStringList hints = Daemon::global()->hints();
+    hints << QStringLiteral("supports-plural-signals=true");
+    q->setHints(hints);
 
     q->connect(p, SIGNAL(Destroy()), SLOT(destroy()));
 
@@ -188,6 +188,11 @@ void TransactionPrivate::runQueuedTransaction()
         break;
     }
 
+    if (reply.isFinished() && reply.isError()) {
+        q->errorCode(Transaction::ErrorInternalError, reply.error().message());
+        finished(Transaction::ExitFailed, 0);
+        return;
+    }
     auto watcher = new QDBusPendingCallWatcher(reply, q);
     q->connect(watcher, &QDBusPendingCallWatcher::finished,
                q, [this, q] (QDBusPendingCallWatcher *call) {
@@ -286,40 +291,40 @@ void TransactionPrivate::updateProperties(const QVariantMap &properties)
         const QVariant &value = it.value();
         if (property == QLatin1String("AllowCancel")) {
             allowCancel = value.toBool();
-            QMetaObject::invokeMethod(q, "allowCancelChanged", Qt::QueuedConnection);
+            QMetaObject::invokeMethod(q, &Transaction::allowCancelChanged, Qt::QueuedConnection);
         } else if (property == QLatin1String("CallerActive")) {
             callerActive = value.toBool();
-            QMetaObject::invokeMethod(q, "isCallerActiveChanged", Qt::QueuedConnection);
+            QMetaObject::invokeMethod(q, &Transaction::isCallerActiveChanged, Qt::QueuedConnection);
         } else if (property == QLatin1String("DownloadSizeRemaining")) {
             downloadSizeRemaining = value.toLongLong();
-            QMetaObject::invokeMethod(q, "downloadSizeRemainingChanged", Qt::QueuedConnection);
+            QMetaObject::invokeMethod(q, &Transaction::downloadSizeRemainingChanged, Qt::QueuedConnection);
         } else if (property == QLatin1String("ElapsedTime")) {
             elapsedTime = value.toUInt();
-            QMetaObject::invokeMethod(q, "elapsedTimeChanged", Qt::QueuedConnection);
+            QMetaObject::invokeMethod(q, &Transaction::elapsedTimeChanged, Qt::QueuedConnection);
         } else if (property == QLatin1String("LastPackage")) {
             lastPackage = value.toString();
-            QMetaObject::invokeMethod(q, "lastPackageChanged", Qt::QueuedConnection);
+            QMetaObject::invokeMethod(q, &Transaction::lastPackageChanged, Qt::QueuedConnection);
         } else if (property == QLatin1String("Percentage")) {
             percentage = value.toUInt();
-            QMetaObject::invokeMethod(q, "percentageChanged", Qt::QueuedConnection);
+            QMetaObject::invokeMethod(q, &Transaction::percentageChanged, Qt::QueuedConnection);
         } else if (property == QLatin1String("RemainingTime")) {
             remainingTime = value.toUInt();
             q->remainingTimeChanged();
         } else if (property == QLatin1String("Role")) {
             role = static_cast<Transaction::Role>(value.toUInt());
-            QMetaObject::invokeMethod(q, "roleChanged", Qt::QueuedConnection);
+            QMetaObject::invokeMethod(q, &Transaction::roleChanged, Qt::QueuedConnection);
         } else if (property == QLatin1String("Speed")) {
             speed = value.toUInt();
-            QMetaObject::invokeMethod(q, "speedChanged", Qt::QueuedConnection);
+            QMetaObject::invokeMethod(q, &Transaction::speedChanged, Qt::QueuedConnection);
         } else if (property == QLatin1String("Status")) {
             status = static_cast<Transaction::Status>(value.toUInt());
-            QMetaObject::invokeMethod(q, "statusChanged", Qt::QueuedConnection);
+            QMetaObject::invokeMethod(q, &Transaction::statusChanged, Qt::QueuedConnection);
         } else if (property == QLatin1String("TransactionFlags")) {
             transactionFlags = static_cast<Transaction::TransactionFlags>(value.toUInt());
-            QMetaObject::invokeMethod(q, "transactionFlagsChanged", Qt::QueuedConnection);
+            QMetaObject::invokeMethod(q, &Transaction::transactionFlagsChanged, Qt::QueuedConnection);
         } else if (property == QLatin1String("Uid")) {
             uid = value.toUInt();
-            QMetaObject::invokeMethod(q, "uidChanged", Qt::QueuedConnection);
+            QMetaObject::invokeMethod(q, &Transaction::uidChanged, Qt::QueuedConnection);
         } else {
             qCWarning(PACKAGEKITQT_TRANSACTION) << "Unknown Transaction property:" << property << value;
         }
@@ -336,6 +341,14 @@ void TransactionPrivate::Package(uint info, const QString &pid, const QString &s
                summary);
 }
 
+void TransactionPrivate::Packages(const QList<PackageKit::PkPackage> &pkgs)
+{
+    Q_Q(Transaction);
+    for (PkPackage const &pkg : pkgs) {
+        q->package(static_cast<Transaction::Info>(pkg.info), pkg.pid, pkg.summary);
+    }
+}
+
 void TransactionPrivate::ItemProgress(const QString &itemID, uint status, uint percentage)
 {
     Q_Q(Transaction);
@@ -424,3 +437,22 @@ void TransactionPrivate::UpdateDetail(const QString &package_id,
                     QDateTime::fromString(issued, Qt::ISODate),
                     QDateTime::fromString(updated, Qt::ISODate));
 }
+
+void TransactionPrivate::UpdateDetails(const QList<PkDetail> &details)
+{
+    Q_Q(Transaction);
+    for (const PkDetail &detail : details) {
+        q->updateDetail(detail.package_id,
+                        detail.updates,
+                        detail.obsoletes,
+                        detail.vendor_urls,
+                        detail.bugzilla_urls,
+                        detail.cve_urls,
+                        static_cast<PackageKit::Transaction::Restart>(detail.restart),
+                        detail.update_text,
+                        detail.changelog,
+                        static_cast<PackageKit::Transaction::UpdateState>(detail.state),
+                        QDateTime::fromString(detail.issued, Qt::ISODate),
+                        QDateTime::fromString(detail.updated, Qt::ISODate));
+    }
+}
diff --git a/src/transactionprivate.h b/src/transactionprivate.h
index 1cc77c7..ee5daac 100644
--- a/src/transactionprivate.h
+++ b/src/transactionprivate.h
@@ -32,6 +32,27 @@
 
 namespace PackageKit {
 
+struct PkPackage {
+    uint info;
+    QString pid;
+    QString summary;
+};
+
+struct PkDetail {
+    QString package_id;
+    QStringList updates;
+    QStringList obsoletes;
+    QStringList vendor_urls;
+    QStringList bugzilla_urls;
+    QStringList cve_urls;
+    uint restart;
+    QString update_text;
+    QString changelog;
+    uint state;
+    QString issued;
+    QString updated;
+};
+
 class TransactionPrivate
 {
     Q_DECLARE_PUBLIC(Transaction)
@@ -103,6 +124,7 @@ protected Q_SLOTS:
     void mediaChangeRequired(uint mediaType, const QString &mediaId, const QString &mediaText);
     void finished(uint exitCode, uint runtime);
     void Package(uint info, const QString &pid, const QString &summary);
+    void Packages(const QList<PackageKit::PkPackage> &packages);
     void ItemProgress(const QString &itemID, uint status, uint percentage);
     void RepoSignatureRequired(const QString &pid,
                                const QString &repoName,
@@ -115,6 +137,7 @@ protected Q_SLOTS:
     void requireRestart(uint type, const QString &pid);
     void transaction(const QDBusObjectPath &oldTid, const QString &timespec, bool succeeded, uint role, uint duration, const QString &data, uint uid, const QString &cmdline);
     void UpdateDetail(const QString &package_id, const QStringList &updates, const QStringList &obsoletes, const QStringList &vendor_urls, const QStringList &bugzilla_urls, const QStringList &cve_urls, uint restart, const QString &update_text, const QString &changelog, uint state, const QString &issued, const QString &updated);
+    void UpdateDetails(const QList<PackageKit::PkDetail> &details);
     void destroy();
     void daemonQuit();
     void propertiesChanged(const QString &interface, const QVariantMap &properties, const QStringList &invalidatedProperties);
diff --git a/tests/ci/Dockerfile-debian b/tests/ci/Dockerfile-debian
new file mode 100644
index 0000000..bcb3b66
--- /dev/null
+++ b/tests/ci/Dockerfile-debian
@@ -0,0 +1,18 @@
+FROM debian:bullseye
+
+# allow fetching source packages
+RUN echo "deb-src http://deb.debian.org/debian/ bullseye main" >> /etc/apt/sources.list
+
+# prepare
+RUN apt-get update -qq
+
+# install build essentials
+RUN apt-get install -yq build-essential
+
+# install PackageKit-Qt dependencies
+RUN apt-get build-dep -yq packagekit-qt
+RUN apt-get install -yq cmake ninja-build
+
+# finish
+RUN mkdir /build
+WORKDIR /build
diff --git a/tests/ci/Dockerfile-fedora b/tests/ci/Dockerfile-fedora
new file mode 100644
index 0000000..3d5b942
--- /dev/null
+++ b/tests/ci/Dockerfile-fedora
@@ -0,0 +1,8 @@
+FROM fedora:31
+
+RUN dnf -y update
+RUN dnf -y install dnf-plugins-core libdnf-devel redhat-rpm-config cmake gcc-c++ ninja-build
+RUN dnf -y builddep PackageKit-Qt
+
+RUN mkdir /build
+WORKDIR /build
diff --git a/tests/ci/build_and_test.sh b/tests/ci/build_and_test.sh
new file mode 100755
index 0000000..d127de7
--- /dev/null
+++ b/tests/ci/build_and_test.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+set -e
+
+if [ -d "build" ]; then
+  rm build -rf
+fi
+cmake -S . -B build -GNinja -DMAINTAINER=1 $@
+
+# Build, Test & Install
+cmake --build build
+## No tests yet
+#cd build && ctest && cd -
+
+DESTDIR=/tmp/install_root/ cmake --install build



More information about the Neon-commits mailing list