QPermission: replace T data<T>() with std::optional<T> value<T>()
As discussed in API review, the default-constructed T() returned from a mismatched data<T>() call is indistinguishable from a real T with default state. To make them distinguishable, return optional<T>. Call the new function value<T>(), mimicking QVariant::value<T>(), and suggested in API review, because data() is usually used to return raw pointers, not values. Remove the qWarning() on requestedType and actualType mismatch, as the new function can be used in std::get_if/dynamic_cast-like if-then-else chains, in which failure is part of the normal operation, and a warning message misplaced: if (auto loc = perm.value<QLocationPermission>()) ~~~ use *loc ~~~ else if (auto con = perm.value<QContactsPermission>()) ~~~ use *con ~~~ ~~~ etc ~~~ Pick-to: 6.5 Change-Id: I799a58e930307323ebce8f9ac50a42455e9c017f Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
parent
36619181fb
commit
ce104cac50
@ -211,8 +211,8 @@ Q_LOGGING_CATEGORY(lcPermissions, "qt.permissions", QtWarningMsg);
|
||||
{
|
||||
if (permission.status() != Qt::PermissionStatus:Granted)
|
||||
return;
|
||||
auto locationPermission = permission.data<QLocationPermission>();
|
||||
if (locationPermission.accuracy() != QLocationPermission::Precise)
|
||||
auto locationPermission = permission.value<QLocationPermission>();
|
||||
if (!locationPermission || locationPermission->accuracy() != QLocationPermission::Precise)
|
||||
return;
|
||||
updatePreciseLocation();
|
||||
}
|
||||
@ -243,13 +243,12 @@ Q_LOGGING_CATEGORY(lcPermissions, "qt.permissions", QtWarningMsg);
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn template <typename T, if_permission<T>> T QPermission::data() const
|
||||
\fn template <typename T, if_permission<T>> std::optional<T> QPermission::value() const
|
||||
|
||||
Returns the \l{typed permission} of type \c T.
|
||||
Returns the \l{typed permission} of type \c T, or \c{std::nullopt} if this
|
||||
QPermission object doesn't contain one.
|
||||
|
||||
If the type doesn't match the type that was originally used to request the
|
||||
permission, returns a default-constructed \c T. Use type() for dynamically
|
||||
choosing which typed permission to request.
|
||||
Use type() for dynamically choosing which typed permission to request.
|
||||
|
||||
This function participates in overload resolution only if \c T is one of
|
||||
the \l{typed permission} classes:
|
||||
@ -273,11 +272,8 @@ Q_LOGGING_CATEGORY(lcPermissions, "qt.permissions", QtWarningMsg);
|
||||
const void *QPermission::data(QMetaType requestedType) const
|
||||
{
|
||||
const auto actualType = type();
|
||||
if (requestedType != actualType) {
|
||||
qCWarning(lcPermissions, "Cannot convert from %s to %s",
|
||||
actualType.name(), requestedType.name());
|
||||
if (requestedType != actualType)
|
||||
return nullptr;
|
||||
}
|
||||
return m_data.data();
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include <QtCore/qtypeinfo.h>
|
||||
#include <QtCore/qmetatype.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
#if !defined(Q_QDOC)
|
||||
QT_REQUIRE_CONFIG(permissions);
|
||||
#endif
|
||||
@ -52,12 +54,11 @@ public:
|
||||
QMetaType type() const { return m_data.metaType(); }
|
||||
|
||||
template <typename T, if_permission<T> = true>
|
||||
T data() const
|
||||
std::optional<T> value() const
|
||||
{
|
||||
if (auto p = data(QMetaType::fromType<T>()))
|
||||
return *static_cast<const T *>(p);
|
||||
else
|
||||
return T{};
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
|
@ -53,7 +53,7 @@ static QStringList nativeStringsFromPermission(const QPermission &permission)
|
||||
{
|
||||
const auto id = permission.type().id();
|
||||
if (id == qMetaTypeId<QLocationPermission>()) {
|
||||
return nativeLocationPermission(permission.data<QLocationPermission>());
|
||||
return nativeLocationPermission(*permission.value<QLocationPermission>());
|
||||
} else if (id == qMetaTypeId<QCameraPermission>()) {
|
||||
return { u"android.permission.CAMERA"_s };
|
||||
} else if (id == qMetaTypeId<QMicrophonePermission>()) {
|
||||
@ -63,12 +63,12 @@ static QStringList nativeStringsFromPermission(const QPermission &permission)
|
||||
return { u"android.permission.BLUETOOTH"_s };
|
||||
} else if (id == qMetaTypeId<QContactsPermission>()) {
|
||||
const auto readContactsString = u"android.permission.READ_CONTACTS"_s;
|
||||
if (!permission.data<QContactsPermission>().isReadWrite())
|
||||
if (!permission.value<QContactsPermission>()->isReadWrite())
|
||||
return { readContactsString };
|
||||
return { readContactsString, u"android.permission.WRITE_CONTACTS"_s };
|
||||
} else if (id == qMetaTypeId<QCalendarPermission>()) {
|
||||
const auto readContactsString = u"android.permission.READ_CALENDAR"_s;
|
||||
if (!permission.data<QCalendarPermission>().isReadWrite())
|
||||
if (!permission.value<QCalendarPermission>()->isReadWrite())
|
||||
return { readContactsString };
|
||||
return { readContactsString, u"android.permission.WRITE_CALENDAR"_s };
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ namespace
|
||||
Q_ASSERT(!geolocation.isNull());
|
||||
|
||||
const auto &permission = geolocationRequestQueue->front().first;
|
||||
const auto &locationPermission = permission.data<QLocationPermission>();
|
||||
const auto locationPermission = *permission.value<QLocationPermission>();
|
||||
const bool highAccuracy = locationPermission.accuracy() == QLocationPermission::Precise;
|
||||
|
||||
val options = val::object();
|
||||
|
@ -55,7 +55,7 @@ struct PermissionRequest
|
||||
|
||||
- (Qt::PermissionStatus)checkPermission:(QPermission)permission
|
||||
{
|
||||
const auto locationPermission = permission.data<QLocationPermission>();
|
||||
const auto locationPermission = *permission.value<QLocationPermission>();
|
||||
|
||||
auto status = [self authorizationStatus:locationPermission];
|
||||
if (status != Qt::PermissionStatus::Granted)
|
||||
@ -118,7 +118,7 @@ struct PermissionRequest
|
||||
- (QStringList)usageDescriptionsFor:(QPermission)permission
|
||||
{
|
||||
QStringList usageDescriptions = { "NSLocationWhenInUseUsageDescription" };
|
||||
const auto locationPermission = permission.data<QLocationPermission>();
|
||||
const auto locationPermission = *permission.value<QLocationPermission>();
|
||||
if (locationPermission.availability() == QLocationPermission::Always)
|
||||
usageDescriptions << "NSLocationAlwaysUsageDescription";
|
||||
return usageDescriptions;
|
||||
@ -150,7 +150,7 @@ struct PermissionRequest
|
||||
self.manager.delegate = self;
|
||||
}
|
||||
|
||||
const auto locationPermission = permission.data<QLocationPermission>();
|
||||
const auto locationPermission = *permission.value<QLocationPermission>();
|
||||
switch (locationPermission.availability()) {
|
||||
case QLocationPermission::WhenInUse:
|
||||
// The documentation specifies that requestWhenInUseAuthorization can
|
||||
|
@ -54,11 +54,12 @@ void tst_QPermission::converting_impl() const
|
||||
QCOMPARE_EQ(p.type(), metaType);
|
||||
}
|
||||
|
||||
// data<>() compiles:
|
||||
// value<>() compiles:
|
||||
{
|
||||
const QPermission p = concrete;
|
||||
[[maybe_unused]] auto r = p.data<T>();
|
||||
static_assert(std::is_same_v<decltype(r), T>);
|
||||
auto v = p.value<T>();
|
||||
static_assert(std::is_same_v<decltype(v), std::optional<T>>);
|
||||
QCOMPARE_NE(v, std::nullopt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,35 +101,43 @@ void tst_QPermission::conversionMaintainsState() const
|
||||
|
||||
{
|
||||
p = dummy;
|
||||
auto r = p.data<DummyPermission>();
|
||||
auto v = p.value<DummyPermission>();
|
||||
QCOMPARE_NE(v, std::nullopt);
|
||||
auto &r = *v;
|
||||
QCOMPARE_EQ(r.state, dummy.state);
|
||||
// check mismatched returns default-constructed value:
|
||||
QCOMPARE_EQ(p.data<QCalendarPermission>().isReadWrite(), cal_default.isReadWrite());
|
||||
// check mismatched returns nullopt:
|
||||
QCOMPARE_EQ(p.value<QCalendarPermission>(), std::nullopt);
|
||||
}
|
||||
|
||||
{
|
||||
p = loc;
|
||||
auto r = p.data<QLocationPermission>();
|
||||
auto v = p.value<QLocationPermission>();
|
||||
QCOMPARE_NE(v, std::nullopt);
|
||||
auto &r = *v;
|
||||
QCOMPARE_EQ(r.accuracy(), loc.accuracy());
|
||||
QCOMPARE_EQ(r.availability(), loc.availability());
|
||||
// check mismatched returns default-constructed value:
|
||||
QCOMPARE_EQ(p.data<DummyPermission>().state, dummy_default.state);
|
||||
// check mismatched returns nullopt:
|
||||
QCOMPARE_EQ(p.value<DummyPermission>(), std::nullopt);
|
||||
}
|
||||
|
||||
{
|
||||
p = con;
|
||||
auto r = p.data<QContactsPermission>();
|
||||
auto v = p.value<QContactsPermission>();
|
||||
QCOMPARE_NE(v, std::nullopt);
|
||||
auto &r = *v;
|
||||
QCOMPARE_EQ(r.isReadWrite(), con.isReadWrite());
|
||||
// check mismatched returns default-constructed value:
|
||||
QCOMPARE_EQ(p.data<QLocationPermission>().accuracy(), loc_default.accuracy());
|
||||
// check mismatched returns nullopt:
|
||||
QCOMPARE_EQ(p.value<QLocationPermission>(), std::nullopt);
|
||||
}
|
||||
|
||||
{
|
||||
p = cal;
|
||||
auto r = p.data<QCalendarPermission>();
|
||||
auto v = p.value<QCalendarPermission>();
|
||||
QCOMPARE_NE(v, std::nullopt);
|
||||
auto &r = *v;
|
||||
QCOMPARE_EQ(r.isReadWrite(), cal.isReadWrite());
|
||||
// check mismatched returns default-constructed value:
|
||||
QCOMPARE_EQ(p.data<QContactsPermission>().isReadWrite(), con_default.isReadWrite());
|
||||
// check mismatched returns nullopt:
|
||||
QCOMPARE_EQ(p.value<QContactsPermission>(), std::nullopt);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user