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. Yet another QSqlTableModel removeRows issue

Yet another QSqlTableModel removeRows issue

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 3 Posters 633 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.
  • M Offline
    M Offline
    Mark81
    wrote on last edited by Mark81
    #1

    Here I read:

    Removes count rows starting at row. Since this model does not support hierarchical structures, parent must be an invalid model index.
    When the edit strategy is OnManualSubmit, deletion of rows from the database is delayed until submitAll() is called.
    Before a row is deleted from the database, the beforeDelete() signal is emitted.

    In my application I do:

    void DialogTechnologies::on_btnRemove_clicked()
    {
        if (ui->table->selectionModel()->hasSelection())
        {
            int row = ui->table->selectionModel()->currentIndex().row();
            _model->removeRow(row);
            _model->submitAll();
        }
    }
    
    void DialogTechnologies::on_btnRemoveAll_clicked()
    {
        _model->removeRows(0, _model->rowCount());
        _model->submitAll();
    }
    

    Both remove* methods return true but nothing happens on the database.
    Questions:

    1. what does actually mean that "parent must be an invalid model index"?
    2. what signal should I use to refresh the view, after the row(s) deletion? Is dataChanged emitted?

    As side note: in the help integrated in the IDE I read instead:

    The base class implementation does nothing and returns false.

    This makes no sense to me. First, it returs true and then why they would have implemented the insertRows function but not the removeRows one? By the way, also for insertRows the help says the "base class implementation does nothing and returns false", but this is not true - it works and it returns true! I'm confused...

    JonBJ 1 Reply Last reply
    0
    • M Mark81

      Here I read:

      Removes count rows starting at row. Since this model does not support hierarchical structures, parent must be an invalid model index.
      When the edit strategy is OnManualSubmit, deletion of rows from the database is delayed until submitAll() is called.
      Before a row is deleted from the database, the beforeDelete() signal is emitted.

      In my application I do:

      void DialogTechnologies::on_btnRemove_clicked()
      {
          if (ui->table->selectionModel()->hasSelection())
          {
              int row = ui->table->selectionModel()->currentIndex().row();
              _model->removeRow(row);
              _model->submitAll();
          }
      }
      
      void DialogTechnologies::on_btnRemoveAll_clicked()
      {
          _model->removeRows(0, _model->rowCount());
          _model->submitAll();
      }
      

      Both remove* methods return true but nothing happens on the database.
      Questions:

      1. what does actually mean that "parent must be an invalid model index"?
      2. what signal should I use to refresh the view, after the row(s) deletion? Is dataChanged emitted?

      As side note: in the help integrated in the IDE I read instead:

      The base class implementation does nothing and returns false.

      This makes no sense to me. First, it returs true and then why they would have implemented the insertRows function but not the removeRows one? By the way, also for insertRows the help says the "base class implementation does nothing and returns false", but this is not true - it works and it returns true! I'm confused...

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #2

      @Mark81

      Both remove* methods return true

      Have to take your word on that, because it's not in your code....

      but nothing happens on the database.

      How do you check that?

      The base class implementation does nothing and returns false.

      That's for whatever the base class is, maybe QAbstractItemModel, I haven't looked. QSqlTableModel does have an implementation.

      what does actually mean that "parent must be an invalid model index"?

      bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) has a default QModelIndex() which is "an invalid model index", you are calling it right, don't worry about it.

      what signal should I use to refresh the view, after the row(s) deletion? Is dataChanged emitted?

      dataChanged is only for updates. For insertion/deletion it's beginRemoveRows/rowsAboutToBeRemoved/rowsRemoved() etc. But QSqlTableModel does this for you. You don't have to raise signals, just ensure your view is properly connected to model.

      Why does it (apparently) not work? I don't know, but I do know you need to check the returns result of the _model->submitAll(); because maybe it's failing at database side.... When you write code like this, please look at return results and always check all of them, especially while developing/you don't know what is going on....

      M 1 Reply Last reply
      2
      • JonBJ JonB

        @Mark81

        Both remove* methods return true

        Have to take your word on that, because it's not in your code....

        but nothing happens on the database.

        How do you check that?

        The base class implementation does nothing and returns false.

        That's for whatever the base class is, maybe QAbstractItemModel, I haven't looked. QSqlTableModel does have an implementation.

        what does actually mean that "parent must be an invalid model index"?

        bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) has a default QModelIndex() which is "an invalid model index", you are calling it right, don't worry about it.

        what signal should I use to refresh the view, after the row(s) deletion? Is dataChanged emitted?

        dataChanged is only for updates. For insertion/deletion it's beginRemoveRows/rowsAboutToBeRemoved/rowsRemoved() etc. But QSqlTableModel does this for you. You don't have to raise signals, just ensure your view is properly connected to model.

        Why does it (apparently) not work? I don't know, but I do know you need to check the returns result of the _model->submitAll(); because maybe it's failing at database side.... When you write code like this, please look at return results and always check all of them, especially while developing/you don't know what is going on....

        M Offline
        M Offline
        Mark81
        wrote on last edited by
        #3

        @JonB said in Yet another QSqlTableModel removeRows issue:

        @Mark81
        Have to take your word on that, because it's not in your code....

        I printed the return values with qDebug().

        How do you check that?

        With "DB Browser for SQLite".

        That's for whatever the base class is, maybe QAbstractItemModel, I haven't looked. QSqlTableModel does have an implementation.

        Good.

        dataChanged is only for updates. For insertion/deletion it's beginRemoveRows/rowsAboutToBeRemoved/rowsRemoved() etc. But QSqlTableModel does this for you. You don't have to raise signals, just ensure your view is properly connected to model.

        Got it, thanks.

        Why does it (apparently) not work? I don't know, but I do know you need to check the returns result of the _model->submitAll(); because maybe it's failing at database side.... When you write code like this, please look at return results and always check all of them, especially while developing/you don't know what is going on....

        Good shot, the problem is sumbitAll() that returns false.
        And inspecting the lastError() I found the root cause of my problem:

        QSqlError("19", "Unable to fetch row", "FOREIGN KEY constraint failed")

        It's correct, indeed.
        I didn't think about it becase I was afraid I didn't understand the documentation!

        JonBJ 1 Reply Last reply
        0
        • M Mark81

          @JonB said in Yet another QSqlTableModel removeRows issue:

          @Mark81
          Have to take your word on that, because it's not in your code....

          I printed the return values with qDebug().

          How do you check that?

          With "DB Browser for SQLite".

          That's for whatever the base class is, maybe QAbstractItemModel, I haven't looked. QSqlTableModel does have an implementation.

          Good.

          dataChanged is only for updates. For insertion/deletion it's beginRemoveRows/rowsAboutToBeRemoved/rowsRemoved() etc. But QSqlTableModel does this for you. You don't have to raise signals, just ensure your view is properly connected to model.

          Got it, thanks.

          Why does it (apparently) not work? I don't know, but I do know you need to check the returns result of the _model->submitAll(); because maybe it's failing at database side.... When you write code like this, please look at return results and always check all of them, especially while developing/you don't know what is going on....

          Good shot, the problem is sumbitAll() that returns false.
          And inspecting the lastError() I found the root cause of my problem:

          QSqlError("19", "Unable to fetch row", "FOREIGN KEY constraint failed")

          It's correct, indeed.
          I didn't think about it becase I was afraid I didn't understand the documentation!

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by
          #4

          @Mark81
          Which is what I suspected would be the reason :) Just be aware: if you use a Qt function which returns a result, especially if it's calling some operation like "updating a database", when you first read the documentation to use it put it code to capture/test the result! :) I can see you have then used the docs to call lastError(), which is excellent!

          1 Reply Last reply
          3
          • VRoninV Offline
            VRoninV Offline
            VRonin
            wrote on last edited by
            #5

            As a general rule, if you have naked statement that return a boolean and your code just assumes it returns true then it's a good idea to wrap it in Q_ASSUME(). This will trigger a debug assertion if the method actually returned false and does nothing in release mode.
            e.g. Q_ASSUME(_model->submitAll());

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            1 Reply Last reply
            4
            • JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #6

              @Mark81
              And what @VRonin has written is certainly better then no test at all! However, to be clear, in a case like this where an operation could genuinely return false, you must/should not just do this, you must provide proper error handling. Otherwise it works fine in your own development tests, but silently fails and does not check when you send out your release code, and you/the user have no idea it did fail or why! You probably already know that, just saying for other readers....

              M 1 Reply Last reply
              1
              • JonBJ JonB

                @Mark81
                And what @VRonin has written is certainly better then no test at all! However, to be clear, in a case like this where an operation could genuinely return false, you must/should not just do this, you must provide proper error handling. Otherwise it works fine in your own development tests, but silently fails and does not check when you send out your release code, and you/the user have no idea it did fail or why! You probably already know that, just saying for other readers....

                M Offline
                M Offline
                Mark81
                wrote on last edited by
                #7

                @JonB said in Yet another QSqlTableModel removeRows issue:

                @Mark81
                And what @VRonin has written is certainly better then no test at all! However, to be clear, in a case like this where an operation could genuinely return false, you must/should not just do this, you must provide proper error handling. Otherwise it works fine in your own development tests, but silently fails and does not check when you send out your release code, and you/the user have no idea it did fail or why! You probably already know that, just saying for other readers....

                Yes of course. As said I was a step before that - due to the doubts on the docs.
                Now, I've already connected a signal to show an error message to the user.

                1 Reply Last reply
                1

                • Login

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