Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to create a Tree of abstract object instances?



  • Hi,

    I have an abstract class, Foo, that has two properties; Name and Type. Name is populated in the constructor with a random hash (placeholder) and Type is hardcoded in any implementation of Foo.

    What I would like is to have a QTreeView that displays the Name and Type of each Foo instance.
    I would like the view to support internal drag and drop (to reorganise the tree), Copy/Paste and Undo/Redo.

    My efforts so far are the result of pulling apart the tree demo and tying together the display columns with the Foo object (Bar implements Foo):

    Model:
    @
    TreeNode *TreeModel::getNode(const QModelIndex &index) const
    {
    if(index.isValid()) {
    TreeNode item = static_cast<TreeNode>(index.internalPointer());
    if(item) {
    return item;
    }
    }
    return m_rootItem;
    }

    bool TreeModel::setFoo(Foo * foo, int row, const QModelIndex &parent)
    {
    bool result = false;
    QModelIndex i = index(row, 0, parent);
    TreeNode node = getNode(i);
    result = node->setFoo(QVariant::fromValue<Foo
    >(foo));
    return result;
    }

    QVariant TreeModel::data(const QModelIndex &index, int role) const
    {
    QVariant result = QVariant();
    if(index.isValid()) {
    if(role == Qt::DisplayRole || role == Qt::EditRole) {
    TreeNode *node = getNode(index);
    switch(column)
    {
    case TreeModel::NameColumn:
    result = node->getName();
    break;
    case TreeModel::TypeColumn:
    result = node->getType();
    break;
    }
    }
    }
    return result;
    }
    @

    TreeNode:
    @
    bool TreeNode::setFoo(const QVariant &value)
    {
    m_foo_instance = value.value<Foo *>();
    return true;
    }

    QVariant TreeNode::getName() const
    {
    Q_ASSERT(m_foo_instance);
    return QVariant(m_foo_instance->Name());
    }

    QVariant TreeNode::getType() const
    {
    Q_ASSERT(m_foo_instance);
    return QVariant(m_foo_instance->Type());
    }
    @

    Adding a node to the tree:
    @
    int row = model->rowCount(parent);
    model->insertRow(row, parent);
    model->setFoo(new Bar(), row, parent);
    @

    This all works but things got complicated with drag and drop when I needed to add mimeData. The only solution I could think of was to have a hash somewhere with all the Foo instances and create QMimeData from the key value. Just seems overkill when all I want to do is change the parent value of TreeNode.

    Alternatively I have exactly what I want when I use QTreeWidget (with drag/drop) but adding Undo/Redo and Copy/Paste is proving tricky.

    Am I going about this the right way?
    Is there a better way to 'have a tree of objects'?
    Would I be better of adding copy/paste/undo/redo to the QTreeWidget?

    Any help or advice would be greatly appreciated.

    Thanks



  • Abstract classes cannot be instantiated, so it is technically impossible to create a tree out of such.



  • Thanks for the reply.

    I understand what you are saying but I am dealing with instances that implement the abstract class. The code above works, so far as creating items in a QTreeItemView, I was just wondering if there is a better way that would allow easy addition of Copy/Paste and Undo/Redo.

    The class Bar in the above code implements Foo which you can see being instantiated in the last few lines.


Log in to reply