I'm attempting to create a tree view in QT using Java to display something similar to
+ Category A
| + Category AB
| | Item AB
| \ Item A
+ Category B
| \ Item B
\ Item
with a custom QAbstractItemModel
while following the guide.
There seems to be some issues with how Qt Jambi has implemented the wrapper for QModelIndex
. There doesn't appear to be a way to create new instances of it like you can in the Qt guide and it appears to be missing function wrappers (at least isValid
and internalPointer
).
Here is the code I currently have based on the guide:
TreeModel
package playground;
import io.qt.core.*;
import java.util.stream.Stream;
public final class TreeModel extends QAbstractItemModel {
private final TreeItem rootItem;
public TreeModel(QString data, QObject parent) {
super(parent);
rootItem = new TreeItem(Stream.of(tr("Title"), tr("Summary")).map(QVariant::new).toList(), null);
setupModelData(data.split('\n'), rootItem);
}
private void setupModelData(QStringList split, TreeItem rootItem) {
//TODO
}
@Override
public QModelIndex index(int row, int column, QModelIndex parent) {
if(!hasIndex(row, column, parent)) {
return new QModelIndex();
}
var parentItem = !parent.isValid() ? rootItem : parent.internalPointer();
var child = parentItem.child(row);
return child != null ? createIndex(row, column, childItem) : new QModelIndex();
}
@Override
public QModelIndex parent(QModelIndex index) {
if(!index.isValid()) {
return new QModelIndex();
}
var childItem = index.internalPointer();
var parentItem = childItem.parentItem();
if(parentItem == rootItem) {
return new QModelIndex();
}
return createIndex(parentItem.row(), 0, parentItem);
}
@Override
public int rowCount(QModelIndex parent) {
if(parent.column() > 0) {
return 0;
}
var parentItem = !parent.isValid() ? rootItem : parent.internalPointer();
return parentItem.childCount();
}
@Override
public int columnCount(QModelIndex parent) {
return (parent.isValid() ? parent.internalPointer() : rootItem).columnCount();
}
@Override
public Object data(QModelIndex index, int role) {
if(!index.isValid()) {
return new QVariant();
}
if(role != Qt.ItemDataRole.DisplayRole) {
return new QVariant();
}
var item = index.internalPointer();
return item.data(index.column());
}
@Override
public Qt.ItemFlags flags(QModelIndex index) {
return !index.isValid() ? new Qt.ItemFlags() : index.flags();
}
@Override
public Object headerData(int section, Qt.Orientation orientation, int role) {
if(orientation == Qt.Orientation.Horizontal && role == Qt.ItemDataRole.DisplayRole) {
return rootItem.data(section);
}
return new QVariant();
}
}
TreeItem
:
package playground;
import io.qt.core.QVariant;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public final class TreeItem {
private final List<TreeItem> childItems = new ArrayList<>();
private final List<QVariant> itemData = new ArrayList<>();
private final TreeItem parentItem;
public TreeItem(List<QVariant> data, TreeItem parent) {
this.itemData.addAll(data);
this.parentItem = parent;
}
public void appendChild(TreeItem child) {
Objects.requireNonNull(child);
childItems.add(child);
}
public TreeItem child(int row) {
if(row < 0 || row >= childItems.size()) {
return null;
}
return childItems.get(row);
}
public int childCount() {
return childItems.size();
}
public int columnCount() {
return itemData.size();
}
public QVariant data(int column) {
if(column < 0 || column >= itemData.size()) {
return null;
}
return itemData.get(column);
}
public int row() {
if(parentItem != null) {
return parentItem.childItems.indexOf(this);
}
return 0;
}
public TreeItem parentItem() {
return parentItem;
}
}