Android: Add setData() and dataChanged() methods to QtAbstractItemModel

Add setData() and dataChanged() methods to add editable model
supoort to the Java QtAbstractItemModel.

This change also enables dynamic changes for classes that
implements this abstract class.

Task-number: QTBUG-129387
Task-number: QTBUG-130249
Task-number: QTBUG-130250
Change-Id: Iffd3751d22b976554b3e022ef71aed66079a3a78
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
Soheil Armin 2024-10-17 09:43:42 +03:00
parent 57361de3a9
commit ab027eb73a
3 changed files with 92 additions and 1 deletions

View File

@ -221,6 +221,48 @@ public abstract class QtAbstractItemModel
{
return (QtModelIndex)jni_sibling(row, column, parent);
}
/**
* Sets the role data for the item at {@code index} to value.
*
* Returns {@code true} if successful; otherwise returns false.
*
* The {@link #dataChanged(QtModelIndex, QtModelIndex, int[])} method should be called
* if the data was successfully set.
*
* The base class implementation returns {@code false}. This method and
* {@link #data(QtModelIndex, int)} must be reimplemented for editable models.
*
* @param index The index of the item
* @param value The data value
* @param role The role
* @return True if successful, otherwise return false.
*/
public boolean setData(QtModelIndex index, Object value, int role) {
return jni_setData(index, value, role);
}
/**
* This method must be called whenever the data in an existing item changes.
*
* If the items have the same parent, the affected ones are inclusively those between
* {@code topLeft} and {@code bottomRight}. If the items do not have the same
* parent, the behavior is undefined.
*
* When reimplementing the {@link #setData(QtModelIndex, Object, int)} method, this method
* must be called explicitly.
*
* The {@code roles} argument specifies which data roles have actually
* been modified. An empty array in the roles argument means that all roles should be
* considered modified. The order of elements in the {@cpde roles} argument does not have any
* relevance.
*
* @param topLeft The top-left index of changed items
* @param bottomRight The bottom-right index of changed items
* @param roles Changed roles; Empty array indicates all roles
* @see #setData(QtModelIndex index, Object value, int role)
*/
public void dataChanged(QtModelIndex topLeft, QtModelIndex bottomRight, int[] roles) {
jni_dataChanged(topLeft, bottomRight, roles);
}
/**
* Begins a column insertion operation.
@ -482,6 +524,9 @@ public abstract class QtAbstractItemModel
private native void jni_endResetModel();
private native Object jni_roleNames();
private native Object jni_sibling(int row, int column, QtModelIndex parent);
private native boolean jni_setData(QtModelIndex index, Object value, int role);
private native void jni_dataChanged(QtModelIndex topLeft, QtModelIndex bottomRight,
int[] roles);
private long m_nativeReference = 0;
private QtAbstractItemModel(long nativeReference) { m_nativeReference = nativeReference; }

View File

@ -121,6 +121,20 @@ QModelIndex QAndroidItemModelProxy::siblingDefault(int row, int column, const QM
return QAbstractItemModel::sibling(row, column, parent);
}
bool QAndroidItemModelProxy::setData(const QModelIndex &index, const QVariant &value, int role)
{
Q_ASSERT(jInstance.isValid());
auto jIndex = QAndroidModelIndexProxy::jInstance(index);
auto jValue = QAndroidTypeConverter::toJavaObject(value, QJniEnvironment::getJniEnv());
return jInstance.callMethod<jboolean>("setData", jIndex, jValue, role);
}
bool QAndroidItemModelProxy::setDataDefault(const QModelIndex &index, const QVariant &value,
int role)
{
return QAbstractItemModel::setData(index, value, role);
}
Q_REQUIRED_RESULT QAbstractItemModel *
QAndroidItemModelProxy::nativeInstance(JQtAbstractItemModel itemModel)
{
@ -345,6 +359,26 @@ jobject QAndroidItemModelProxy::jni_sibling(JNIEnv *env, jobject object, jint ro
return env->NewLocalRef(QAndroidModelIndexProxy::jInstance(index).object());
}
jboolean QAndroidItemModelProxy::jni_setData(JNIEnv *env, jobject object, JQtModelIndex index,
jobject &value, jint role)
{
const QModelIndex nativeIndex = QAndroidModelIndexProxy::qInstance(index);
const QVariant qValue = QAndroidTypeConverter::toQVariant(QJniObject(value));
return invokeNativeImpl(env, object, &QAndroidItemModelProxy::setDataDefault,
&QAbstractItemModel::setData, nativeIndex, qValue, role);
}
void QAndroidItemModelProxy::jni_dataChanged(JNIEnv *env, jobject object, JQtModelIndex topLeft,
JQtModelIndex bottomRight, QJniArray<jint> roles)
{
const QModelIndex nativeTopLeft = QAndroidModelIndexProxy::qInstance(topLeft);
const QModelIndex nativeBottomRight = QAndroidModelIndexProxy::qInstance(bottomRight);
const QList<int> nativeRoles = roles.toContainer();
invokeNativeImpl(env, object, &QAndroidItemModelProxy::dataChanged,
&QAbstractItemModel::dataChanged, nativeTopLeft, nativeBottomRight,
nativeRoles);
}
bool QAndroidItemModelProxy::registerAbstractNatives(QJniEnvironment &env)
{
return env.registerNativeMethods(
@ -369,7 +403,9 @@ bool QAndroidItemModelProxy::registerAbstractNatives(QJniEnvironment &env)
Q_JNI_NATIVE_SCOPED_METHOD(jni_endRemoveColumns, QAndroidItemModelProxy),
Q_JNI_NATIVE_SCOPED_METHOD(jni_endRemoveRows, QAndroidItemModelProxy),
Q_JNI_NATIVE_SCOPED_METHOD(jni_endResetModel, QAndroidItemModelProxy),
Q_JNI_NATIVE_SCOPED_METHOD(jni_sibling, QAndroidItemModelProxy) });
Q_JNI_NATIVE_SCOPED_METHOD(jni_sibling, QAndroidItemModelProxy),
Q_JNI_NATIVE_SCOPED_METHOD(jni_setData, QAndroidItemModelProxy),
Q_JNI_NATIVE_SCOPED_METHOD(jni_dataChanged, QAndroidItemModelProxy) });
}
bool QAndroidItemModelProxy::registerProxyNatives(QJniEnvironment &env)

View File

@ -52,6 +52,8 @@ public:
bool hasChildrenDefault(const QModelIndex &parent) const;
QModelIndex sibling(int row, int column, const QModelIndex &parent) const override;
QModelIndex siblingDefault(int row, int column, const QModelIndex &parent);
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
bool setDataDefault(const QModelIndex &index, const QVariant &value, int role);
Q_REQUIRED_RESULT static QAbstractItemModel *
nativeInstance(QtJniTypes::JQtAbstractItemModel itemModel);
@ -202,6 +204,14 @@ public:
JQtModelIndex parent);
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_sibling)
static void jni_dataChanged(JNIEnv *env, jobject object, JQtModelIndex topLeft,
JQtModelIndex bottomRight, QJniArray<jint> roles);
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_dataChanged)
static jboolean jni_setData(JNIEnv *env, jobject object, JQtModelIndex index, jobject &value,
jint role);
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_setData)
static bool registerAbstractNatives(QJniEnvironment &env);
static bool registerProxyNatives(QJniEnvironment &env);