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

Probably a newbie problem about custom tree structure and QDataWidgetMapper...



  • Hello there,
    I've built a custom tree model by inheriting QAbstractItemModel and displayed the data with a QTreeView object successfully.

    The problem is that when I was trying to map the data of the model to some QLineEdit objects, they didn't give me a crap (nothing showed up).

    alt text
    The "data" function in the tree model returns "QString".

    I called "setCurrentModelIndex()" of the QDataWidgetMapper to set up the model index to be that of "Gray". I expected the 3 QLineEdit objects to display "Peter", "Robert", and "Amber".

    Could anyone give me a hint about what I missed?

    // The mainwindow object implementation
    MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
    {
        manageWindow();
        resize(600,400);
    }
    
    MainWindow::~MainWindow(){
    
    }
    
    void MainWindow::setDataModel(){
    
    }
    
    void MainWindow::manageWindow(){
        TreeModel* model = new TreeModel;
        QItemSelectionModel* selection = new QItemSelectionModel;
        selection->setModel(model);
        QSplitter* splitter = new QSplitter(this);
        QTreeView* treeView = new QTreeView(this);
        //FamilyTreeDelegate *delegate = new FamilyTreeDelegate();
    
        treeView->setModel(model);
        treeView->setAnimated(true);
        treeView->setHeaderHidden(true);
        //treeView->setSelectionModel(selection);
    
        DataMapperWidget* mapper = new DataMapperWidget(model);
    
        splitter->addWidget(treeView);
        splitter->addWidget(mapper);
        splitter->setSizes({150,150});
        setCentralWidget(splitter);
    }
    

    The implementation below is that of the widget with QDataWidgetMapper.

    //The widget with the QDataWidgetMapper
    DataMapperWidget::DataMapperWidget(QAbstractItemModel* model,
                                       QWidget *parent) : QWidget(parent)
    {
        setWidgets();
        setModel(model);
    }
    
    DataMapperWidget::~DataMapperWidget()
    {
    
    }
    
    void DataMapperWidget::setWidgets()
    {
        QFormLayout* layout = new QFormLayout;
        layout->setSpacing(20);
        layout->setContentsMargins(30,30,30,30);
    
        edit1 = new QLineEdit;
        edit2 = new QLineEdit;
        edit3 = new QLineEdit;
        layout->addWidget(edit1);
        layout->addWidget(edit2);
        layout->addWidget(edit3);
        setLayout(layout);
        resize(400,200);
    }
    
    
    void DataMapperWidget::setModel(QAbstractItemModel *model)
    {
        mapper = new QDataWidgetMapper(this);
        mapper->setOrientation(Qt::Vertical);
    
    
        mapper->setModel(model);
        QModelIndex parentIndex = model->index(0,0,QModelIndex());
    
        mapper->setCurrentModelIndex(parentIndex);
        mapper->addMapping(edit1, 0);
        mapper->addMapping(edit2, 1);
        mapper->addMapping(edit3, 2);
        mapper->toFirst();
    }
    

    And this is the implementation of the custom tree model:

    // the treemodel
    TreeModel::TreeModel(QObject* parent): QAbstractItemModel (parent){
      Family = new FamilyMember("Family");
      setModelData();
    }
    
    TreeModel::~TreeModel(){
        delete Family;
    }
    
    QVariant TreeModel::data(const QModelIndex &index, int role) const{
        if (!index.isValid())
            return QVariant();
    
        if (role != Qt::DisplayRole)
            return QVariant();
    
        FamilyMember* item = static_cast<FamilyMember*>(index.internalPointer());
        return item->name;
        //QVariant v;
        //v.setValue(*item);
        //return v;
    
    }
    
    QModelIndex TreeModel::index(int row, int column, const QModelIndex& parent) const{
        if (hasIndex(row, column, parent))
        {
            if (parent.isValid()){
                FamilyMember* parentItem = static_cast<FamilyMember*>(parent.internalPointer());
                FamilyMember* childItem = parentItem->child(row);
                return createIndex(row, 0, childItem);
            }
            FamilyMember* parentItem = Family;
            FamilyMember* childItem = parentItem->child(row);
            return createIndex(row, 0, childItem);
        }
    
        return QModelIndex();
    }
    
    int TreeModel::rowCount(const QModelIndex &parent) const{
        FamilyMember* parentMember;
        if (!parent.isValid())
            parentMember = Family;
        else {
            parentMember = static_cast<FamilyMember*>(parent.internalPointer());
        }
    
        return parentMember->numberOfChildren();
    
    }
    
    int TreeModel::columnCount(const QModelIndex &parent) const{
        Q_UNUSED(parent);
        return 1;
    }
    
    QModelIndex TreeModel::parent(const QModelIndex &index) const{
        if (!index.isValid())
            return QModelIndex();
        FamilyMember* childrenItem = static_cast<FamilyMember*>(index.internalPointer());
        FamilyMember* ParentItem = childrenItem->parentItem();
    
        if (ParentItem == Family){
            return QModelIndex();
        }
        return createIndex(ParentItem->row(), 0, ParentItem);
    }
    
    void TreeModel::setModelData(){
    
    FamilyMember* grandParent = new FamilyMember("grandparent", "Gray", 98 , Family);
    FamilyMember* Parent = new FamilyMember("parent", "Peter", 40, grandParent);
    FamilyMember* uncle = new FamilyMember("uncle", "Robert", 38, grandParent);
    FamilyMember* aunt = new FamilyMember("aunt", "Amber", 30, grandParent);
    FamilyMember* son = new FamilyMember("son", "Sean", 11 ,Parent);
    FamilyMember* daughter = new FamilyMember("daughter", "Diana", 12 , Parent);
    FamilyMember* sonOfUncle = new FamilyMember("Son of uncle", "Sam", 13 ,uncle);
    FamilyMember* daughterOfUncle = new FamilyMember("Daughter of uncle", "Dann", 14, uncle);
    FamilyMember* sonOfAunt = new FamilyMember("Son of aunt", "Ethan ", 15,aunt);
    FamilyMember* daughterOfAunt = new FamilyMember("Daughter of aunt", "Emily" ,16, aunt);
    FamilyMember* daughterOfDaughterOfAunt = new FamilyMember("Daughter of daughter of aunt",
                                                              "Sarah", 1, daughterOfAunt);
    }
    
    

    This is the object definition used in the treemodel:

    // Familymember class
    FamilyMember::FamilyMember(){}
    
    FamilyMember::FamilyMember(const QString& Appellation, const QString& Name,
                               const int& Age, FamilyMember* parent)
    {
        appellation = Appellation;
        name = Name;
        age = Age;
        m_parent = parent;
        if (parent)
        {
           m_parent->appendChildItem(this);
        }
    }
    
    FamilyMember::FamilyMember(const FamilyMember& F)
    {
        appellation = F.appellation;
        name = F.name;
        age = F.age;
        m_parent = F.m_parent;
    }
    
    FamilyMember::~FamilyMember(){
        qDeleteAll(m_children);
    }
    
    void FamilyMember::appendChildItem(FamilyMember* newChild){
        m_children.append(newChild);
    }
    
    FamilyMember* FamilyMember::parentItem() const{
        return m_parent;
    }
    
    FamilyMember* FamilyMember::child(int row){
        if (row < 0 || row > m_children.count())
            return nullptr;
        return m_children.at(row);
    }
    
    int FamilyMember::numberOfChildren(){
        return m_children.size();
    }
    
    int FamilyMember::row(){
      if (parentItem())
          //return parentItem()->m_children.indexOf(const_cast<FamilyMember*>(this)); // What "simpletreemodel" example does.
          return parentItem()->m_children.indexOf(this);    // What I does. It seems that the two methods both work.
      return 0;
    }