QTreeView displays one top level item and wrong children
-
This problem might be a little bit too involved for here but here goes.
We're moving some code to Qt5.1 (currently it uses VCL) and would like to use a QTreeView for displaying one of the data structures.
The data structure is a kind of stack where each item in the stack has a number of items in it. These items have no children. I've modified the stack data structure to be our model. Looks kind of like this
|StackEntry1
- -itemA
- -itemB
|StackEntry0
--itemX
--itemY
--itemZ
The data structure itself appears to be quite solid. Children are pointing to the right parent objects and vise versa. However, when I connect the model to the view there is some odd behavior.
At load everythign is fine, the first thing pushed onto the stack appears in the view, all its children are there.
|StackEntry0
--itemX
--itemY
However, once I push anything else onto the stack, the view displays the new item's name as the top item, and displays the original item's children underneath.|StackEntry1
--itemX
--itemYI'm also noticing that
data() never gets called on StackEntry0 once we add StackEntry1
rowcount() only counts the two StackEntries once when I try expanding StackEntry1
Below is the code for the QTreeView methods. The objects in the stack are ModeStackMenuEntry. The StackEntryNs above are of type Mode and the ItemN are of type ModeEntry
@QModelIndex ModeStack::index(int row, int column, QModelIndex const &parent) const {
ModeStackMenuEntry parent_entry = NULL;
Mode parent_mode = NULL;
ModeEntry child_entry = NULL;
if (!parent.isValid()) {//juts get top level Mode
parent_mode = const_cast<Mode>(ModeAt(row));
if (!parent_mode) return QModelIndex();
QString foo = parent_mode->GetName();
return createIndex(row, column, parent_mode);
}
parent_entry = static_cast<ModeStackMenuEntry>(parent.internalPointer());
parent_mode = dynamic_cast<Mode>(parent_entry);if (parent_mode) { std::string goober = parent_mode->GetName().toUtf8().data(); char g = goober[0]; if (row < parent_mode->count()) child_entry = &parent_mode->GetEntry(row); } else { return QModelIndex(); } if (child_entry) { return createIndex(row, column, child_entry); } return QModelIndex();
}
QModelIndex ModeStack::parent(QModelIndex const &index) const {
if (!index.isValid())
return QModelIndex();ModeStackMenuEntry *row_ptr = static_cast<ModeStackMenuEntry*>(index.internalPointer()); Mode *item = NULL, *item_parent = NULL; ModeEntry *entry = NULL; item = dynamic_cast<Mode*>(row_ptr); if (item) { return QModelIndex(); } else { entry = dynamic_cast<ModeEntry*>(row_ptr); if (entry) { return createIndex(StackIndex(*entry->parent()), 0, entry->parent()); } } return createIndex(item_parent->GetModeEntryIndex(*entry), 0, item_parent);
}
int ModeStack::rowCount(QModelIndex const &parent) const {
int ret = 0;
ModeStackMenuEntry* item = NULL;
if (parent.column() > 0)
ret = 0;
else if (!parent.isValid())
ret = StackDepth();
else {
item = static_cast<ModeStackMenuEntry*>(parent.internalPointer());
ret = item->count();
}
return ret;
}
int ModeStack::columnCount( QModelIndex const &parent) const {
EntryType type = GetEntryType(parent);
if (type == EntryType::ModeEntry)
return 1;
return 2;
}
QVariant ModeStack::data(QModelIndex const &index, int role) const {
if (role != Qt::DisplayRole)
return QVariant();
if (!index.isValid())
return QVariant();
ModeStackMenuEntry item = static_cast<ModeStackMenuEntry>(index.internalPointer());
return item->GetText(index.column());
}bool ModeStack::hasChildren(QModelIndex const &parent) const {
bool b = false;
b = rowCount(parent) > 0;return b;
}@
-
An interesting development. I was thinking maybe the life of the QModelIndexes was somewhat, borked.
We're using a stack here, so What is at Index 0 in the beginning, ends up being moved to Index 1 when a new item is put in. I theorized that maybe this was messing up the QModelIndexes.
I tried turning out Stack into a simple List. Instead of being put on tpo, the new items get put at the end. Now intead of getting a second item, i get nothign new in the model. However, rowCoutn is still returning 2 when it checks the Model. Odd.
-
Ok so i've got it 'working' now. However, i'm skeptical.
By adding a line
@emit(layoutChanged())@in my model whenever I add or remove something from the stack, everything updates properly. Is this good practice?
-
How do You add/remove items from this stack?
Did You read "this":https://qt-project.org/doc/qt-4.8/model-view-programming.html#inserting-and-removing-rows? This should explain hot to insert/remove rows from/to Your model.
Hope this will help You,
Robert
-
Hi Robert,
Right now there are simply some Push/Pop methods in the class that handle adding/removing data.
I suspect that the information you linked will solve our problems but this will require some serious refactoring to get working. Once that's finished I will post back.
-
If You have any doubts just write them down. I will try to help You :).
Robert