// 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 #include #include #include #include QT_BEGIN_NAMESPACE using namespace QtJniTypes; QModelIndex QAndroidModelIndexProxy::qInstance(JQtModelIndex jModelIndex) { if (!jModelIndex.isValid()) return QModelIndex(); const QJniArray jPrivateArray = jModelIndex.getField("m_privateData"); const auto privateData = jPrivateArray.toContainer(); Q_ASSERT(privateData.size() == 4); const jlong modelReference = privateData[3]; if (!modelReference) return QModelIndex(); const jint row = privateData[0]; const jint column = privateData[1]; QAbstractItemModel *model = reinterpret_cast(modelReference); QAndroidItemModelProxy *proxyModel = qobject_cast(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("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(modelIndex.model()); if (isModelProxy) return JQtModelIndex(modelIndex.row(), modelIndex.column(), jlong(modelIndex.internalId()), reinterpret_cast(modelIndex.model())); else return JQtModelIndex(modelIndex.row(), modelIndex.column(), QAndroidModelIndexProxy::jInstance(modelIndex.parent()), reinterpret_cast(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::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