Revision control

Copy as Markdown

// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include <QtCore/private/qandroiditemmodelproxy_p.h>
#include <QtCore/private/qandroidmodelindexproxy_p.h>
#include <QtCore/private/qandroidtypeconverter_p.h>
#include <QtCore/qjniarray.h>
QT_BEGIN_NAMESPACE
using namespace QtJniTypes;
QModelIndex QAndroidModelIndexProxy::qInstance(JQtModelIndex jModelIndex)
{
if (!jModelIndex.isValid())
return QModelIndex();
const QJniArray<jlong> jPrivateArray = jModelIndex.getField<jlong[]>("m_privateData");
const auto privateData = jPrivateArray.toContainer();
// The private data must hold row, column, internalId, and model reference.
Q_ASSERT(privateData.size() == 4);
if (privateData.size() != 4) {
qCritical("QtModelIndex has %lld private data entries, expected 4",
qlonglong(privateData.size()));
return QModelIndex();
}
const jlong modelReference = privateData[3];
if (!modelReference)
return QModelIndex();
const jint row = privateData[0];
const jint column = privateData[1];
QAbstractItemModel *model = reinterpret_cast<QAbstractItemModel *>(modelReference);
QAndroidItemModelProxy *proxyModel = qobject_cast<QAndroidItemModelProxy *>(model);
// If the native model instance is a proxy we have access to the protected function
// createIndex(). Else, if the native instance is not a results Java->Qt proxy, we
// use index() to get the QModelIndex.
if (proxyModel) {
const jint internalId = privateData[2];
return proxyModel->createIndex(row, column, internalId);
} else {
const JQtModelIndex parent = jModelIndex.getField<JQtModelIndex>("m_parent");
if (parent.isValid())
return model->index(row, column, QAndroidModelIndexProxy::qInstance(parent));
}
return QModelIndex();
}
JQtModelIndex QAndroidModelIndexProxy::jInstance(QModelIndex modelIndex)
{
if (!modelIndex.isValid())
return JQtModelIndex();
bool isModelProxy = qobject_cast<const QAndroidItemModelProxy *>(modelIndex.model());
if (isModelProxy)
return JQtModelIndex(modelIndex.row(), modelIndex.column(), jlong(modelIndex.internalId()),
reinterpret_cast<jlong>(modelIndex.model()));
else
return JQtModelIndex(modelIndex.row(), modelIndex.column(),
QAndroidModelIndexProxy::jInstance(modelIndex.parent()),
reinterpret_cast<jlong>(modelIndex.model()));
}
jobject QAndroidModelIndexProxy::data(JNIEnv *env, jobject object, int role)
{
Q_ASSERT(env);
Q_ASSERT(object);
QModelIndex modelIndex = qInstance(object);
if (!modelIndex.isValid())
return nullptr;
return QAndroidTypeConverter::toJavaObject(modelIndex.model()->data(modelIndex, role), env);
}
jlong QAndroidModelIndexProxy::internalId(JNIEnv *env, jobject object)
{
Q_ASSERT(env);
Q_ASSERT(object);
return qInstance(object).internalId();
};
jboolean QAndroidModelIndexProxy::isValid(JNIEnv *env, jobject object)
{
Q_ASSERT(env);
Q_ASSERT(object);
return qInstance(object).isValid();
}
JQtModelIndex QAndroidModelIndexProxy::parent(JNIEnv *env, jobject object)
{
Q_ASSERT(env);
Q_ASSERT(object);
return jInstance(qInstance(object).parent());
};
bool QAndroidModelIndexProxy::registerNatives(QJniEnvironment &env)
{
return env.registerNativeMethods(
Traits<JQtModelIndex>::className(),
{ Q_JNI_NATIVE_SCOPED_METHOD(data, QAndroidModelIndexProxy),
Q_JNI_NATIVE_SCOPED_METHOD(internalId, QAndroidModelIndexProxy),
Q_JNI_NATIVE_SCOPED_METHOD(isValid, QAndroidModelIndexProxy),
Q_JNI_NATIVE_SCOPED_METHOD(parent, QAndroidModelIndexProxy) });
}
QT_END_NAMESPACE