Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. How to delete row from TableView properly
Forum Updated to NodeBB v4.3 + New Features

How to delete row from TableView properly

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
8 Posts 2 Posters 1.4k Views 2 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.
  • S Offline
    S Offline
    sandro4912
    wrote on 16 Dec 2020, 17:26 last edited by sandro4912
    #1

    I have a table I created with TableView in qml.

    I can delete a row with right click on the Id field like this:

    26ef30f3-b7bd-4a36-ba99-2878044a9f42-image.png

    The deletion etc works but I get these errors in qml:

    52ce968c-c472-43ea-9998-be023b617333-image.png

    The method for delete rows looks like this in main.qml:

    function deleteRowFromDatabase(row) {
           console.log("before" + model.countOfRows())
    
           if (!model.removeEntry(row)) {
               console.log(qsTr("remove row %1 failed").arg(row))
           }
    
           model = QuestionsProxyModel
           console.log("after" + model.countOfRows())
       }
    

    The error point to the delegate row of id in main.qml

            DelegateChoice {
                column: 0
                delegate: QuestionIdDelegate {
                    id: questionIdDelegate
                    width: tableView.columnWidthProvider(column)
                    text: model.id                    /// this is undefined
                    row: model.row
    
                    Component.onCompleted: {
                        questionIdDelegate.markForDelete.connect(
                                    tableView.deleteRowFromDatabase)
                    }
                }
            }
    

    Removing of the rows is implemented from C++ In a class derrived from QIdentityProxyModel in questionsproxmodel.h:

    bool QuestionsProxyModel::removeEntry(int row)
    {
        return removeRows(row, 1);
    }
    

    This model takes a class QuestionSqlTableModel derrived from QSqlTableModel as a source model

    The remove rows is implemented like this in questionssqltablemodel.qml:

         bool QuestionSqlTableModel::removeRows(int row, int count,
                                                   const QModelIndex &parent)
            {
                auto result = QSqlTableModel::removeRows(row, count, parent);
                if (result) {
                    select(); // row is not deleted from sql database until select is called
                }
            
                return result;
            }
    

    From my understanding the countOfRows of the model gets updated only after the select() is called so I assume between QSqlTableModel::removeRows and select the TableView reads one more time with the non existing row and causes these errors in QML. How can that be prevented?

    Full Source code to try it out:

    main.cpp:

    #include <QDebug>
    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQuickStyle>
    
    #include <QFile>
    #include <QSqlDatabase>
    #include <QSqlQuery>
    
    #include <QSqlError>
    
    #include "questionsproxymodel.h"
    #include "questionsqltablemodel.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        QUrl dbUrl{"file:///home/sandro/Desktop/test.db"};
        auto exists = QFile::exists(dbUrl.toLocalFile());
    
        auto db = QSqlDatabase::addDatabase("QSQLITE", "DBConnection");
        db.setDatabaseName(dbUrl.toLocalFile());
        db.open();
    
        if (!exists) {
            const QString questionTableName = "questions";
            QSqlQuery query{db};
            query.exec("CREATE TABLE " + questionTableName +
                       " ("
                       "id INTEGER PRIMARY KEY AUTOINCREMENT)");
        }
    
        QScopedPointer<QuestionSqlTableModel> questionSqlTableModel(
            new QuestionSqlTableModel(nullptr, db));
    
        QScopedPointer<QuestionsProxyModel> questionsProxyModel{
            new QuestionsProxyModel};
        questionsProxyModel->setSourceModel(questionSqlTableModel.get());
    
        if (!exists) {
            for (int i = 0; i < 10; ++i) {
                questionsProxyModel->addNewEntry();
            }
        }
    
        QQmlApplicationEngine engine;
    
        qmlRegisterSingletonInstance<QuestionsProxyModel>(
            "QuestionsProxyModels", 1, 0, "QuestionsProxyModel",
            questionsProxyModel.get());
    
        const QUrl url(QStringLiteral("qrc:/qml/main.qml"));
        engine.load(url);
    
        return app.exec();
    }
    

    questionssqltablemodel.h

    #include <QSqlTableModel>
    
    class QuestionSqlTableModel : public QSqlTableModel {
        Q_OBJECT
    public:
        explicit QuestionSqlTableModel(QObject *parent = nullptr,
                                       const QSqlDatabase &db = QSqlDatabase());
    
        bool removeRows(int row, int count, const QModelIndex &parent) override;
    };
    

    questionssqltablemodel.cpp

    #include <QBuffer>
    #include <QDebug>
    #include <QPixmap>
    
    #include <QSqlError>
    #include <QSqlField>
    #include <QSqlRecord>
    #include <QSqlRelationalDelegate>
    
    QuestionSqlTableModel::QuestionSqlTableModel(QObject *parent,
                                                 const QSqlDatabase &db)
        : QSqlTableModel{parent, db}
    {
        setTable("questions");
        setSort(0, Qt::AscendingOrder);
        if (!select()) {
            qDebug() << "QuestionSqlTableModel: Select table questions failed";
        }
        setEditStrategy(EditStrategy::OnFieldChange);
    }
    
    bool QuestionSqlTableModel::removeRows(int row, int count,
                                           const QModelIndex &parent)
    {
        auto result = QSqlTableModel::removeRows(row, count, parent);
        if (result) {
            select(); // row is not deleted from sql database until select is called
        }
    
        return result;
    }
    

    questionsproxymodel.h:

    #include <QIdentityProxyModel>
    #include <QObject>
    
    class QuestionsProxyModel : public QIdentityProxyModel {
        Q_OBJECT
    
        enum questionRoles {
            idRole = Qt::UserRole + 1,
        };
    
    public:
        QuestionsProxyModel(QObject *parent = nullptr);
    
        QHash<int, QByteArray> roleNames() const override;
    
        Q_INVOKABLE QVariant data(const QModelIndex &index,
                                  int role = Qt::DisplayRole) const override;
    
        bool setData(const QModelIndex &index, const QVariant &value,
                     int role = Qt::EditRole) override;
    
        bool addNewEntry();
        Q_INVOKABLE bool removeEntry(int row);
        Q_INVOKABLE int countOfRows() const;
    
    private:
        QModelIndex mapIndex(const QModelIndex &source, int role) const;
    };
    

    questionsproxymodel.h:

    #include <QBuffer>
    #include <QDebug>
    #include <QPixmap>
    
    #include <QByteArray>
    
    #include <QSqlError>
    #include <QSqlTableModel>
    
    QuestionsProxyModel::QuestionsProxyModel(QObject *parent)
        : QIdentityProxyModel(parent)
    {
    }
    
    QHash<int, QByteArray> QuestionsProxyModel::roleNames() const
    {
        QHash<int, QByteArray> roles;
        roles[idRole] = "id";
        return roles;
    }
    
    QVariant QuestionsProxyModel::data(const QModelIndex &index, int role) const
    {
        QModelIndex newIndex = mapIndex(index, role);
        if (role == idRole) {
    
            return QIdentityProxyModel::data(newIndex, Qt::DisplayRole);
        }
        return QIdentityProxyModel::data(newIndex, role);
    }
    
    bool QuestionsProxyModel::setData(const QModelIndex &index,
                                      const QVariant &value, int role)
    {
        QModelIndex newIndex = mapIndex(index, role);
    
        if (role == idRole) {
    
            return QIdentityProxyModel::setData(newIndex, value, Qt::EditRole);
        }
        return QIdentityProxyModel::setData(newIndex, value, role);
    }
    
    bool QuestionsProxyModel::addNewEntry()
    {
        auto newRow = rowCount();
    
        if (!insertRows(newRow, 1)) {
            return false;
        }
        if (!setData(createIndex(newRow, 0), newRow + 1)) {
            removeRows(newRow, 1);
            return false;
        }
        auto sqlModel = qobject_cast<QSqlTableModel *>(sourceModel());
        return sqlModel->submit();
    }
    
    bool QuestionsProxyModel::removeEntry(int row)
    {
        return removeRows(row, 1);
    }
    
    int QuestionsProxyModel::countOfRows() const
    {
        return rowCount();
    }
    
    QModelIndex QuestionsProxyModel::mapIndex(const QModelIndex &source,
                                              int role) const
    {
        switch (role) {
        case idRole:
            return createIndex(source.row(), 0);
        }
        return source;
    }
    

    main.qml

    import QtQuick 2.15
    import QtQuick.Controls 2.15
    import QtQuick.Window 2.15
    import Qt.labs.qmlmodels 1.0
    import QtQuick.Controls.Material 2.15
    
    import QuestionsProxyModels 1.0
    
    ApplicationWindow {
        id: root
        visible: true
        width: 1460
        height: 800
    
        TableView {
            id: tableView
            width: parent.width
    
            anchors.fill: parent
            boundsBehavior: Flickable.StopAtBounds
    
            reuseItems: true
            clip: true
            property var columnWidths: [60]
            columnWidthProvider: function (column) {
                return columnWidths[column]
            }
    
            model: QuestionsProxyModel
    
            delegate: DelegateChooser {
                id: chooser
    
                DelegateChoice {
                    column: 0
                    delegate: QuestionIdDelegate {
                        id: questionIdDelegate
                        width: tableView.columnWidthProvider(column)
                        text: model.id
                        row: model.row
    
                        Component.onCompleted: {
                            questionIdDelegate.markForDelete.connect(
                                        tableView.deleteRowFromDatabase)
                        }
                    }
                }
            }
            ScrollBar.vertical: ScrollBar {}
    
            function deleteRowFromDatabase(row) {
                console.log("before" + model.countOfRows())
    
                if (!model.removeEntry(row)) {
                    console.log(qsTr("remove row %1 failed").arg(row))
                }
    
                model = QuestionsProxyModel
                console.log("after" + model.countOfRows())
            }
        }
    }
    

    QuestionIdDelegate.qml:

    import QtQuick 2.15
    import QtQuick.Controls 2.15
    
    TextField {
        property int row
    
        signal markForDelete(int row)
    
        id: root
    
        implicitHeight: 100
    
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignVCenter
    
        readOnly: true
    
        background: Frame {}
    
        MouseArea {
            id: mouseArea
            anchors.fill: parent
            acceptedButtons: Qt.RightButton
    
            onClicked: {
                eraseContextMenu.popup(root, 0, mouseArea.mouseY + 10)
            }
        }
    
        Menu {
            id: eraseContextMenu
            y: root.y
            MenuItem {
                text: qsTr("Delete entry")
                onTriggered: {
                    eraseDialog.open()
                    eraseContextMenu.close()
                }
            }
            MenuItem {
                text: qsTr("Cancel")
                onTriggered: {
                    eraseContextMenu.close()
                }
            }
        }
    
        Dialog {
            id: eraseDialog
            title: qsTr("Delete database entry")
            modal: true
            focus: true
    
            contentItem: Label {
                id: label
                text: qsTr("Do you really want to erase the entry with id %1?").arg(
                          root.text)
            }
    
            onAccepted: {
                markForDelete(root.row)
            }
    
            standardButtons: Dialog.Ok | Dialog.Cancel
        }
    }
    
    DiracsbracketD 1 Reply Last reply 18 Dec 2020, 13:25
    0
    • S sandro4912
      16 Dec 2020, 17:26

      I have a table I created with TableView in qml.

      I can delete a row with right click on the Id field like this:

      26ef30f3-b7bd-4a36-ba99-2878044a9f42-image.png

      The deletion etc works but I get these errors in qml:

      52ce968c-c472-43ea-9998-be023b617333-image.png

      The method for delete rows looks like this in main.qml:

      function deleteRowFromDatabase(row) {
             console.log("before" + model.countOfRows())
      
             if (!model.removeEntry(row)) {
                 console.log(qsTr("remove row %1 failed").arg(row))
             }
      
             model = QuestionsProxyModel
             console.log("after" + model.countOfRows())
         }
      

      The error point to the delegate row of id in main.qml

              DelegateChoice {
                  column: 0
                  delegate: QuestionIdDelegate {
                      id: questionIdDelegate
                      width: tableView.columnWidthProvider(column)
                      text: model.id                    /// this is undefined
                      row: model.row
      
                      Component.onCompleted: {
                          questionIdDelegate.markForDelete.connect(
                                      tableView.deleteRowFromDatabase)
                      }
                  }
              }
      

      Removing of the rows is implemented from C++ In a class derrived from QIdentityProxyModel in questionsproxmodel.h:

      bool QuestionsProxyModel::removeEntry(int row)
      {
          return removeRows(row, 1);
      }
      

      This model takes a class QuestionSqlTableModel derrived from QSqlTableModel as a source model

      The remove rows is implemented like this in questionssqltablemodel.qml:

           bool QuestionSqlTableModel::removeRows(int row, int count,
                                                     const QModelIndex &parent)
              {
                  auto result = QSqlTableModel::removeRows(row, count, parent);
                  if (result) {
                      select(); // row is not deleted from sql database until select is called
                  }
              
                  return result;
              }
      

      From my understanding the countOfRows of the model gets updated only after the select() is called so I assume between QSqlTableModel::removeRows and select the TableView reads one more time with the non existing row and causes these errors in QML. How can that be prevented?

      Full Source code to try it out:

      main.cpp:

      #include <QDebug>
      #include <QGuiApplication>
      #include <QQmlApplicationEngine>
      #include <QQuickStyle>
      
      #include <QFile>
      #include <QSqlDatabase>
      #include <QSqlQuery>
      
      #include <QSqlError>
      
      #include "questionsproxymodel.h"
      #include "questionsqltablemodel.h"
      
      int main(int argc, char *argv[])
      {
          QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
      
          QGuiApplication app(argc, argv);
      
          QUrl dbUrl{"file:///home/sandro/Desktop/test.db"};
          auto exists = QFile::exists(dbUrl.toLocalFile());
      
          auto db = QSqlDatabase::addDatabase("QSQLITE", "DBConnection");
          db.setDatabaseName(dbUrl.toLocalFile());
          db.open();
      
          if (!exists) {
              const QString questionTableName = "questions";
              QSqlQuery query{db};
              query.exec("CREATE TABLE " + questionTableName +
                         " ("
                         "id INTEGER PRIMARY KEY AUTOINCREMENT)");
          }
      
          QScopedPointer<QuestionSqlTableModel> questionSqlTableModel(
              new QuestionSqlTableModel(nullptr, db));
      
          QScopedPointer<QuestionsProxyModel> questionsProxyModel{
              new QuestionsProxyModel};
          questionsProxyModel->setSourceModel(questionSqlTableModel.get());
      
          if (!exists) {
              for (int i = 0; i < 10; ++i) {
                  questionsProxyModel->addNewEntry();
              }
          }
      
          QQmlApplicationEngine engine;
      
          qmlRegisterSingletonInstance<QuestionsProxyModel>(
              "QuestionsProxyModels", 1, 0, "QuestionsProxyModel",
              questionsProxyModel.get());
      
          const QUrl url(QStringLiteral("qrc:/qml/main.qml"));
          engine.load(url);
      
          return app.exec();
      }
      

      questionssqltablemodel.h

      #include <QSqlTableModel>
      
      class QuestionSqlTableModel : public QSqlTableModel {
          Q_OBJECT
      public:
          explicit QuestionSqlTableModel(QObject *parent = nullptr,
                                         const QSqlDatabase &db = QSqlDatabase());
      
          bool removeRows(int row, int count, const QModelIndex &parent) override;
      };
      

      questionssqltablemodel.cpp

      #include <QBuffer>
      #include <QDebug>
      #include <QPixmap>
      
      #include <QSqlError>
      #include <QSqlField>
      #include <QSqlRecord>
      #include <QSqlRelationalDelegate>
      
      QuestionSqlTableModel::QuestionSqlTableModel(QObject *parent,
                                                   const QSqlDatabase &db)
          : QSqlTableModel{parent, db}
      {
          setTable("questions");
          setSort(0, Qt::AscendingOrder);
          if (!select()) {
              qDebug() << "QuestionSqlTableModel: Select table questions failed";
          }
          setEditStrategy(EditStrategy::OnFieldChange);
      }
      
      bool QuestionSqlTableModel::removeRows(int row, int count,
                                             const QModelIndex &parent)
      {
          auto result = QSqlTableModel::removeRows(row, count, parent);
          if (result) {
              select(); // row is not deleted from sql database until select is called
          }
      
          return result;
      }
      

      questionsproxymodel.h:

      #include <QIdentityProxyModel>
      #include <QObject>
      
      class QuestionsProxyModel : public QIdentityProxyModel {
          Q_OBJECT
      
          enum questionRoles {
              idRole = Qt::UserRole + 1,
          };
      
      public:
          QuestionsProxyModel(QObject *parent = nullptr);
      
          QHash<int, QByteArray> roleNames() const override;
      
          Q_INVOKABLE QVariant data(const QModelIndex &index,
                                    int role = Qt::DisplayRole) const override;
      
          bool setData(const QModelIndex &index, const QVariant &value,
                       int role = Qt::EditRole) override;
      
          bool addNewEntry();
          Q_INVOKABLE bool removeEntry(int row);
          Q_INVOKABLE int countOfRows() const;
      
      private:
          QModelIndex mapIndex(const QModelIndex &source, int role) const;
      };
      

      questionsproxymodel.h:

      #include <QBuffer>
      #include <QDebug>
      #include <QPixmap>
      
      #include <QByteArray>
      
      #include <QSqlError>
      #include <QSqlTableModel>
      
      QuestionsProxyModel::QuestionsProxyModel(QObject *parent)
          : QIdentityProxyModel(parent)
      {
      }
      
      QHash<int, QByteArray> QuestionsProxyModel::roleNames() const
      {
          QHash<int, QByteArray> roles;
          roles[idRole] = "id";
          return roles;
      }
      
      QVariant QuestionsProxyModel::data(const QModelIndex &index, int role) const
      {
          QModelIndex newIndex = mapIndex(index, role);
          if (role == idRole) {
      
              return QIdentityProxyModel::data(newIndex, Qt::DisplayRole);
          }
          return QIdentityProxyModel::data(newIndex, role);
      }
      
      bool QuestionsProxyModel::setData(const QModelIndex &index,
                                        const QVariant &value, int role)
      {
          QModelIndex newIndex = mapIndex(index, role);
      
          if (role == idRole) {
      
              return QIdentityProxyModel::setData(newIndex, value, Qt::EditRole);
          }
          return QIdentityProxyModel::setData(newIndex, value, role);
      }
      
      bool QuestionsProxyModel::addNewEntry()
      {
          auto newRow = rowCount();
      
          if (!insertRows(newRow, 1)) {
              return false;
          }
          if (!setData(createIndex(newRow, 0), newRow + 1)) {
              removeRows(newRow, 1);
              return false;
          }
          auto sqlModel = qobject_cast<QSqlTableModel *>(sourceModel());
          return sqlModel->submit();
      }
      
      bool QuestionsProxyModel::removeEntry(int row)
      {
          return removeRows(row, 1);
      }
      
      int QuestionsProxyModel::countOfRows() const
      {
          return rowCount();
      }
      
      QModelIndex QuestionsProxyModel::mapIndex(const QModelIndex &source,
                                                int role) const
      {
          switch (role) {
          case idRole:
              return createIndex(source.row(), 0);
          }
          return source;
      }
      

      main.qml

      import QtQuick 2.15
      import QtQuick.Controls 2.15
      import QtQuick.Window 2.15
      import Qt.labs.qmlmodels 1.0
      import QtQuick.Controls.Material 2.15
      
      import QuestionsProxyModels 1.0
      
      ApplicationWindow {
          id: root
          visible: true
          width: 1460
          height: 800
      
          TableView {
              id: tableView
              width: parent.width
      
              anchors.fill: parent
              boundsBehavior: Flickable.StopAtBounds
      
              reuseItems: true
              clip: true
              property var columnWidths: [60]
              columnWidthProvider: function (column) {
                  return columnWidths[column]
              }
      
              model: QuestionsProxyModel
      
              delegate: DelegateChooser {
                  id: chooser
      
                  DelegateChoice {
                      column: 0
                      delegate: QuestionIdDelegate {
                          id: questionIdDelegate
                          width: tableView.columnWidthProvider(column)
                          text: model.id
                          row: model.row
      
                          Component.onCompleted: {
                              questionIdDelegate.markForDelete.connect(
                                          tableView.deleteRowFromDatabase)
                          }
                      }
                  }
              }
              ScrollBar.vertical: ScrollBar {}
      
              function deleteRowFromDatabase(row) {
                  console.log("before" + model.countOfRows())
      
                  if (!model.removeEntry(row)) {
                      console.log(qsTr("remove row %1 failed").arg(row))
                  }
      
                  model = QuestionsProxyModel
                  console.log("after" + model.countOfRows())
              }
          }
      }
      

      QuestionIdDelegate.qml:

      import QtQuick 2.15
      import QtQuick.Controls 2.15
      
      TextField {
          property int row
      
          signal markForDelete(int row)
      
          id: root
      
          implicitHeight: 100
      
          horizontalAlignment: Text.AlignHCenter
          verticalAlignment: Text.AlignVCenter
      
          readOnly: true
      
          background: Frame {}
      
          MouseArea {
              id: mouseArea
              anchors.fill: parent
              acceptedButtons: Qt.RightButton
      
              onClicked: {
                  eraseContextMenu.popup(root, 0, mouseArea.mouseY + 10)
              }
          }
      
          Menu {
              id: eraseContextMenu
              y: root.y
              MenuItem {
                  text: qsTr("Delete entry")
                  onTriggered: {
                      eraseDialog.open()
                      eraseContextMenu.close()
                  }
              }
              MenuItem {
                  text: qsTr("Cancel")
                  onTriggered: {
                      eraseContextMenu.close()
                  }
              }
          }
      
          Dialog {
              id: eraseDialog
              title: qsTr("Delete database entry")
              modal: true
              focus: true
      
              contentItem: Label {
                  id: label
                  text: qsTr("Do you really want to erase the entry with id %1?").arg(
                            root.text)
              }
      
              onAccepted: {
                  markForDelete(root.row)
              }
      
              standardButtons: Dialog.Ok | Dialog.Cancel
          }
      }
      
      DiracsbracketD Offline
      DiracsbracketD Offline
      Diracsbracket
      wrote on 18 Dec 2020, 13:25 last edited by
      #2

      @sandro4912
      I couldn't see any call to

      beginRemoveRows(...)
      ...
      endRemoveRows(...)
      

      in your code. Refer to:
      https://doc.qt.io/qt-5/qabstractitemmodel.html#beginRemoveRows

      Sometimes it is easier just to use the following pair instead:

      beginResetModel();
      ...
      endResetModel();
      

      https://doc.qt.io/qt-5/qabstractitemmodel.html#beginResetModel

      S 1 Reply Last reply 18 Dec 2020, 19:16
      0
      • DiracsbracketD Diracsbracket
        18 Dec 2020, 13:25

        @sandro4912
        I couldn't see any call to

        beginRemoveRows(...)
        ...
        endRemoveRows(...)
        

        in your code. Refer to:
        https://doc.qt.io/qt-5/qabstractitemmodel.html#beginRemoveRows

        Sometimes it is easier just to use the following pair instead:

        beginResetModel();
        ...
        endResetModel();
        

        https://doc.qt.io/qt-5/qabstractitemmodel.html#beginResetModel

        S Offline
        S Offline
        sandro4912
        wrote on 18 Dec 2020, 19:16 last edited by
        #3

        @Diracsbracket said in How to delete row from TableView properly:

        endResetModel();

        Were would you add that?

        I added it to the function:

        bool QuestionSqlTableModel::removeRows(int row, int count,
                                               const QModelIndex &parent)
        

        but still get the errors in qml.

        DiracsbracketD 1 Reply Last reply 19 Dec 2020, 03:28
        0
        • S sandro4912
          18 Dec 2020, 19:16

          @Diracsbracket said in How to delete row from TableView properly:

          endResetModel();

          Were would you add that?

          I added it to the function:

          bool QuestionSqlTableModel::removeRows(int row, int count,
                                                 const QModelIndex &parent)
          

          but still get the errors in qml.

          DiracsbracketD Offline
          DiracsbracketD Offline
          Diracsbracket
          wrote on 19 Dec 2020, 03:28 last edited by
          #4

          @sandro4912

          Normally you would place it like this:

          bool QuestionSqlTableModel::removeRows(int row, int count,
                                                 const QModelIndex &parent)
          {
              beginRemoveRows() //<--- or beginResetModel()
          
              auto result = QSqlTableModel::removeRows(row, count, parent);
              if (result) {
                  select(); // row is not deleted from sql database until select is called
              }
          
             endRemoveRows(); //<-- or endResetModel()
             return result;
          }
          
          1 Reply Last reply
          1
          • S Offline
            S Offline
            sandro4912
            wrote on 19 Dec 2020, 15:20 last edited by
            #5

            You are right I totally forgot to add that.

            Although It did not solve the assign errors. I still had to change in the delegates:

            text: model.id === undefined ? "" : model.id
            

            And I realized there is another error which still shows up:

            If I delete the row 1 and then the row 2 my output looks like this:
            enter image description here

            This binding loop error points Dialog in QuestionsIDDelegate:

            Dialog {
                id: eraseDialog
                title: qsTr("Delete database entry")
                modal: true
                focus: true
            
                contentItem: Label {
                    id: label
                    text: qsTr("Do you really want to erase the entry with id %1?").arg(
                              root.text)
                }
            
                onAccepted: {
                    markForDelete(root.row)
                }
            
                standardButtons: Dialog.Ok | Dialog.Cancel
            }
            
            DiracsbracketD 1 Reply Last reply 21 Dec 2020, 07:28
            0
            • S sandro4912
              19 Dec 2020, 15:20

              You are right I totally forgot to add that.

              Although It did not solve the assign errors. I still had to change in the delegates:

              text: model.id === undefined ? "" : model.id
              

              And I realized there is another error which still shows up:

              If I delete the row 1 and then the row 2 my output looks like this:
              enter image description here

              This binding loop error points Dialog in QuestionsIDDelegate:

              Dialog {
                  id: eraseDialog
                  title: qsTr("Delete database entry")
                  modal: true
                  focus: true
              
                  contentItem: Label {
                      id: label
                      text: qsTr("Do you really want to erase the entry with id %1?").arg(
                                root.text)
                  }
              
                  onAccepted: {
                      markForDelete(root.row)
                  }
              
                  standardButtons: Dialog.Ok | Dialog.Cancel
              }
              
              DiracsbracketD Offline
              DiracsbracketD Offline
              Diracsbracket
              wrote on 21 Dec 2020, 07:28 last edited by Diracsbracket
              #6

              @sandro4912 said in How to delete row from TableView properly:

              This binding loop error points Dialog in QuestionsIDDelegate:

              That is probably a bug in your Qt version. I'm tested it in Qt 5.15.2, and I get no binding loop.
              As a workaround, try setting the height of the Label explicitly.

              @sandro4912 said in How to delete row from TableView properly:

              text: model.id === undefined ? "" : model.id

              Assuming that id is always defined in your model, this shouldn't be necessary (imagine having to do this check for every field of your model you use in the delegate).

              Maybe try with begin/endResetModel() instead of begin/endRemoveRows() ?

              1 Reply Last reply
              0
              • S Offline
                S Offline
                sandro4912
                wrote on 21 Dec 2020, 13:48 last edited by sandro4912
                #7

                @Diracsbracket said in How to delete row from TableView properly:

                Qt 5.15

                Did you try to reproduce the binding loop to delete several elements? If I delete the first it did not happen.

                Im Also on Qt 5.15

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  sandro4912
                  wrote on 25 Dec 2020, 17:40 last edited by
                  #8

                  I also asked this question here:

                  Even If I used signals and slots to invoke the methods not directly from javascript I still get these errors:

                  https://stackoverflow.com/questions/65328173/how-to-delete-row-from-tableview-properly/65382947?noredirect=1#comment115712152_65382947

                  1 Reply Last reply
                  0

                  1/8

                  16 Dec 2020, 17:26

                  • Login

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