Important: Please read the Qt Code of Conduct -

QTreeView doesn't show any content

  • Hello folks,

    I'm currently experiencing an issue with a QTreeView and a custom subclass of QAbstractItemModel: The model is working well and returns the data it's supposed to return (I confirmed that with qDebug() everywhere) but the QTreeView never shows any data. I experienced that issues multiple times in the past when I first started to work with Qt models and that was always due to missing calls to beginInsertRows() and endInsertRows() in my model subclass but that's not the problem here.

    I also tried using other views such as QTableView and QListView. It's always the same: The model appears to operate properly internally but the view doesn't show any content. Interesting is the fact that when I move the mouse cursor inside the view I see that the data() method gets triggered all the time and according to the qDebug() it also returns the correct data (a valid non-empty QVariant object).

    I'd appreciate any help on this. Here are my sources:

    Additional info:

    • Qt 5.8.0 on Windows 10 using MinGW 5.3.0 32-bit
    • The FindWidget::resultReady() method contains a qDebug() on the model's rowCount() which returns the expected non-zero value equal to the number of results that have been added to the model.

  • Moderators

    I just skimmed through the code, but at a first glance there are at least couple of bugs there:

    • The reintrpret_cast usage is completely wrong. That's definitely not what you meant. reinterpret_cast is a "Stay away compiler, I totally know what I'm doing" cast i.e. it will always succeed no matter if the types are related in any way or not. Needless to say you are often casting things assuming you'll get null if the thing is not the thing, but what you actually get is a garbage pointer.
    • You are not checking the role parameter in ResultsModel::data which means you return a string for everything, including things like background color, font or size hint. You should only return that string if role == Qt::DisplayRole.
    • Your implementation of rowCount creates a tree of infinite depth because you're only checking for the top level and returning the number of files. For the second level you return the number of lines. For the third level you return the number of lines of something... and so on.
    • In the implementation of ResultsModel::addResult you should call index instead of createIndex. The only methods using createIndex() directly should probably be index() and parent().

    I hadn't time to go through the index() and parent() in detail, but by the sole amount of for loops for a simple two-level tree I'm betting there's something wrong there too. Keep in mind that index() and parent() are the most often called methods. It can easily go into hundreds at a time in a medium size data set. They should be as simple as possible and I have yet to see a case where a loop over everything would be needed.

  • Hello Chris, glad to see that you're still around! :)

    • I agree with you that the use of reinterpret_cast is not proper here. This was meant to be just a very quick proof-of-concept implementation of a file search tool. I always find it somewhat inconvenient to pass pointers via QVariant so being a bit in a hurry I decided to go the good old "I know what I'm doing" way.
    • The QTreeView is showing the expected data now that I added a check for role != Qt::DisplayRole in my data() method. I'm not sue how I could miss that. After all, it's not the first time I'm dealing with that. Probably one shouldn't do just quick proof-of-concept implementations of models :p
    • Regarding the rowCount() implementation: In my opinion this is correct. After all, this model only supports two levels of depth. It's just a list of files that contain multiple sub-results in form of line numbers. Or am I missing something? This is the first time I'm implementing a somewhat "make shift" model. I regret it already.
    • Good catch on the createIndex() instead of index() call in addResult(). I missed that one!

    Thank you a lot for your help. Much appreciated!

  • Err... I just realize what you actually were referring to regarding the issue with reinterpret_cast.... Thanks Chris, much appreciated, as always! :)

  • Moderators

    After all, this model only supports two levels of depth.

    Well yeah, you and I know that. But how is the tree view suppose to know that? It's not like it understands your intent ;)
    The view discovers the amount of levels by calling rowCount() until it returns 0, and you never do that (if there are any lines added) so it will let you expand and expand until it probably crashes at some point if you stumble upon an out of range index.

  • Chris, thank you a lot for your time to look into this. I appreciate it a lot.
    I'll rewrite this properly. There's no point in going quick proof-of-concept on something like this.

Log in to reply