diff options
author | Dominik Holland <dominik.holland@pelagicore.com> | 2019-01-10 14:11:13 +0100 |
---|---|---|
committer | Dominik Holland <dominik.holland@pelagicore.com> | 2019-01-11 12:18:54 +0000 |
commit | 7c191b1eda7f859ebc91d3a841f01ea86b8f0db9 (patch) | |
tree | 935608519781484374940ee19328d675bee18ea1 | |
parent | 278839a14994364f7977f66c1b2bc80f4d9aea49 (diff) |
Show a meaningful error message debug and release libraries mixed
On mac it can easily happen that debug and release libraries are
mixed when building an application. E.g. using one of the qface
examples. In general qtivicore tries to load the correct plugin version
if available, but if the wrong one was loaded or the appropriate one
was not available it can happen that plugin interfaces can't be
casted to the correct types and thus the class doesn't work.
When this happens a more descriptive error message is now shown and
the backend is not used.
Change-Id: I4ae63ac87509ec3feb1ae65750d8e0ee71ad6520
Reviewed-by: Robert Griebl <robert.griebl@pelagicore.com>
-rw-r--r-- | src/ivicore/qiviabstractfeature.cpp | 8 | ||||
-rw-r--r-- | src/ivicore/qiviabstractfeature_p.h | 8 | ||||
-rw-r--r-- | src/ivicore/qiviabstractfeaturelistmodel_p.h | 6 | ||||
-rw-r--r-- | src/ivicore/qiviabstractzonedfeature.cpp | 2 | ||||
-rw-r--r-- | src/ivicore/qivipagingmodel.cpp | 2 | ||||
-rw-r--r-- | src/ivicore/qivisearchandbrowsemodel.cpp | 2 | ||||
-rw-r--r-- | src/ivicore/qiviserviceinterface.cpp | 12 | ||||
-rw-r--r-- | src/ivicore/qiviserviceinterface.h | 19 | ||||
-rw-r--r-- | src/ivimedia/qiviamfmtuner.cpp | 2 | ||||
-rw-r--r-- | src/ivimedia/qivimediadevicediscoverymodel.cpp | 2 | ||||
-rw-r--r-- | src/ivimedia/qivimediaindexercontrol.cpp | 2 | ||||
-rw-r--r-- | src/ivimedia/qivimediaplayer.cpp | 2 | ||||
-rw-r--r-- | src/tools/ivigenerator/templates_frontend/interface.cpp.tpl | 4 | ||||
-rw-r--r-- | src/tools/ivigenerator/templates_test/tst_test.cpp.tpl | 5 |
14 files changed, 63 insertions, 13 deletions
diff --git a/src/ivicore/qiviabstractfeature.cpp b/src/ivicore/qiviabstractfeature.cpp index 6c90516..ee2be9c 100644 --- a/src/ivicore/qiviabstractfeature.cpp +++ b/src/ivicore/qiviabstractfeature.cpp @@ -312,8 +312,12 @@ bool QIviAbstractFeature::setServiceObject(QIviServiceObject *so) if (so) { connectToServiceObject(d->m_serviceObject); - if (!d->m_isConnected) - qWarning("The QIviServiceObject got accepted but QIviAbstractFeature::connectToServiceObject wasn't called"); + if (!d->m_isConnected) { + qCritical() << this << + "accepted the given QIviServiceObject, but didn't connect to it completely" + ", as QIviAbstractFeature::connectToServiceObject wasn't called."; + return false; + } connect(so, &QObject::destroyed, this, &QIviAbstractFeature::serviceObjectDestroyed); } diff --git a/src/ivicore/qiviabstractfeature_p.h b/src/ivicore/qiviabstractfeature_p.h index 59e912b..633681f 100644 --- a/src/ivicore/qiviabstractfeature_p.h +++ b/src/ivicore/qiviabstractfeature_p.h @@ -59,6 +59,7 @@ #include "qiviabstractfeature.h" #include "qivifeatureinterface.h" +#include "qiviserviceobject.h" QT_BEGIN_NAMESPACE @@ -85,6 +86,13 @@ public: virtual bool notify(const QByteArray &propertyName, const QVariant &value); QIviFeatureInterface *backend() const; + template <class T> T backend() const + { + Q_Q(const QIviAbstractFeature); + if (m_serviceObject) + return m_serviceObject->interfaceInstance<T>(q->interfaceName()); + return nullptr; + } void setDiscoveryResult(QIviAbstractFeature::DiscoveryResult discoveryResult); void onInitializationDone(); diff --git a/src/ivicore/qiviabstractfeaturelistmodel_p.h b/src/ivicore/qiviabstractfeaturelistmodel_p.h index 5adb88c..ea09a91 100644 --- a/src/ivicore/qiviabstractfeaturelistmodel_p.h +++ b/src/ivicore/qiviabstractfeaturelistmodel_p.h @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE -class QIviHelperFeature : public QIviAbstractFeature +class Q_QTIVICORE_EXPORT QIviHelperFeature : public QIviAbstractFeature { Q_OBJECT @@ -95,6 +95,10 @@ public: virtual void initialize(); QIviFeatureInterface *backend() const; + template <class T> T backend() const + { + return m_feature->iviPrivate()->backend<T>(); + } Q_DISABLE_COPY(QIviAbstractFeatureListModelPrivate) diff --git a/src/ivicore/qiviabstractzonedfeature.cpp b/src/ivicore/qiviabstractzonedfeature.cpp index f583ed3..5d7c0c4 100644 --- a/src/ivicore/qiviabstractzonedfeature.cpp +++ b/src/ivicore/qiviabstractzonedfeature.cpp @@ -144,7 +144,7 @@ QIviZonedFeatureInterface *QIviAbstractZonedFeature::backend(const QString &inte if (auto *parentFeature = qobject_cast<QIviAbstractZonedFeature*>(parent())) return parentFeature->backend(); else if (QIviServiceObject *so = serviceObject()) - return qobject_cast<QIviZonedFeatureInterface*>(so->interfaceInstance(iface)); + return so->interfaceInstance<QIviZonedFeatureInterface*>(iface); return nullptr; } diff --git a/src/ivicore/qivipagingmodel.cpp b/src/ivicore/qivipagingmodel.cpp index 30ae7f9..b5dd312 100644 --- a/src/ivicore/qivipagingmodel.cpp +++ b/src/ivicore/qivipagingmodel.cpp @@ -252,7 +252,7 @@ const QIviStandardItem *QIviPagingModelPrivate::itemAt(int i) const QIviPagingModelInterface *QIviPagingModelPrivate::backend() const { - return qobject_cast<QIviPagingModelInterface*>(QIviAbstractFeatureListModelPrivate::backend()); + return QIviAbstractFeatureListModelPrivate::backend<QIviPagingModelInterface*>(); } /*! diff --git a/src/ivicore/qivisearchandbrowsemodel.cpp b/src/ivicore/qivisearchandbrowsemodel.cpp index 5ce2ca9..c9e70b4 100644 --- a/src/ivicore/qivisearchandbrowsemodel.cpp +++ b/src/ivicore/qivisearchandbrowsemodel.cpp @@ -174,7 +174,7 @@ void QIviSearchAndBrowseModelPrivate::setAvailableContenTypes(const QStringList QIviSearchAndBrowseModelInterface *QIviSearchAndBrowseModelPrivate::searchBackend() const { - return qobject_cast<QIviSearchAndBrowseModelInterface*>(QIviPagingModelPrivate::backend()); + return QIviAbstractFeatureListModelPrivate::backend<QIviSearchAndBrowseModelInterface*>(); } void QIviSearchAndBrowseModelPrivate::updateContentType(const QString &contentType) diff --git a/src/ivicore/qiviserviceinterface.cpp b/src/ivicore/qiviserviceinterface.cpp index 6ae9ea5..5cd24a4 100644 --- a/src/ivicore/qiviserviceinterface.cpp +++ b/src/ivicore/qiviserviceinterface.cpp @@ -44,6 +44,18 @@ QT_BEGIN_NAMESPACE +/*! + \fn template <class T> T qivi_interface_cast(QObject *backend) + \relates QIviServiceInterface + + Casts the given \a backend to the interface type T. + + When implementing a QtIvi Feature this function should be used, as it shows a meaningful error + message when the cast fails. + + \sa qobject_cast +*/ + QIviServiceInterface::~QIviServiceInterface() { } diff --git a/src/ivicore/qiviserviceinterface.h b/src/ivicore/qiviserviceinterface.h index fe811ff..98e43f6 100644 --- a/src/ivicore/qiviserviceinterface.h +++ b/src/ivicore/qiviserviceinterface.h @@ -50,6 +50,20 @@ QT_BEGIN_NAMESPACE +template <class T> T qivi_interface_cast(QObject *backend) +{ + T inst = qobject_cast<T>(backend); + static bool showOnce = true; + if (!inst && showOnce) { + typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType; + qCritical("Casting the backend to the interface %s failed.\n" + "Either the backend pointer is not of the correct type or casting failed because " + "debug and release libraries were mixed.", ObjType::staticMetaObject.className()); + showOnce = false; + } + return inst; +} + class Q_QTIVICORE_EXPORT QIviServiceInterface { public: @@ -57,6 +71,11 @@ public: virtual QStringList interfaces() const = 0; virtual QIviFeatureInterface *interfaceInstance(const QString &interface) const = 0; + + template <class T> T interfaceInstance(const QString &interface) const { + T inst = qivi_interface_cast<T>(interfaceInstance(interface)); + return inst; + } }; #define QIviServiceInterface_iid "org.qt-project.qtivi.QIviServiceInterface/1.0" diff --git a/src/ivimedia/qiviamfmtuner.cpp b/src/ivimedia/qiviamfmtuner.cpp index a0da253..9590dfd 100644 --- a/src/ivimedia/qiviamfmtuner.cpp +++ b/src/ivimedia/qiviamfmtuner.cpp @@ -148,7 +148,7 @@ void QIviAmFmTunerPrivate::onScanStatusChanged(bool scanRunning) QIviAmFmTunerBackendInterface *QIviAmFmTunerPrivate::tunerBackend() const { - return qobject_cast<QIviAmFmTunerBackendInterface*>(backend()); + return backend<QIviAmFmTunerBackendInterface*>(); } /*! diff --git a/src/ivimedia/qivimediadevicediscoverymodel.cpp b/src/ivimedia/qivimediadevicediscoverymodel.cpp index 6efd360..410e583 100644 --- a/src/ivimedia/qivimediadevicediscoverymodel.cpp +++ b/src/ivimedia/qivimediadevicediscoverymodel.cpp @@ -125,7 +125,7 @@ void QIviMediaDeviceDiscoveryModelPrivate::onDeviceRemoved(QIviServiceObject *de QIviMediaDeviceDiscoveryModelBackendInterface *QIviMediaDeviceDiscoveryModelPrivate::discoveryBackend() const { - return qobject_cast<QIviMediaDeviceDiscoveryModelBackendInterface*>(backend()); + return backend<QIviMediaDeviceDiscoveryModelBackendInterface*>(); } /*! diff --git a/src/ivimedia/qivimediaindexercontrol.cpp b/src/ivimedia/qivimediaindexercontrol.cpp index cdbefff..004de33 100644 --- a/src/ivimedia/qivimediaindexercontrol.cpp +++ b/src/ivimedia/qivimediaindexercontrol.cpp @@ -84,7 +84,7 @@ void QIviMediaIndexerControlPrivate::onStateChanged(QIviMediaIndexerControl::Sta QIviMediaIndexerControlBackendInterface *QIviMediaIndexerControlPrivate::indexerBackend() const { - return qobject_cast<QIviMediaIndexerControlBackendInterface*>(backend()); + return backend<QIviMediaIndexerControlBackendInterface*>(); } /*! diff --git a/src/ivimedia/qivimediaplayer.cpp b/src/ivimedia/qivimediaplayer.cpp index 4460569..8d78246 100644 --- a/src/ivimedia/qivimediaplayer.cpp +++ b/src/ivimedia/qivimediaplayer.cpp @@ -162,7 +162,7 @@ void QIviMediaPlayerPrivate::onMutedChanged(bool muted) QIviMediaPlayerBackendInterface *QIviMediaPlayerPrivate::playerBackend() const { - return qobject_cast<QIviMediaPlayerBackendInterface*>(backend()); + return backend<QIviMediaPlayerBackendInterface*>(); } /*! diff --git a/src/tools/ivigenerator/templates_frontend/interface.cpp.tpl b/src/tools/ivigenerator/templates_frontend/interface.cpp.tpl index 5f4c904..7cddae5 100644 --- a/src/tools/ivigenerator/templates_frontend/interface.cpp.tpl +++ b/src/tools/ivigenerator/templates_frontend/interface.cpp.tpl @@ -446,14 +446,14 @@ void {{class}}::clearServiceObject() /*! \internal */ {{class}}BackendInterface *{{class}}::{{interface|lower}}Backend() const { - return qobject_cast<{{class}}BackendInterface*>(backend()); + return qivi_interface_cast<{{class}}BackendInterface*>(backend()); } {% else %} /*! \internal */ {{class}}BackendInterface *{{class}}::{{interface|lower}}Backend() const { if (QIviServiceObject *so = serviceObject()) - return qobject_cast<{{class}}BackendInterface*>(so->interfaceInstance(interfaceName())); + return so->interfaceInstance<{{class}}BackendInterface*>(interfaceName()); return nullptr; } {% endif %} diff --git a/src/tools/ivigenerator/templates_test/tst_test.cpp.tpl b/src/tools/ivigenerator/templates_test/tst_test.cpp.tpl index 6660ead..194e3ee 100644 --- a/src/tools/ivigenerator/templates_test/tst_test.cpp.tpl +++ b/src/tools/ivigenerator/templates_test/tst_test.cpp.tpl @@ -306,7 +306,10 @@ void {{interface}}Test::testInvalidBackend() {{interface}}InvalidServiceObject *service = new {{interface}}InvalidServiceObject(); manager->registerService(service, service->interfaces()); {{interface}} cc; - QTest::ignoreMessage(QtWarningMsg, "The QIviServiceObject got accepted but QIviAbstractFeature::connectToServiceObject wasn't called"); + QTest::ignoreMessage(QtCriticalMsg, QRegularExpression(".*accepted the given QIviServiceObject, " + "but didn't connect to it completely, as " + "QIviAbstractFeature::connectToServiceObject " + "wasn't called.")); cc.startAutoDiscovery(); // Running without a backend means that changes do not propagate |