Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Problem with model, or Instantiator
Forum Updated to NodeBB v4.3 + New Features

Problem with model, or Instantiator

Scheduled Pinned Locked Moved Solved General and Desktop
4 Posts 1 Posters 327 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • fcarneyF Offline
    fcarneyF Offline
    fcarney
    wrote on last edited by
    #1

    I have a QAbstractListModel with some methods that I think are correct:

    void JsonObjectStore::insert(int ind, QJSValue jsondata)
    {
        if(ind < 0 || ind > rowCount())
            return;
    
        auto pjsondata = prepareData(jsondata);
        if(!pjsondata)
            return;
    
        QAbstractListModel::beginInsertRows(index(ind,0), ind, ind);
        m_jsonObjectList.insert(ind, pjsondata);
        QAbstractListModel::endInsertRows();
    
        emit countChanged();
    }
    
    void JsonObjectStore::remove(int ind, int n)
    {
        if(ind < 0 || (ind + n) > rowCount()){
            qDebug() << "JsonObjectStore::remove index+count too big:" << ind << n << rowCount();
            return;
        }
    
        QAbstractListModel::beginRemoveRows(index(ind,0), ind, ind+(n-1));
        for(int count=ind; count < ind+n && count < m_jsonObjectList.size(); ++count)
            delete m_jsonObjectList[count];
        m_jsonObjectList.remove(ind, n); // does this return an error/crash if extends past list end?
        QAbstractListModel::endRemoveRows();
    
        emit countChanged();
    }
    

    Insert seems to trigger the down stream Instantiator just fine, but I am not seeing the Instantiator call onObjectRemoved. I originally assumed it was the remove method at fault, but I cannot tell what is wrong with it.

                Instantiator {
                    id: editor_repeater
    
                    active: true
                    model: loaded_objects
    
                    property var grid_object: edit_grid_board
                    property int currentIndex: -1
    
                    delegate: EditorObject {
                        id: etdelegate
    
                        params: datarole
                        inst_index: index
    
                        width: editor_repeater.grid_object.cell_width * gw
                        height: editor_repeater.grid_object.cell_height * gh
    
                        anchors.left: parent.left
                        anchors.top: parent.top
                        clip: true
    
                        selected: editor_repeater.currentIndex === index
    
                        onDroppedObject: {
                            if(dropobj.drop.keys.includes("pathkey")){
                                loaded_objects.setProperty(index, inst_obj.dropProperties.path, dropobj.drop.source.dropdata.path.toString())
                                loaded_objects.dirty = true
                            }
                        }
    
                        MouseArea {
                            id: etdelegate_mousearea
    
                            anchors.fill: parent
                            acceptedButtons: Qt.LeftButton | Qt.RightButton
    
                            onClicked: {
                                //console.log("clicked")
                                if(mouse.button === Qt.LeftButton){
                                    editor_repeater.currentIndex = index
                                }else if(mouse.button === Qt.RightButton){
                                    etdelegate_contextmenu.popup()
                                }
                            }
                        }
    
                        Menu {
                            id: etdelegate_contextmenu
    
                            MenuItem {
                                text: "Delete"
                                onTriggered: {
                                    editor_repeater.model.remove(index)
                                }
                            }
                        }
                    }
    
                    onObjectAdded: {
                        var pos_object = grid_object.getDelegateInsertObject(object.gx, object.gy)
                        pos_object.data.push(object)
                    }
                    onObjectRemoved: {
                        console.log(object)
                    }
                }
    

    There is a bunch of junk in Instantiator, but you get the idea. The object does not seem to dissapear like I thought it would. When I right click to call remove again I get the warning about it being out of bounds. So it is not in the QVector m_jsonObjectList anymore. I don't understand why it is not seeing the beginRemoveRows and endRemoveRows.

    C++ is a perfectly valid school of magic.

    1 Reply Last reply
    0
    • fcarneyF Offline
      fcarneyF Offline
      fcarney
      wrote on last edited by
      #2

      Here is a better example:

      #ifndef CUSTOMMODEL_H
      #define CUSTOMMODEL_H
      
      #include <QObject>
      #include <QAbstractListModel>
      
      class BasicModel : public QAbstractListModel
      {
          Q_OBJECT
          Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
      
          int m_count;
          QVector<int> m_list;
      
      public:
          BasicModel(QObject* parent=nullptr)
              : QAbstractListModel(parent)
          {
          }
      
          int rowCount(const QModelIndex &parent = QModelIndex()) const{
              return m_list.count();
          }
          QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const{
              if(index.row() < 0 || index.row() >= rowCount())
                  return QVariant();
      
              if(role != Qt::DisplayRole)
                  return QVariant();
      
              return m_list[index.row()];
          }
      signals:
          void countChanged();
      
      public slots:
          void insert(int ind, int data){
              if(ind < 0 || ind > rowCount())
                  return;
      
              QAbstractListModel::beginInsertRows(index(ind,0), ind, ind);
              m_list.insert(ind, data);
              QAbstractListModel::endInsertRows();
      
              emit countChanged();
          }
          void remove(int ind){
              if(ind < 0 || ind >= rowCount())
                  return;
      
              QAbstractListModel::beginRemoveRows(index(ind,0), ind, ind);
              m_list.remove(ind);
              QAbstractListModel::endRemoveRows();
      
              emit countChanged();
          }
      };
      
      #endif // CUSTOMMODEL_H
      
      

      main.cpp:

      #include <QGuiApplication>
      #include <QQmlApplicationEngine>
      
      #include "custommodel.h"
      
      int main(int argc, char *argv[])
      {
          QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
      
          QGuiApplication app(argc, argv);
      
          qmlRegisterType<BasicModel>("BasicModels",1,0,"BasicModel");
      
          QQmlApplicationEngine engine;
          const QUrl url(QStringLiteral("qrc:/main.qml"));
          QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                           &app, [url](QObject *obj, const QUrl &objUrl) {
              if (!obj && url == objUrl)
                  QCoreApplication::exit(-1);
          }, Qt::QueuedConnection);
          engine.load(url);
      
          return app.exec();
      }
      
      

      main.qml:

      import QtQuick 2.15
      import QtQuick.Window 2.15
      import QtQml.Models 2.15
      
      import BasicModels 1.0
      
      Window {
          visible: true
          width: 640
          height: 480
          title: qsTr("Test Instantiator Custom Model")
      
          BasicModel {
              id: basicmodel
          }
      
          ListModel {
              id: objectmodel
          }
      
          Instantiator {
              id: instantiator
      
              model: basicmodel
      
              delegate: Text {
                  text: display
              }
      
              onObjectAdded: {
                  console.log("onObjectAdded", object.text)
              }
              onObjectRemoved: {
                  console.log("onObjectRemoved", object.text)
              }
      
              Component.onCompleted: {
                  instantiator.model.insert(instantiator.model.count, 1)
                  instantiator.model.insert(instantiator.model.count, 2)
                  console.log(instantiator.model.count)
      
                  Qt.callLater(removeItems)
              }
      
              function removeItems(){
                  while(instantiator.model.count){
                      instantiator.model.remove(0)
                  }
                  console.log(instantiator.model.count)
              }
          }
      }
      

      It calls the onObjectRemoved on the ListModel, but not on the BasicModel. I thought ListModel was based on QAbstractListModel, so I don't know what the issue is.

      C++ is a perfectly valid school of magic.

      1 Reply Last reply
      0
      • fcarneyF Offline
        fcarneyF Offline
        fcarney
        wrote on last edited by
        #3

        This better illustrates the issue:

        import QtQuick 2.15
        import QtQuick.Window 2.15
        import QtQml.Models 2.15
        
        import BasicModels 1.0
        
        Window {
            visible: true
            width: 640
            height: 480
            title: qsTr("Test Instantiator Custom Model")
        
            BasicModel {
                id: basicmodel
            }
        
            ListModel {
                id: objectmodel
            }
        
            Instantiator {
                id: instantiator
        
                model: basicmodel
        
                delegate: Text {
                    text: display
                }
        
                onObjectAdded: {
                    console.log("onObjectAdded", object.text)
                }
                onObjectRemoved: {
                    console.log("onObjectRemoved", object.text)
                }
        
                Component.onCompleted: {
                    console.log("instantiator")
                    instantiator.model.insert(instantiator.model.count, 1)
                    instantiator.model.insert(instantiator.model.count, 2)
                    console.log(instantiator.model.count)
        
                    Qt.callLater(removeItems)
                }
        
                function removeItems(){
                    console.log("instantiator")
                    while(instantiator.model.count){
                        instantiator.model.remove(0)
                    }
                    console.log(instantiator.model.count)
                }
            }
        
            Instantiator {
                id: instantiator2
        
                model: objectmodel
        
                delegate: Text {
                    text: display
                }
        
                onObjectAdded: {
                    console.log("onObjectAdded", object.text)
                }
                onObjectRemoved: {
                    console.log("onObjectRemoved", object.text)
                }
        
                Component.onCompleted: {
                    console.log("instantiator2")
                    instantiator2.model.insert(instantiator.model.count, {display:1})
                    instantiator2.model.insert(instantiator.model.count, {display:2})
                    console.log(instantiator2.model.count)
        
                    Qt.callLater(removeItems)
                }
        
                function removeItems(){
                    console.log("instantiator2")
                    while(instantiator2.model.count){
                        instantiator2.model.remove(0)
                    }
                    console.log(instantiator2.model.count)
                }
            }
        }
        
        

        C++ is a perfectly valid school of magic.

        1 Reply Last reply
        0
        • fcarneyF Offline
          fcarneyF Offline
          fcarney
          wrote on last edited by
          #4

          Okay, stupid mistake:

          void insert(int ind, int data){
                  if(ind < 0 || ind > rowCount())
                      return;
          
                  QAbstractListModel::beginInsertRows(QModelIndex(), ind, ind);
                  m_list.insert(ind, data);
                  QAbstractListModel::endInsertRows();
          
                  emit countChanged();
              }
              void remove(int ind){
                  if(ind < 0 || ind >= rowCount())
                      return;
          
                  QAbstractListModel::beginRemoveRows(QModelIndex(), ind, ind);
                  m_list.remove(ind);
                  QAbstractListModel::endRemoveRows();
          
                  emit countChanged();
              }
          

          C++ is a perfectly valid school of magic.

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved