Android: Add Java QtAbstractItemModel and QtAbstractListModel
These classes used to be a part of QtDeclarative and are being moved to QtCore based on API reviews. Task-number: QTBUG-126976 Task-number: QTBUG-126977 Change-Id: Ic269f23ca2292031cda62faf41428667889537d0 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io> (cherry picked from commit 55fc15ce8272073b9b404762b83e3e7acee0111e) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
81a9cbe1db
commit
e544ae0abd
@ -46,6 +46,10 @@ set(java_sources
|
|||||||
src/org/qtproject/qt/android/QtMenuInterface.java
|
src/org/qtproject/qt/android/QtMenuInterface.java
|
||||||
src/org/qtproject/qt/android/QtLayoutInterface.java
|
src/org/qtproject/qt/android/QtLayoutInterface.java
|
||||||
src/org/qtproject/qt/android/QtInputInterface.java
|
src/org/qtproject/qt/android/QtInputInterface.java
|
||||||
|
src/org/qtproject/qt/android/QtAbstractItemModel.java
|
||||||
|
src/org/qtproject/qt/android/QtAbstractItemModelProxy.java
|
||||||
|
src/org/qtproject/qt/android/QtModelIndex.java
|
||||||
|
src/org/qtproject/qt/android/QtAbstractListModel.java
|
||||||
)
|
)
|
||||||
|
|
||||||
qt_internal_add_jar(Qt${QtBase_VERSION_MAJOR}Android
|
qt_internal_add_jar(Qt${QtBase_VERSION_MAJOR}Android
|
||||||
|
@ -0,0 +1,490 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
package org.qtproject.qt.android;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QtAbstractItemModel is a base class for implementing custom models in Java,
|
||||||
|
* similar to the C++ QAbstractItemModel.
|
||||||
|
*
|
||||||
|
* The QAbstractItemModel class defines the standard interface that item
|
||||||
|
* models must use to be able to interoperate with other components in the
|
||||||
|
* model/view architecture. It is not supposed to be instantiated directly.
|
||||||
|
* Instead, you should extend it to create new models.
|
||||||
|
*
|
||||||
|
* A QtAbstractItemModel can be used as the underlying data model for the
|
||||||
|
* item view elements in QML.
|
||||||
|
*
|
||||||
|
* If you need a model to use with an item view, such as QML's ListView element,
|
||||||
|
* you should consider extending {@link QtAbstractListModel} instead of this class.
|
||||||
|
*
|
||||||
|
* The underlying data model is exposed to views and delegates as a hierarchy
|
||||||
|
* of tables. If you do not use the hierarchy, the model is a simple table of
|
||||||
|
* rows and columns. Each item has a unique index specified by a {@link QtModelIndex}.
|
||||||
|
*
|
||||||
|
* @image modelindex-no-parent.png
|
||||||
|
*
|
||||||
|
* Every item of data that can be accessed via a model has an associated model
|
||||||
|
* index. You can obtain this model index using the {@link #index(int, int)} method.
|
||||||
|
* Each index may have a {@link #sibling(int, int)} index; child items have a
|
||||||
|
* {@link #parent()} index.
|
||||||
|
*
|
||||||
|
* Each item has data elements associated with it, and they can be
|
||||||
|
* retrieved by specifying a role to the model's {@link #data(QtModelIndex, int)} function.
|
||||||
|
*
|
||||||
|
* If an item has child objects, {@link #hasChildren(QtModelIndex)} returns true for the
|
||||||
|
* corresponding index.
|
||||||
|
*
|
||||||
|
* The model has a {@link #rowCount(QtModelIndex)} and a {@link #columnCount(QtModelIndex)}
|
||||||
|
* for each level of the hierarchy.
|
||||||
|
*
|
||||||
|
* Extending QtAbstractItemModel:
|
||||||
|
*
|
||||||
|
* Some general guidelines for sub-classing models are available in the
|
||||||
|
* {@link https://doc.qt.io/qt-6/model-view-programming.html#model-subclassing-reference}
|
||||||
|
* model sub-classing reference.
|
||||||
|
*
|
||||||
|
* When sub-classing QtAbstractItemModel, at the very least, you must implement
|
||||||
|
* {@link #index(int, int)}, {@link #parent(QtModelIndex)},{@link #rowCount(QtModelIndex)},
|
||||||
|
* {@link #columnCount(QtModelIndex)}, and {@link #data(QtModelIndex, int)}.
|
||||||
|
* These abstract methods are used in all models.
|
||||||
|
*
|
||||||
|
* You can also re-implement {@link #hasChildren(QtModelIndex)} to provide special behavior for
|
||||||
|
* models where the implementation of {@link #rowCount(QtModelIndex)} is expensive. This makes it
|
||||||
|
* possible for models to restrict the amount of data requested by views and
|
||||||
|
* can be used as a way to implement the population of model data.
|
||||||
|
*
|
||||||
|
* Custom models need to create model indexes for other components to use. To
|
||||||
|
* do this, call {@link #createIndex(int, int, long)} with suitable row and column numbers for the
|
||||||
|
* item, and a long type identifier for it.
|
||||||
|
* The combination of these values must be unique for each item. Custom models
|
||||||
|
* typically use these unique identifiers in other re-implemented functions to
|
||||||
|
* retrieve item data and access information about the item's parents and
|
||||||
|
* children.
|
||||||
|
*
|
||||||
|
* To create models that populate incrementally, you can re-implement
|
||||||
|
* {@link #fetchMore(QtModelIndex)} and {@link #canFetchMore(QtModelIndex)}.
|
||||||
|
* If the re-implementation of {@link #fetchMore(QtModelIndex)} adds
|
||||||
|
* rows to the model, {@link QtAbstractItemModel#beginInsertRows(QtModelIndex, int, int)} and
|
||||||
|
* {@link QtAbstractItemModel#endInsertRows()} must be called.
|
||||||
|
* @since 6.8
|
||||||
|
*/
|
||||||
|
public abstract class QtAbstractItemModel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructs a new QtAbstractItemModel.
|
||||||
|
*/
|
||||||
|
public QtAbstractItemModel(){};
|
||||||
|
/**
|
||||||
|
* Returns the number of columns for the children of the given parent.
|
||||||
|
* In most subclasses, the number of columns is independent of the parent.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* @Override
|
||||||
|
* int columnCount(const QtModelIndex parent)
|
||||||
|
* {
|
||||||
|
* return 3;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* When implementing a table-based model, columnCount() should return 0,
|
||||||
|
* when the parent is valid.
|
||||||
|
*
|
||||||
|
* @param parent The parent index.
|
||||||
|
* @return The number of columns.
|
||||||
|
* @see #rowCount(QtModelIndex)
|
||||||
|
*/
|
||||||
|
public abstract int columnCount(QtModelIndex parent);
|
||||||
|
/**
|
||||||
|
* Returns the data for the given index and role.
|
||||||
|
* Types conversions are:
|
||||||
|
* QML <- Java
|
||||||
|
* int <- Integer
|
||||||
|
* string <- String
|
||||||
|
* double <- Double
|
||||||
|
* real <- Double
|
||||||
|
* bool <- Boolean
|
||||||
|
*
|
||||||
|
* @param index The index.
|
||||||
|
* @param role The role.
|
||||||
|
* @return The data object.
|
||||||
|
*/
|
||||||
|
public abstract Object data(QtModelIndex index, int role);
|
||||||
|
/**
|
||||||
|
* Returns the index for the specified row and column for the supplied parent index.
|
||||||
|
* When re-implementing this function in a subclass, call createIndex() to generate model
|
||||||
|
* indexes that other components can use to refer to items in your model.
|
||||||
|
*
|
||||||
|
* @param row The row.
|
||||||
|
* @param column The column.
|
||||||
|
* @param parent The parent index.
|
||||||
|
* @return The index.
|
||||||
|
* @see #createIndex(int row, int column, long id)
|
||||||
|
*/
|
||||||
|
public abstract QtModelIndex index(int row, int column, QtModelIndex parent);
|
||||||
|
/**
|
||||||
|
* Returns the parent of the model item with the given index. If the item
|
||||||
|
* has no parent, then an invalid QtModelIndex is returned.
|
||||||
|
*
|
||||||
|
* A common convention used in models that expose tree data structures is that
|
||||||
|
* only items in the first column have children. For that case, when
|
||||||
|
* re-implementing this function in a subclass, the column of the returned
|
||||||
|
* QtModelIndex would be 0.
|
||||||
|
|
||||||
|
* When re-implementing this function in a subclass, be careful to avoid
|
||||||
|
* calling QtModelIndex member functions, such as QtModelIndex::parent(), since
|
||||||
|
* indexes belonging to your model will call your implementation,
|
||||||
|
* leading to infinite recursion.
|
||||||
|
*
|
||||||
|
* @param index The index.
|
||||||
|
* @return The parent index.
|
||||||
|
* @see #createIndex(int row, int column, long id)
|
||||||
|
*/
|
||||||
|
public abstract QtModelIndex parent(QtModelIndex index);
|
||||||
|
/**
|
||||||
|
* Returns the number of rows under the given parent. When the parent is
|
||||||
|
* valid, it means that rowCount is returning the number of children of the parent.
|
||||||
|
|
||||||
|
* Note: when implementing a table-based model, rowCount() should return 0,
|
||||||
|
* when the parent is valid.
|
||||||
|
*
|
||||||
|
* @param parent The parent index.
|
||||||
|
* @return The number of rows.
|
||||||
|
* @see #columnCount(QtModelIndex parent)
|
||||||
|
*/
|
||||||
|
public abstract int rowCount(QtModelIndex parent);
|
||||||
|
/**
|
||||||
|
* Returns whether more items can be fetched for the given parent index.
|
||||||
|
*
|
||||||
|
* @param parent The parent index.
|
||||||
|
* @return True if more items can be fetched, false otherwise.
|
||||||
|
*/
|
||||||
|
public native boolean canFetchMore(QtModelIndex parent);
|
||||||
|
/**
|
||||||
|
* Fetches any available data for the items with the parent specified by the
|
||||||
|
* parent index.
|
||||||
|
*
|
||||||
|
* @param parent The parent index.
|
||||||
|
*/
|
||||||
|
public native void fetchMore(QtModelIndex parent);
|
||||||
|
/**
|
||||||
|
* Returns true if the parent has any children; otherwise, returns false.
|
||||||
|
* Use rowCount() on the parent to get the number of children.
|
||||||
|
*
|
||||||
|
* @param parent The parent index.
|
||||||
|
* @return True if the parent has children, false otherwise.
|
||||||
|
* @see #parent(QtModelIndex index)
|
||||||
|
* @see #index(int row, int column, QtModelIndex parent)
|
||||||
|
*/
|
||||||
|
public native boolean hasChildren(QtModelIndex parent);
|
||||||
|
/**
|
||||||
|
* Returns true if the model returns a valid QModelIndex for row and
|
||||||
|
* column with parent, otherwise returns \c{false}.
|
||||||
|
*
|
||||||
|
* @param row The row.
|
||||||
|
* @param column The column.
|
||||||
|
* @param parent The parent index.
|
||||||
|
* @return True if the index exists, false otherwise.
|
||||||
|
*/
|
||||||
|
public native boolean hasIndex(int row, int column, QtModelIndex parent);
|
||||||
|
/**
|
||||||
|
* Returns a map of role names.
|
||||||
|
* You must override this to provide your own role names or the
|
||||||
|
* {@link https://doc.qt.io/qt-6/qabstractitemmodel.html#roleNames defaults}
|
||||||
|
* will be used.
|
||||||
|
*
|
||||||
|
* @return The role names map.
|
||||||
|
*/
|
||||||
|
public HashMap<Integer, String> roleNames()
|
||||||
|
{
|
||||||
|
return (HashMap<Integer, String>)jni_roleNames();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the sibling at row and column for the item at index or an
|
||||||
|
* invalid QModelIndex if there is no sibling at that location.
|
||||||
|
*
|
||||||
|
* sibling() is just a convenience function that finds the item's parent and
|
||||||
|
* uses it to retrieve the index of the child item in the specified row and
|
||||||
|
* column.
|
||||||
|
*
|
||||||
|
* This method can optionally be overridden to optimize a specific implementation.
|
||||||
|
*
|
||||||
|
* @param row The row.
|
||||||
|
* @param column The column.
|
||||||
|
* @param parent The parent index.
|
||||||
|
* @return The sibling index.
|
||||||
|
*/
|
||||||
|
public QtModelIndex sibling(int row, int column, QtModelIndex parent)
|
||||||
|
{
|
||||||
|
return (QtModelIndex)jni_sibling(row, column, parent);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Begins a column insertion operation.
|
||||||
|
|
||||||
|
* The parent index corresponds to the parent into which the new columns
|
||||||
|
* are inserted; first and last are the column numbers of the new
|
||||||
|
* columns will have after they have been inserted.
|
||||||
|
*
|
||||||
|
* @see #endInsertColumns()
|
||||||
|
*/
|
||||||
|
protected final void beginInsertColumns(QtModelIndex parent, int first, int last)
|
||||||
|
{
|
||||||
|
jni_beginInsertColumns(parent, first, last);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Begins a row insertion operation.
|
||||||
|
* Parent index corresponds to the parent into which the new rows
|
||||||
|
* are inserted; first and last are the row numbers the new rows will have
|
||||||
|
* after they have been inserted.
|
||||||
|
|
||||||
|
* @see #endInsertRows()
|
||||||
|
*/
|
||||||
|
protected final void beginInsertRows(QtModelIndex parent, int first, int last)
|
||||||
|
{
|
||||||
|
jni_beginInsertRows(parent, first, last);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Begins a column move operation.
|
||||||
|
|
||||||
|
When re-implementing a subclass, this method simplifies moving
|
||||||
|
entities in your model. This method is responsible for moving
|
||||||
|
persistent indexes in the model.
|
||||||
|
|
||||||
|
The sourceParent index corresponds to the parent from which the
|
||||||
|
columns are moved; sourceFirst and sourceLast are the first and last
|
||||||
|
column numbers of the columns to be moved. The destinationParent index
|
||||||
|
corresponds to the parent into which those columns are moved. The
|
||||||
|
destinationChild is the column to which the columns will be moved. That
|
||||||
|
is, the index at column sourceFirst in sourceParent will become
|
||||||
|
column destinationChild in destinationParent, followed by all other
|
||||||
|
columns up to sourceLast.
|
||||||
|
|
||||||
|
However, when moving columns down in the same parent (sourceParent
|
||||||
|
and destinationParent are equal), the columns will be placed before the
|
||||||
|
destinationChild index. If you wish to move columns 0 and 1 so
|
||||||
|
they will become columns 1 and 2, destinationChild should be 3. In this
|
||||||
|
case, the new index for the source column i (which is between
|
||||||
|
sourceFirst and sourceLast) is equal to (destinationChild-sourceLast-1+i).
|
||||||
|
|
||||||
|
Note that if sourceParent and destinationParent are the same,
|
||||||
|
you must ensure that the destinationChild is not within the range
|
||||||
|
of sourceFirst and sourceLast + 1. You must also ensure that you
|
||||||
|
do not attempt to move a column to one of its own children or ancestors.
|
||||||
|
This method returns false if either condition is true, in which case you
|
||||||
|
should abort your move operation.
|
||||||
|
|
||||||
|
@see endMoveColumns()
|
||||||
|
*/
|
||||||
|
protected final boolean beginMoveColumns(QtModelIndex sourceParent, int sourceFirst,
|
||||||
|
int sourceLast, QtModelIndex destinationParent,
|
||||||
|
int destinationChild)
|
||||||
|
{
|
||||||
|
return jni_beginMoveColumns(sourceParent, sourceFirst, sourceLast, destinationParent,
|
||||||
|
destinationChild);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Begins a row move operation.
|
||||||
|
|
||||||
|
* When re-implementing a subclass, this method simplifies moving
|
||||||
|
* entities in your model.
|
||||||
|
|
||||||
|
* The sourceParent index corresponds to the parent from which the
|
||||||
|
* rows are moved; sourceFirst and sourceLast are the first and last
|
||||||
|
* row numbers of the rows to be moved. The destinationParent index
|
||||||
|
* corresponds to the parent into which those rows are moved. The
|
||||||
|
* destinationChild is the row to which the rows will be moved. That
|
||||||
|
* is, the index at row sourceFirst in sourceParent will become
|
||||||
|
* row destinationChild in destinationParent, followed by all other
|
||||||
|
* rows up to sourceLast.
|
||||||
|
|
||||||
|
* However, when moving rows down in the same parent (sourceParent
|
||||||
|
* and destinationParent are equal), the rows will be placed before the
|
||||||
|
* destinationChild index. That is, if you wish to move rows 0 and 1 so
|
||||||
|
* they will become rows 1 and 2, destinationChild should be 3. In this
|
||||||
|
* case, the new index for the source row i (which is between
|
||||||
|
* sourceFirst and sourceLast) is equal to
|
||||||
|
* (destinationChild-sourceLast-1+i).
|
||||||
|
|
||||||
|
* Note that if sourceParent and destinationParent are the same,
|
||||||
|
* you must ensure that the destinationChild is not within the range
|
||||||
|
* of sourceFirst and sourceLast + 1. You must also ensure that you
|
||||||
|
* do not attempt to move a row to one of its own children or ancestors.
|
||||||
|
* This method returns false if either condition is true, in which case you
|
||||||
|
* should abort your move operation.
|
||||||
|
|
||||||
|
* {@link https://doc.qt.io/qt-6/qabstractitemmodel.html#beginMoveRows PossibleOps}
|
||||||
|
|
||||||
|
* @see #endMoveRows()
|
||||||
|
*/
|
||||||
|
protected final boolean beginMoveRows(QtModelIndex sourceParent, int sourceFirst,
|
||||||
|
int sourceLast, QtModelIndex destinationParent,
|
||||||
|
int destinationChild)
|
||||||
|
{
|
||||||
|
return jni_beginMoveRows(sourceParent, sourceFirst, sourceLast, destinationParent,
|
||||||
|
destinationChild);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Begins a column removal operation.
|
||||||
|
|
||||||
|
* When re-implementing removeColumns() in a subclass, you must call this
|
||||||
|
* function before removing data from the model's underlying data store.
|
||||||
|
|
||||||
|
* The parent index corresponds to the parent from which the new columns
|
||||||
|
* are removed; first and last are the column numbers of the first and
|
||||||
|
* last columns to be removed.
|
||||||
|
*
|
||||||
|
* {@link https://doc.qt.io/qt-6/qabstractitemmodel.html#beginRemoveColumns RemoveColums}
|
||||||
|
* @see #endRemoveColumns()
|
||||||
|
*/
|
||||||
|
protected final void beginRemoveColumns(QtModelIndex parent, int first, int last)
|
||||||
|
{
|
||||||
|
jni_beginRemoveColumns(parent, first, last);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Begins a row removal operation.
|
||||||
|
|
||||||
|
* When re-implementing removeRows() in a subclass, you must call this
|
||||||
|
* function before removing data from the model's underlying data store.
|
||||||
|
|
||||||
|
* The parent index corresponds to the parent from which the new rows are
|
||||||
|
* removed; first and last are the row numbers of the rows to be.
|
||||||
|
|
||||||
|
{@link https://doc.qt.io/qt-6/qabstractitemmodel.html#beginRemoveRows RemoveRows}
|
||||||
|
* @see #endRemoveRow()
|
||||||
|
*/
|
||||||
|
protected final void beginRemoveRows(QtModelIndex parent, int first, int last)
|
||||||
|
{
|
||||||
|
jni_beginRemoveRows(parent, first, last);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Begins a model reset operation.
|
||||||
|
|
||||||
|
* A reset operation resets the model to its current state in any attached views.
|
||||||
|
|
||||||
|
* Note: any views attached to this model will also be reset.
|
||||||
|
|
||||||
|
* When a model is reset, any previous data reported from the
|
||||||
|
* model is now invalid and has to be queried again. This also means that
|
||||||
|
* the current and any selected items will become invalid.
|
||||||
|
|
||||||
|
* When a model radically changes its data, it can sometimes be easier to just
|
||||||
|
* call this function rather than emit dataChanged() to inform other
|
||||||
|
* components when the underlying data source, or its structure, has changed.
|
||||||
|
|
||||||
|
* You must call this function before resetting any internal data structures
|
||||||
|
in your model.
|
||||||
|
|
||||||
|
* @see #modelAboutToBeReset()
|
||||||
|
* @see #modelReset()
|
||||||
|
* @see #endResetModel()
|
||||||
|
*/
|
||||||
|
protected final void beginResetModel() { jni_beginResetModel(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a model index for the given row and column with the internal
|
||||||
|
* identifier id.
|
||||||
|
|
||||||
|
* This function provides a consistent interface, which model sub classes must
|
||||||
|
* use to create model indexes.
|
||||||
|
*/
|
||||||
|
protected final QtModelIndex createIndex(int row, int column, long id)
|
||||||
|
{
|
||||||
|
return (QtModelIndex)jni_createIndex(row, column, id);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Ends a column insertion operation.
|
||||||
|
|
||||||
|
* When re-implementing insertColumns() in a subclass, you must call this
|
||||||
|
* function after inserting data into the model's underlying data
|
||||||
|
* store.
|
||||||
|
|
||||||
|
* @see #beginInsertColumns()
|
||||||
|
*/
|
||||||
|
protected final void endInsertColumns() { jni_endInsertColumns(); }
|
||||||
|
/**
|
||||||
|
* Ends a row insertion operation.
|
||||||
|
|
||||||
|
* When re-implementing insertRows() in a subclass, you must call this function
|
||||||
|
* after inserting data into the model's underlying data store.
|
||||||
|
|
||||||
|
* @see #beginInsertRows()
|
||||||
|
*/
|
||||||
|
protected final void endInsertRows() { jni_endInsertRows(); }
|
||||||
|
/**
|
||||||
|
* Ends a column move operation.
|
||||||
|
|
||||||
|
* When implementing a subclass, you must call this
|
||||||
|
* function after moving data within the model's underlying data
|
||||||
|
* store.
|
||||||
|
|
||||||
|
* @see #beginMoveColumns()
|
||||||
|
*/
|
||||||
|
protected final void endMoveColumns() { jni_endMoveColumns(); }
|
||||||
|
/**
|
||||||
|
Ends a row move operation.
|
||||||
|
|
||||||
|
When implementing a subclass, you must call this
|
||||||
|
function after moving data within the model's underlying data
|
||||||
|
store.
|
||||||
|
|
||||||
|
@see #beginMoveRows()
|
||||||
|
*/
|
||||||
|
protected final void endMoveRows() { jni_endMoveRows(); }
|
||||||
|
/**
|
||||||
|
* Ends a column removal operation.
|
||||||
|
|
||||||
|
* When reimplementing removeColumns() in a subclass, you must call this
|
||||||
|
* function after removing data from the model's underlying data store.
|
||||||
|
|
||||||
|
* @see #beginRemoveColumns()
|
||||||
|
*/
|
||||||
|
protected final void endRemoveColumns() { jni_endRemoveColumns(); }
|
||||||
|
/**
|
||||||
|
* Ends a row move operation.
|
||||||
|
|
||||||
|
* When implementing a subclass, you must call this
|
||||||
|
* function after moving data within the model's underlying data
|
||||||
|
* store.
|
||||||
|
|
||||||
|
* @see #beginMoveRows(QtModelIndex sourceParent, int sourceFirst, int sourceLast, QtModelIndexdestinationParent, int destinationChild)
|
||||||
|
*/
|
||||||
|
protected final void endRemoveRows() { jni_endRemoveRows(); }
|
||||||
|
/**
|
||||||
|
* Completes a model reset operation.
|
||||||
|
|
||||||
|
* You must call this function after resetting any internal data structure in your model.
|
||||||
|
|
||||||
|
* @see #beginResetModel()
|
||||||
|
*/
|
||||||
|
protected final void endResetModel() { jni_endResetModel(); }
|
||||||
|
|
||||||
|
private native void jni_beginInsertColumns(QtModelIndex parent, int first, int last);
|
||||||
|
private native void jni_beginInsertRows(QtModelIndex parent, int first, int last);
|
||||||
|
private native boolean jni_beginMoveColumns(QtModelIndex sourceParent, int sourceFirst,
|
||||||
|
int sourceLast, QtModelIndex destinationParent,
|
||||||
|
int destinationChild);
|
||||||
|
private native boolean jni_beginMoveRows(QtModelIndex sourceParent, int sourceFirst,
|
||||||
|
int sourceLast, QtModelIndex destinationParent,
|
||||||
|
int destinationChild);
|
||||||
|
private native void jni_beginRemoveColumns(QtModelIndex parent, int first, int last);
|
||||||
|
private native void jni_beginRemoveRows(QtModelIndex parent, int first, int last);
|
||||||
|
private native void jni_beginResetModel();
|
||||||
|
private native Object jni_createIndex(int row, int column, long id);
|
||||||
|
private native void jni_endInsertColumns();
|
||||||
|
private native void jni_endInsertRows();
|
||||||
|
private native void jni_endMoveColumns();
|
||||||
|
private native void jni_endMoveRows();
|
||||||
|
private native void jni_endRemoveColumns();
|
||||||
|
private native void jni_endRemoveRows();
|
||||||
|
private native void jni_endResetModel();
|
||||||
|
private native Object jni_roleNames();
|
||||||
|
private native Object jni_sibling(int row, int column, QtModelIndex parent);
|
||||||
|
|
||||||
|
private long m_nativeReference = 0;
|
||||||
|
private QtAbstractItemModel(long nativeReference) { m_nativeReference = nativeReference; }
|
||||||
|
private void detachFromNative() { m_nativeReference = 0; };
|
||||||
|
private long nativeReference() { return m_nativeReference; }
|
||||||
|
private void setNativeReference(long nativeReference) { m_nativeReference = nativeReference; }
|
||||||
|
private static boolean instanceOf(Object obj) { return (obj instanceof QtAbstractItemModel); }
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
package org.qtproject.qt.android;
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
|
||||||
|
class QtAndroidItemModelProxy extends QtAbstractItemModel
|
||||||
|
{
|
||||||
|
@Override public int columnCount(QtModelIndex parent) { return jni_columnCount(parent); };
|
||||||
|
@Override public Object data(QtModelIndex index, int role) { return jni_data(index, role); }
|
||||||
|
@Override public QtModelIndex index(int row, int column, QtModelIndex parent)
|
||||||
|
{
|
||||||
|
return (QtModelIndex)jni_index(row, column, parent);
|
||||||
|
}
|
||||||
|
@Override public QtModelIndex parent(QtModelIndex index)
|
||||||
|
{
|
||||||
|
return (QtModelIndex)jni_parent(index);
|
||||||
|
}
|
||||||
|
@Override public int rowCount(QtModelIndex parent) { return jni_rowCount(parent); }
|
||||||
|
|
||||||
|
private native int jni_columnCount(QtModelIndex parent);
|
||||||
|
private native Object jni_data(QtModelIndex index, int role);
|
||||||
|
private native Object jni_index(int row, int column, QtModelIndex parent);
|
||||||
|
private native Object jni_parent(QtModelIndex index);
|
||||||
|
private native int jni_rowCount(QtModelIndex parent);
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
package org.qtproject.qt.android;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public abstract class QtAbstractListModel extends QtAbstractItemModel
|
||||||
|
{
|
||||||
|
public QtAbstractListModel(){};
|
||||||
|
|
||||||
|
@Override public final int columnCount(QtModelIndex parent) { return parent.isValid() ? 0 : 1; }
|
||||||
|
|
||||||
|
@Override public QtModelIndex index(int row, int column, QtModelIndex parent)
|
||||||
|
{
|
||||||
|
return hasIndex(row, column, parent) ? createIndex(row, column, 0) : new QtModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public final QtModelIndex parent(QtModelIndex index) { return new QtModelIndex(); }
|
||||||
|
|
||||||
|
@Override public final boolean hasChildren(QtModelIndex parent)
|
||||||
|
{
|
||||||
|
return parent.isValid() ? false : (rowCount(new QtModelIndex()) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public QtModelIndex sibling(int row, int column, QtModelIndex parent)
|
||||||
|
{
|
||||||
|
return index(row, column, new QtModelIndex());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
package org.qtproject.qt.android;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an index in a custom item model, similar to
|
||||||
|
* {@link https://doc.qt.io/qt-6/https://doc.qt.io/qt-6/qmodelindex.html QModelindex}
|
||||||
|
* in c++.
|
||||||
|
*/
|
||||||
|
public class QtModelIndex
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructs a new QtModelIndex.
|
||||||
|
*/
|
||||||
|
public QtModelIndex() { }
|
||||||
|
/**
|
||||||
|
* Returns the column of this index.
|
||||||
|
*
|
||||||
|
* @return The column.
|
||||||
|
*/
|
||||||
|
public int column() { return (int)m_privateData[1]; }
|
||||||
|
/**
|
||||||
|
* Retrieves data for this index based on the specified role.
|
||||||
|
*
|
||||||
|
* @param role The role for which data is requested.
|
||||||
|
* @return The data object.
|
||||||
|
*/
|
||||||
|
public native Object data(int role);
|
||||||
|
/**
|
||||||
|
* Returns the internal ID associated with this index.
|
||||||
|
*
|
||||||
|
* @return The internal ID.
|
||||||
|
*/
|
||||||
|
public native long internalId();
|
||||||
|
/**
|
||||||
|
* Checks if this index is valid.
|
||||||
|
*
|
||||||
|
* @return True if the index is valid, false otherwise.
|
||||||
|
*/
|
||||||
|
public native boolean isValid();
|
||||||
|
/**
|
||||||
|
* Returns the parent index of this index.
|
||||||
|
*
|
||||||
|
* @return The parent index.
|
||||||
|
*/
|
||||||
|
public native QtModelIndex parent();
|
||||||
|
/**
|
||||||
|
* Returns the row of this index.
|
||||||
|
*
|
||||||
|
* @return The row.
|
||||||
|
*/
|
||||||
|
public int row() { return (int)m_privateData[0]; }
|
||||||
|
|
||||||
|
private long[] m_privateData = { -1 /*row*/, -1 /*column*/, 0 /*internalId*/,
|
||||||
|
0 /*modelReference*/ };
|
||||||
|
private QtModelIndex m_parent = null;
|
||||||
|
private QtModelIndex(int row, int column, long internalId, long modelReference)
|
||||||
|
{
|
||||||
|
m_privateData[0] = row;
|
||||||
|
m_privateData[1] = column;
|
||||||
|
m_privateData[2] = internalId;
|
||||||
|
m_privateData[3] = modelReference;
|
||||||
|
m_parent = null;
|
||||||
|
}
|
||||||
|
private QtModelIndex(int row, int column, QtModelIndex parent, long modelReference)
|
||||||
|
{
|
||||||
|
m_privateData[0] = row;
|
||||||
|
m_privateData[1] = column;
|
||||||
|
m_privateData[2] = 0;
|
||||||
|
m_privateData[3] = modelReference;
|
||||||
|
m_parent = parent;
|
||||||
|
}
|
||||||
|
private void detachFromNative()
|
||||||
|
{
|
||||||
|
m_privateData[0] = -1;
|
||||||
|
m_privateData[1] = -1;
|
||||||
|
m_privateData[2] = 0;
|
||||||
|
m_privateData[3] = 0;
|
||||||
|
};
|
||||||
|
}
|
@ -1064,6 +1064,8 @@ qt_internal_extend_target(Core CONDITION ANDROID
|
|||||||
platform/android/qandroidnativeinterface.cpp
|
platform/android/qandroidnativeinterface.cpp
|
||||||
platform/android/qandroidtypes_p.h
|
platform/android/qandroidtypes_p.h
|
||||||
platform/android/qandroidtypeconverter_p.h
|
platform/android/qandroidtypeconverter_p.h
|
||||||
|
platform/android/qandroiditemmodelproxy_p.h platform/android/qandroiditemmodelproxy.cpp
|
||||||
|
platform/android/qandroidmodelindexproxy_p.h platform/android/qandroidmodelindexproxy.cpp
|
||||||
NO_UNITY_BUILD_SOURCES
|
NO_UNITY_BUILD_SOURCES
|
||||||
platform/android/qandroidextras.cpp
|
platform/android/qandroidextras.cpp
|
||||||
# qtNativeClassName conflicts with similar symbols in android headers
|
# qtNativeClassName conflicts with similar symbols in android headers
|
||||||
|
379
src/corelib/platform/android/qandroiditemmodelproxy.cpp
Normal file
379
src/corelib/platform/android/qandroiditemmodelproxy.cpp
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
// 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 <QtCore/private/qandroiditemmodelproxy_p.h>
|
||||||
|
#include <QtCore/private/qandroidmodelindexproxy_p.h>
|
||||||
|
#include <QtCore/private/qandroidtypeconverter_p.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
using namespace QtJniTypes;
|
||||||
|
|
||||||
|
jint QAndroidItemModelProxy::columnCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(jInstance.isValid());
|
||||||
|
auto parentIndex = QAndroidModelIndexProxy::jInstance(parent);
|
||||||
|
return jInstance.callMethod<jint>("columnCount", parentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QAndroidItemModelProxy::canFetchMore(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(jInstance.isValid());
|
||||||
|
auto parentIndex = QAndroidModelIndexProxy::jInstance(parent);
|
||||||
|
return jInstance.callMethod<jboolean>("canFetchMore", parentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QAndroidItemModelProxy::canFetchMoreDefault(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
return QAbstractItemModel::canFetchMore(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant QAndroidItemModelProxy::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(jInstance.isValid());
|
||||||
|
auto jIndex = QAndroidModelIndexProxy::jInstance(index);
|
||||||
|
QJniObject jData = jInstance.callMethod<jobject>("data", jIndex, role);
|
||||||
|
return QAndroidTypeConverter::toQVariant(jData);
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex QAndroidItemModelProxy::index(int row, int column, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(jInstance.isValid());
|
||||||
|
JQtModelIndex jIndex = jInstance.callMethod<JQtModelIndex>(
|
||||||
|
"index", row, column, QAndroidModelIndexProxy::jInstance(parent));
|
||||||
|
return QAndroidModelIndexProxy::qInstance(jIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex QAndroidItemModelProxy::parent(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(jInstance.isValid());
|
||||||
|
|
||||||
|
auto jIndex = QAndroidModelIndexProxy::jInstance(index);
|
||||||
|
return QAndroidModelIndexProxy::qInstance(
|
||||||
|
jInstance.callMethod<JQtModelIndex>("parent", jIndex));
|
||||||
|
}
|
||||||
|
int QAndroidItemModelProxy::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(jInstance.isValid());
|
||||||
|
|
||||||
|
auto parentIndex = QAndroidModelIndexProxy::jInstance(parent);
|
||||||
|
return jInstance.callMethod<int>("rowCount", parentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> QAndroidItemModelProxy::roleNames() const
|
||||||
|
{
|
||||||
|
Q_ASSERT(jInstance.isValid());
|
||||||
|
|
||||||
|
QHash<int, QByteArray> roleNames;
|
||||||
|
HashMap hashMap = jInstance.callMethod<HashMap>("roleNames");
|
||||||
|
Set set = hashMap.callMethod<Set>("keySet");
|
||||||
|
QJniArray<jobject> keyArray = set.callMethod<QJniArray<jobject>>("toArray");
|
||||||
|
|
||||||
|
for (auto key : keyArray) {
|
||||||
|
const QJniObject roleName = hashMap.callMethod<jobject>("get", key);
|
||||||
|
const int intKey = QJniObject(key).callMethod<jint>("intValue");
|
||||||
|
const QByteArray roleByteArray = String(roleName).toString().toLatin1();
|
||||||
|
roleNames.insert(intKey, roleByteArray);
|
||||||
|
}
|
||||||
|
return roleNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> QAndroidItemModelProxy::defaultRoleNames() const
|
||||||
|
{
|
||||||
|
return QAbstractItemModel::roleNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidItemModelProxy::fetchMore(const QModelIndex &parent)
|
||||||
|
{
|
||||||
|
Q_ASSERT(jInstance.isValid());
|
||||||
|
auto parentIndex = QAndroidModelIndexProxy::jInstance(parent);
|
||||||
|
jInstance.callMethod<void>("fetchMore", parentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidItemModelProxy::fetchMoreDefault(const QModelIndex &parent)
|
||||||
|
{
|
||||||
|
QAbstractItemModel::fetchMore(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QAndroidItemModelProxy::hasChildren(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(jInstance.isValid());
|
||||||
|
auto parentIndex = QAndroidModelIndexProxy::jInstance(parent);
|
||||||
|
return jInstance.callMethod<jboolean>("hasChildren", parentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QAndroidItemModelProxy::hasChildrenDefault(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
return QAbstractItemModel::hasChildren(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex QAndroidItemModelProxy::sibling(int row, int column, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(jInstance.isValid());
|
||||||
|
return QAndroidModelIndexProxy::qInstance(jInstance.callMethod<jobject>(
|
||||||
|
"sibling", row, column, QAndroidModelIndexProxy::jInstance(parent)));
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex QAndroidItemModelProxy::siblingDefault(int row, int column, const QModelIndex &parent)
|
||||||
|
{
|
||||||
|
return QAbstractItemModel::sibling(row, column, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_REQUIRED_RESULT QAbstractItemModel *
|
||||||
|
QAndroidItemModelProxy::nativeInstance(JQtAbstractItemModel itemModel)
|
||||||
|
{
|
||||||
|
jlong nativeReference = itemModel.callMethod<jlong>("nativeReference");
|
||||||
|
return reinterpret_cast<QAbstractItemModel *>(nativeReference);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_REQUIRED_RESULT QAbstractItemModel *
|
||||||
|
QAndroidItemModelProxy::createNativeProxy(QJniObject itemModel)
|
||||||
|
{
|
||||||
|
QAbstractItemModel *nativeProxy = nativeInstance(itemModel);
|
||||||
|
if (!nativeProxy) {
|
||||||
|
nativeProxy = new QAndroidItemModelProxy(itemModel);
|
||||||
|
|
||||||
|
itemModel.callMethod<void>("setNativeReference", reinterpret_cast<jlong>(nativeProxy));
|
||||||
|
connect(nativeProxy, &QAndroidItemModelProxy::destroyed, nativeProxy, [](QObject *obj) {
|
||||||
|
auto proxy = qobject_cast<QAndroidItemModelProxy *>(obj);
|
||||||
|
if (proxy)
|
||||||
|
proxy->jInstance.callMethod<void>("detachFromNative");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return nativeProxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJniObject QAndroidItemModelProxy::createProxy(QAbstractItemModel *itemModel)
|
||||||
|
{
|
||||||
|
return JQtAndroidItemModelProxy(reinterpret_cast<jlong>(itemModel));
|
||||||
|
}
|
||||||
|
|
||||||
|
int QAndroidItemModelProxy::jni_columnCount(JNIEnv *env, jobject object, JQtModelIndex parent)
|
||||||
|
{
|
||||||
|
const QModelIndex nativeParent = QAndroidModelIndexProxy::qInstance(parent);
|
||||||
|
return invokeNativeMethod(env, object, &QAbstractItemModel::columnCount, nativeParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject QAndroidItemModelProxy::jni_data(JNIEnv *env, jobject object, JQtModelIndex index,
|
||||||
|
jint role)
|
||||||
|
{
|
||||||
|
const QModelIndex nativeIndex = QAndroidModelIndexProxy::qInstance(index);
|
||||||
|
const QVariant data =
|
||||||
|
invokeNativeMethod(env, object, &QAbstractItemModel::data, nativeIndex, role);
|
||||||
|
return QAndroidTypeConverter::toJavaObject(data, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject QAndroidItemModelProxy::jni_index(JNIEnv *env, jobject object, jint row, jint column,
|
||||||
|
JQtModelIndex parent)
|
||||||
|
{
|
||||||
|
auto nativeParent = QAndroidModelIndexProxy::qInstance(parent);
|
||||||
|
const QModelIndex modelIndex =
|
||||||
|
invokeNativeMethod(env, object, &QAbstractItemModel::index, row, column, nativeParent);
|
||||||
|
return env->NewLocalRef(QAndroidModelIndexProxy::jInstance(modelIndex).object());
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject QAndroidItemModelProxy::jni_parent(JNIEnv *env, jobject object, JQtModelIndex index)
|
||||||
|
{
|
||||||
|
const QModelIndex nativeIndex = QAndroidModelIndexProxy::qInstance(index);
|
||||||
|
QModelIndex (QAbstractItemModel::*parentOverloadPtr)(const QModelIndex &) const =
|
||||||
|
&QAbstractItemModel::parent;
|
||||||
|
const QModelIndex parent = invokeNativeMethod(env, object, parentOverloadPtr, nativeIndex);
|
||||||
|
return env->NewLocalRef(QAndroidModelIndexProxy::jInstance(parent).object());
|
||||||
|
}
|
||||||
|
|
||||||
|
jint QAndroidItemModelProxy::jni_rowCount(JNIEnv *env, jobject object, JQtModelIndex parent)
|
||||||
|
{
|
||||||
|
return invokeNativeMethod(env, object, &QAbstractItemModel::rowCount,
|
||||||
|
QAndroidModelIndexProxy::qInstance(parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject QAndroidItemModelProxy::jni_roleNames(JNIEnv *env, jobject object)
|
||||||
|
{
|
||||||
|
auto roleNames = invokeNativeImpl(env, object, &QAndroidItemModelProxy::defaultRoleNames,
|
||||||
|
&QAbstractItemModel::roleNames);
|
||||||
|
HashMap jRoleNames{};
|
||||||
|
for (auto [role, roleName] : roleNames.asKeyValueRange()) {
|
||||||
|
const Integer jRole(role);
|
||||||
|
const QJniObject jRoleName = QJniObject::fromString(roleName);
|
||||||
|
jRoleNames.callMethod<jobject>("put", jRole.object(), jRoleName.object());
|
||||||
|
}
|
||||||
|
return env->NewLocalRef(jRoleNames.object());
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject QAndroidItemModelProxy::jni_createIndex(JNIEnv *env, jobject object, jint row, jint column,
|
||||||
|
jlong id)
|
||||||
|
{
|
||||||
|
QModelIndex (QAndroidItemModelProxy::*createIndexPtr)(int, int, quintptr) const =
|
||||||
|
&QAndroidItemModelProxy::createIndex;
|
||||||
|
const QModelIndex index = invokeNativeProxyMethod(env, object, createIndexPtr, row, column, id);
|
||||||
|
return env->NewLocalRef(QAndroidModelIndexProxy::jInstance(index).object());
|
||||||
|
}
|
||||||
|
|
||||||
|
jboolean QAndroidItemModelProxy::jni_canFetchMore(JNIEnv *env, jobject object, JQtModelIndex parent)
|
||||||
|
{
|
||||||
|
return invokeNativeImpl(env, object, &QAndroidItemModelProxy::canFetchMoreDefault,
|
||||||
|
&QAbstractItemModel::canFetchMore,
|
||||||
|
QAndroidModelIndexProxy::qInstance(parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidItemModelProxy::jni_fetchMore(JNIEnv *env, jobject object, JQtModelIndex parent)
|
||||||
|
{
|
||||||
|
return invokeNativeImpl(env, object, &QAndroidItemModelProxy::fetchMoreDefault,
|
||||||
|
&QAbstractItemModel::fetchMore,
|
||||||
|
QAndroidModelIndexProxy::qInstance(parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
jboolean QAndroidItemModelProxy::jni_hasChildren(JNIEnv *env, jobject object, JQtModelIndex parent)
|
||||||
|
{
|
||||||
|
return invokeNativeImpl(env, object, &QAndroidItemModelProxy::hasChildrenDefault,
|
||||||
|
&QAbstractItemModel::hasChildren,
|
||||||
|
QAndroidModelIndexProxy::qInstance(parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
jboolean QAndroidItemModelProxy::jni_hasIndex(JNIEnv *env, jobject object, jint row, jint column,
|
||||||
|
JQtModelIndex parent)
|
||||||
|
{
|
||||||
|
return invokeNativeMethod(env, object, &QAbstractItemModel::hasIndex, row, column,
|
||||||
|
QAndroidModelIndexProxy::qInstance(parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidItemModelProxy::jni_beginInsertColumns(JNIEnv *env, jobject object,
|
||||||
|
JQtModelIndex parent, jint first, jint last)
|
||||||
|
{
|
||||||
|
|
||||||
|
invokeNativeProxyMethod(env, object, &QAndroidItemModelProxy::beginInsertColumns,
|
||||||
|
QAndroidModelIndexProxy::qInstance(parent), first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidItemModelProxy::jni_beginInsertRows(JNIEnv *env, jobject object, JQtModelIndex parent,
|
||||||
|
jint first, jint last)
|
||||||
|
{
|
||||||
|
invokeNativeProxyMethod(env, object, &QAndroidItemModelProxy::beginInsertRows,
|
||||||
|
QAndroidModelIndexProxy::qInstance(parent), first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
jboolean QAndroidItemModelProxy::jni_beginMoveColumns(JNIEnv *env, jobject object,
|
||||||
|
JQtModelIndex sourceParent, jint sourceFirst,
|
||||||
|
jint sourceLast,
|
||||||
|
JQtModelIndex destinationParent,
|
||||||
|
jint destinationChild)
|
||||||
|
{
|
||||||
|
return invokeNativeProxyMethod(
|
||||||
|
env, object, &QAndroidItemModelProxy::beginMoveColumns,
|
||||||
|
QAndroidModelIndexProxy::qInstance(sourceParent), sourceFirst, sourceLast,
|
||||||
|
QAndroidModelIndexProxy::qInstance(destinationParent), destinationChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
jboolean QAndroidItemModelProxy::jni_beginMoveRows(JNIEnv *env, jobject object,
|
||||||
|
JQtModelIndex sourceParent, jint sourceFirst,
|
||||||
|
jint sourceLast, JQtModelIndex destinationParent,
|
||||||
|
jint destinationChild)
|
||||||
|
{
|
||||||
|
return invokeNativeProxyMethod(
|
||||||
|
env, object, &QAndroidItemModelProxy::beginMoveRows,
|
||||||
|
QAndroidModelIndexProxy::qInstance(sourceParent), sourceFirst, sourceLast,
|
||||||
|
QAndroidModelIndexProxy::qInstance(destinationParent), destinationChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidItemModelProxy::jni_beginRemoveColumns(JNIEnv *env, jobject object,
|
||||||
|
JQtModelIndex parent, jint first, jint last)
|
||||||
|
{
|
||||||
|
invokeNativeProxyMethod(env, object, &QAndroidItemModelProxy::beginRemoveColumns,
|
||||||
|
QAndroidModelIndexProxy::qInstance(parent), first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidItemModelProxy::jni_beginRemoveRows(JNIEnv *env, jobject object, JQtModelIndex parent,
|
||||||
|
jint first, jint last)
|
||||||
|
{
|
||||||
|
invokeNativeProxyMethod(env, object, &QAndroidItemModelProxy::beginRemoveRows,
|
||||||
|
QAndroidModelIndexProxy::qInstance(parent), first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidItemModelProxy::jni_beginResetModel(JNIEnv *env, jobject object)
|
||||||
|
{
|
||||||
|
invokeNativeProxyMethod(env, object, &QAndroidItemModelProxy::beginResetModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidItemModelProxy::jni_endInsertColumns(JNIEnv *env, jobject object)
|
||||||
|
{
|
||||||
|
invokeNativeProxyMethod(env, object, &QAndroidItemModelProxy::endInsertColumns);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidItemModelProxy::jni_endInsertRows(JNIEnv *env, jobject object)
|
||||||
|
{
|
||||||
|
invokeNativeProxyMethod(env, object, &QAndroidItemModelProxy::endInsertRows);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidItemModelProxy::jni_endMoveColumns(JNIEnv *env, jobject object)
|
||||||
|
{
|
||||||
|
invokeNativeProxyMethod(env, object, &QAndroidItemModelProxy::endMoveColumns);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidItemModelProxy::jni_endMoveRows(JNIEnv *env, jobject object)
|
||||||
|
{
|
||||||
|
invokeNativeProxyMethod(env, object, &QAndroidItemModelProxy::endMoveRows);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidItemModelProxy::jni_endRemoveColumns(JNIEnv *env, jobject object)
|
||||||
|
{
|
||||||
|
invokeNativeProxyMethod(env, object, &QAndroidItemModelProxy::endRemoveColumns);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidItemModelProxy::jni_endRemoveRows(JNIEnv *env, jobject object)
|
||||||
|
{
|
||||||
|
invokeNativeProxyMethod(env, object, &QAndroidItemModelProxy::endRemoveRows);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidItemModelProxy::jni_endResetModel(JNIEnv *env, jobject object)
|
||||||
|
{
|
||||||
|
invokeNativeProxyMethod(env, object, &QAndroidItemModelProxy::endResetModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject QAndroidItemModelProxy::jni_sibling(JNIEnv *env, jobject object, jint row, jint column,
|
||||||
|
JQtModelIndex parent)
|
||||||
|
{
|
||||||
|
const QModelIndex index = invokeNativeImpl(env, object, &QAndroidItemModelProxy::siblingDefault,
|
||||||
|
&QAbstractItemModel::sibling, row, column,
|
||||||
|
QAndroidModelIndexProxy::qInstance(parent));
|
||||||
|
return env->NewLocalRef(QAndroidModelIndexProxy::jInstance(index).object());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QAndroidItemModelProxy::registerAbstractNatives(QJniEnvironment &env)
|
||||||
|
{
|
||||||
|
return env.registerNativeMethods(
|
||||||
|
Traits<JQtAbstractItemModel>::className(),
|
||||||
|
{ Q_JNI_NATIVE_SCOPED_METHOD(jni_roleNames, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_canFetchMore, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_createIndex, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_fetchMore, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_hasChildren, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_hasIndex, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_beginInsertColumns, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_beginInsertRows, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_beginMoveColumns, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_beginMoveRows, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_beginRemoveColumns, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_beginRemoveRows, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_beginResetModel, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_endInsertColumns, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_endInsertRows, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_endMoveColumns, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_endMoveRows, QAndroidItemModelProxy),
|
||||||
|
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) });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QAndroidItemModelProxy::registerProxyNatives(QJniEnvironment &env)
|
||||||
|
{
|
||||||
|
return env.registerNativeMethods(
|
||||||
|
Traits<JQtAndroidItemModelProxy>::className(),
|
||||||
|
{ Q_JNI_NATIVE_SCOPED_METHOD(jni_columnCount, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_data, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_index, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_parent, QAndroidItemModelProxy),
|
||||||
|
Q_JNI_NATIVE_SCOPED_METHOD(jni_rowCount, QAndroidItemModelProxy) });
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
190
src/corelib/platform/android/qandroiditemmodelproxy_p.h
Normal file
190
src/corelib/platform/android/qandroiditemmodelproxy_p.h
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
#ifndef QANDROIDITEMMODELPROXY_P_H
|
||||||
|
#define QANDROIDITEMMODELPROXY_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
|
||||||
|
#include <QtCore/private/qandroidmodelindexproxy_p.h>
|
||||||
|
#include <QtCore/private/qandroidtypes_p.h>
|
||||||
|
|
||||||
|
#include <QtCore/qabstractitemmodel.h>
|
||||||
|
#include <QtCore/qjniobject.h>
|
||||||
|
#include <QtCore/qjnienvironment.h>
|
||||||
|
#include <QtCore/qjnitypes.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class Q_CORE_EXPORT QAndroidItemModelProxy : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit QAndroidItemModelProxy(QtJniTypes::JQtAbstractItemModel jInstance)
|
||||||
|
: jInstance(jInstance)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
QModelIndex index(int row, int column,
|
||||||
|
const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QModelIndex parent(const QModelIndex &index) const override;
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
bool canFetchMore(const QModelIndex &parent) const override;
|
||||||
|
bool canFetchMoreDefault(const QModelIndex &parent) const;
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
QHash<int, QByteArray> defaultRoleNames() const;
|
||||||
|
void fetchMore(const QModelIndex &parent) override;
|
||||||
|
void fetchMoreDefault(const QModelIndex &parent);
|
||||||
|
bool hasChildren(const QModelIndex &parent) const override;
|
||||||
|
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);
|
||||||
|
|
||||||
|
Q_REQUIRED_RESULT static QAbstractItemModel *
|
||||||
|
nativeInstance(QtJniTypes::JQtAbstractItemModel itemModel);
|
||||||
|
Q_REQUIRED_RESULT static QAbstractItemModel *createNativeProxy(QJniObject itemModel);
|
||||||
|
static QJniObject createProxy(QAbstractItemModel *abstractClass);
|
||||||
|
|
||||||
|
template <typename Func, typename... Args>
|
||||||
|
static auto invokeNativeProxyMethod(JNIEnv */*env*/, jobject jvmObject, Func func, Args &&...args)
|
||||||
|
{
|
||||||
|
Q_ASSERT(jvmObject);
|
||||||
|
auto model = qobject_cast<QAndroidItemModelProxy *>(nativeInstance(jvmObject));
|
||||||
|
Q_ASSERT(model);
|
||||||
|
return std::invoke(func, model, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Func, typename... Args>
|
||||||
|
static auto invokeNativeMethod(JNIEnv */*env*/, jobject jvmObject, Func func, Args &&...args)
|
||||||
|
{
|
||||||
|
Q_ASSERT(jvmObject);
|
||||||
|
auto model = nativeInstance(jvmObject);
|
||||||
|
Q_ASSERT(model);
|
||||||
|
return std::invoke(func, model, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Func1, typename Func2, typename... Args>
|
||||||
|
static auto invokeNativeImpl(JNIEnv */*env*/, jobject jvmObject, Func1 defaultFunc, Func2 func,
|
||||||
|
Args &&...args)
|
||||||
|
{
|
||||||
|
Q_ASSERT(jvmObject);
|
||||||
|
auto nativeModel = nativeInstance(jvmObject);
|
||||||
|
auto nativeProxyModel = qobject_cast<QAndroidItemModelProxy *>(nativeModel);
|
||||||
|
if (nativeProxyModel)
|
||||||
|
return std::invoke(defaultFunc, nativeProxyModel, std::forward<Args>(args)...);
|
||||||
|
else
|
||||||
|
return std::invoke(func, nativeModel, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
static jint jni_columnCount(JNIEnv *env, jobject object, JQtModelIndex parent);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_columnCount)
|
||||||
|
|
||||||
|
static jobject jni_data(JNIEnv *env, jobject object, JQtModelIndex index, jint role);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_data)
|
||||||
|
|
||||||
|
static jobject jni_index(JNIEnv *env, jobject object, jint row, jint column,
|
||||||
|
JQtModelIndex parent);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_index)
|
||||||
|
|
||||||
|
static jobject jni_parent(JNIEnv *env, jobject object, JQtModelIndex index);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_parent)
|
||||||
|
|
||||||
|
static jint jni_rowCount(JNIEnv *env, jobject object, JQtModelIndex parent);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_rowCount)
|
||||||
|
|
||||||
|
static jboolean jni_canFetchMore(JNIEnv *env, jobject object, JQtModelIndex parent);
|
||||||
|
QT_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE_2(jni_canFetchMore, canFetchMore)
|
||||||
|
|
||||||
|
static void jni_fetchMore(JNIEnv *env, jobject object, JQtModelIndex parent);
|
||||||
|
QT_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE_2(jni_fetchMore, fetchMore)
|
||||||
|
|
||||||
|
static jboolean jni_hasChildren(JNIEnv *env, jobject object, JQtModelIndex parent);
|
||||||
|
QT_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE_2(jni_hasChildren, hasChildren)
|
||||||
|
|
||||||
|
static jboolean jni_hasIndex(JNIEnv *env, jobject object, jint row, jint column,
|
||||||
|
JQtModelIndex parent);
|
||||||
|
QT_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE_2(jni_hasIndex, hasIndex)
|
||||||
|
|
||||||
|
static jobject jni_roleNames(JNIEnv *env, jobject object);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_roleNames)
|
||||||
|
|
||||||
|
static void jni_beginInsertColumns(JNIEnv *env, jobject object, JQtModelIndex parent,
|
||||||
|
jint first, jint last);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_beginInsertColumns)
|
||||||
|
|
||||||
|
static void jni_beginInsertRows(JNIEnv *env, jobject object, JQtModelIndex parent, jint first,
|
||||||
|
jint last);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_beginInsertRows)
|
||||||
|
|
||||||
|
static jboolean jni_beginMoveColumns(JNIEnv *env, jobject object, JQtModelIndex sourceParent,
|
||||||
|
jint sourceFirst, jint sourceLast,
|
||||||
|
JQtModelIndex destinationParent, jint destinationChild);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_beginMoveColumns)
|
||||||
|
|
||||||
|
static jboolean jni_beginMoveRows(JNIEnv *env, jobject object, JQtModelIndex sourceParent,
|
||||||
|
jint sourceFirst, jint sourceLast,
|
||||||
|
JQtModelIndex destinationParent, jint destinationChild);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_beginMoveRows)
|
||||||
|
|
||||||
|
static void jni_beginRemoveColumns(JNIEnv *env, jobject object, JQtModelIndex parent,
|
||||||
|
jint first, jint last);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_beginRemoveColumns)
|
||||||
|
|
||||||
|
static void jni_beginRemoveRows(JNIEnv *env, jobject object, JQtModelIndex parent, jint first,
|
||||||
|
jint last);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_beginRemoveRows)
|
||||||
|
|
||||||
|
static void jni_beginResetModel(JNIEnv *env, jobject object);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_beginResetModel)
|
||||||
|
|
||||||
|
static jobject jni_createIndex(JNIEnv *env, jobject object, jint row, jint column, jlong id);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_createIndex)
|
||||||
|
|
||||||
|
static void jni_endInsertColumns(JNIEnv *env, jobject object);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_endInsertColumns)
|
||||||
|
|
||||||
|
static void jni_endInsertRows(JNIEnv *env, jobject object);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_endInsertRows)
|
||||||
|
|
||||||
|
static void jni_endMoveColumns(JNIEnv *env, jobject object);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_endMoveColumns)
|
||||||
|
|
||||||
|
static void jni_endMoveRows(JNIEnv *env, jobject object);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_endMoveRows)
|
||||||
|
|
||||||
|
static void jni_endRemoveColumns(JNIEnv *env, jobject object);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_endRemoveColumns)
|
||||||
|
|
||||||
|
static void jni_endRemoveRows(JNIEnv *env, jobject object);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_endRemoveRows)
|
||||||
|
|
||||||
|
static void jni_endResetModel(JNIEnv *env, jobject object);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_endResetModel)
|
||||||
|
|
||||||
|
static jobject jni_sibling(JNIEnv *env, jobject object, jint row, jint column,
|
||||||
|
JQtModelIndex parent);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(jni_sibling)
|
||||||
|
|
||||||
|
static bool registerAbstractNatives(QJniEnvironment &env);
|
||||||
|
static bool registerProxyNatives(QJniEnvironment &env);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QJniObject jInstance;
|
||||||
|
friend class QAndroidModelIndexProxy;
|
||||||
|
};
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // QANDROIDITEMMODELPROXY_P_H
|
103
src/corelib/platform/android/qandroidmodelindexproxy.cpp
Normal file
103
src/corelib/platform/android/qandroidmodelindexproxy.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
// 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 <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();
|
||||||
|
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<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
|
55
src/corelib/platform/android/qandroidmodelindexproxy_p.h
Normal file
55
src/corelib/platform/android/qandroidmodelindexproxy_p.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
#ifndef QANDROIDMODELINDEXPROXY_P_H
|
||||||
|
#define QANDROIDMODELINDEXPROXY_P_H
|
||||||
|
|
||||||
|
#include <QtCore/private/qandroidtypes_p.h>
|
||||||
|
|
||||||
|
#include <QtCore/qabstractitemmodel.h>
|
||||||
|
#include <QtCore/qjniobject.h>
|
||||||
|
#include <QtCore/qjnienvironment.h>
|
||||||
|
#include <QtCore/qjnitypes.h>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
using namespace QtJniTypes;
|
||||||
|
|
||||||
|
class QAndroidItemModelProxy;
|
||||||
|
|
||||||
|
class Q_CORE_EXPORT QAndroidModelIndexProxy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static JQtModelIndex jInstance(QModelIndex modelIndex);
|
||||||
|
static QModelIndex qInstance(JQtModelIndex jModelIndex);
|
||||||
|
|
||||||
|
static jobject data(JNIEnv *env, jobject object, int role);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(data)
|
||||||
|
|
||||||
|
static jlong internalId(JNIEnv *env, jobject object);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(internalId)
|
||||||
|
|
||||||
|
static jboolean isValid(JNIEnv *env, jobject object);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(isValid)
|
||||||
|
|
||||||
|
static JQtModelIndex parent(JNIEnv *env, jobject object);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(parent)
|
||||||
|
|
||||||
|
static bool registerNatives(QJniEnvironment &env);
|
||||||
|
};
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
#endif // QANDROIDMODELINDEXPROXY_P_H
|
@ -14,8 +14,8 @@
|
|||||||
//
|
//
|
||||||
// We mean it.
|
// We mean it.
|
||||||
|
|
||||||
#include <QtQuick/private/qandroidtypes_p.h>
|
#include <QtCore/private/qandroidtypes_p.h>
|
||||||
#include <QtQuick/private/qandroiditemmodelproxy_p.h>
|
#include <QtCore/private/qandroiditemmodelproxy_p.h>
|
||||||
|
|
||||||
#include <QtCore/qjniobject.h>
|
#include <QtCore/qjniobject.h>
|
||||||
#include <QtCore/qjnienvironment.h>
|
#include <QtCore/qjnienvironment.h>
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
#include <QtCore/qresource.h>
|
#include <QtCore/qresource.h>
|
||||||
#include <QtCore/qscopeguard.h>
|
#include <QtCore/qscopeguard.h>
|
||||||
#include <QtCore/qthread.h>
|
#include <QtCore/qthread.h>
|
||||||
|
#include <QtCore/private/qandroiditemmodelproxy_p.h>
|
||||||
|
#include <QtCore/private/qandroidmodelindexproxy_p.h>
|
||||||
#include <QtGui/private/qguiapplication_p.h>
|
#include <QtGui/private/qguiapplication_p.h>
|
||||||
#include <QtGui/private/qhighdpiscaling_p.h>
|
#include <QtGui/private/qhighdpiscaling_p.h>
|
||||||
|
|
||||||
@ -881,7 +883,10 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
|
|||||||
|| !QAndroidPlatformClipboard::registerNatives(env)
|
|| !QAndroidPlatformClipboard::registerNatives(env)
|
||||||
|| !QAndroidPlatformWindow::registerNatives(env)
|
|| !QAndroidPlatformWindow::registerNatives(env)
|
||||||
|| !QtAndroidWindowEmbedding::registerNatives(env)
|
|| !QtAndroidWindowEmbedding::registerNatives(env)
|
||||||
|| !AndroidBackendRegister::registerNatives()) {
|
|| !AndroidBackendRegister::registerNatives()
|
||||||
|
|| !QAndroidModelIndexProxy::registerNatives(env)
|
||||||
|
|| !QAndroidItemModelProxy::registerAbstractNatives(env)
|
||||||
|
|| !QAndroidItemModelProxy::registerProxyNatives(env)) {
|
||||||
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
|
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user