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. QAbstractTableModel and dataChanged
Forum Updated to NodeBB v4.3 + New Features

QAbstractTableModel and dataChanged

Scheduled Pinned Locked Moved Solved General and Desktop
16 Posts 6 Posters 3.8k Views
  • 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.
  • Christian EhrlicherC Offline
    Christian EhrlicherC Offline
    Christian Ehrlicher
    Lifetime Qt Champion
    wrote on last edited by
    #7

    @Lachrymology said in QAbstractTableModel and dataChanged:

    So, what I'm missing now?

    Why do you reimplement setQuery() at all? There is no need for it.

    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
    Visit the Qt Academy at https://academy.qt.io/catalog

    1 Reply Last reply
    0
    • L Offline
      L Offline
      Lachrymology
      wrote on last edited by
      #8

      Uff ... I think it would be easier to have the SQL thingy removed first.

      So okay, let us assume SQL stands here for Super Quarreler Laughter, which is a complex data structure needing a TableModel to be presented. Deal?

      1 Reply Last reply
      0
      • L Lachrymology

        @JonB
        Jep, subclassing QSqlTableModel is easy and it works like expected. I've tried it now.

        Nevertheless - I don't get it .. the docs are saying the following:

        "When subclassing QAbstractItemModel, at the very least you must implement index(), parent(), rowCount(), columnCount(), and data(). These functions are used in all read-only models, and form the basis of editable models."

        Currently I've a read-only model. As shown above I've implemented these function, except index and parent.

        But I'm not sure about:
        "Models that provide interfaces to resizable data structures can provide implementations of insertRows(), removeRows(), insertColumns(),and removeColumns()."

        The "CAN" confuses me - do I have to or is it optional?

        Furthermore I'm now working with: beginInsertRows/endInsertRows and beginInsertColumns/endInsertColumns

        void SqlTableModel::setHeader( QStringList header )
        {
            _header = header;
            beginInsertColumns( QModelIndex(), 0, _header.count() );
            int c = 0;
            for( QString headStr : _header )
            {
                qDebug() << "Inserted Column: " << insertColumn( c, QModelIndex() );
                c++;
            }
            endInsertColumns();
        }
        
        void SqlTableModel::setQuery( QString queryStr )
        {
            _queryStr = queryStr;
            SQL::execQuery( queryStr );
        
            QSqlQuery query = SQL::getLastQuery();
        
            int row = 0;
            QSqlRecord rec = query.record();
            int colCount = rec.count();
        
            _data.clear();
        
            beginInsertRows( QModelIndex(), 0, query.size() );
            while( query.next() )
            {
                SqlDataStruct stuc;
                for( int column = 0; column < colCount; column++ )
                {
                    stuc._data.insert( column, query.value( column ).toString() );
                }
                _data.insert( row, stuc );
                qDebug() << "Inserted Row: " << insertRow( row );
                row++;
            }
            endInsertRows();
        
            QModelIndex topLeft = index( 0, 0 );
            QModelIndex bottomRight = index( row-1, colCount-1 );
        
            qDebug() << topLeft.isValid();
            qDebug() << bottomRight.isValid();
        
            emit dataChanged( topLeft, bottomRight );
        }
        

        insertColumn and insertRow are both always false.

        So, what I'm missing now?
        layoutChanged, modelReset?

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

        @Lachrymology said in QAbstractTableModel and dataChanged:

        But I'm not sure about:
        "Models that provide interfaces to resizable data structures can provide implementations of insertRows(), removeRows(), insertColumns(),and removeColumns()."
        The "CAN" confuses me - do I have to or is it optional?

        Yes, you have to. Read e.g. https://doc.qt.io/qt-5/qabstractitemmodel.html#insertRows

        Note: The base class implementation of this function does nothing and returns false.

        On models that support this, inserts count rows into the model

        The base does nothing but return false, so no insertion/deletion of rows or columns. If you have a mechanism for inserting rows into your data --- which you do --- then to make that available you must implement this, and the other virtuals you support.

        Also it concludes

        If you implement your own model, you can reimplement this function if you want to support insertions. Alternatively, you can provide your own API for altering the data. In either case, you will need to call beginInsertRows() and endInsertRows() to notify other components that the model has changed.

        1 Reply Last reply
        0
        • L Offline
          L Offline
          Lachrymology
          wrote on last edited by Lachrymology
          #10

          @JonB
          I'm confused.

          I have a data set/list.

          Via the methods "rowCount" and "columnCount" the model provides how many rows/columns are expected.

          Via "headerData" the model provides what the names of the head section are.

          Via the method "data" the model is iterating over the rows and columns.
          Within this it accesses the data set/list and provides it for each tupel.

          So far what my knowledge is, about why these are the major methods for read-only models.

          If I'm using, like in the beginning, only these methods, nothing will be displayed/updated/inserted.


          Ok the base of insertRow(s) returns false. In many examples this is mainly used to store external data within the internal data set/list without doing anything else than calling begin/endInsertRows. Same with insertColumn(s)

          This is what I'm doing within "setQuery" and "setHeader".


          If I'm looking at this example:
          https://doc.qt.io/archives/4.6/itemviews-addressbook-tablemodel-cpp.html

          I don't see, what I'm missing to have my model working with the QTableView.


          So again - why do I need exactly to implement such methods?

          1 Reply Last reply
          0
          • L Offline
            L Offline
            Lachrymology
            wrote on last edited by
            #11

            Found it on my own:

            Within setQuery I missed calling "begin/endResetModel".

            void SqlTableModel::setQuery( QString queryStr )
            {
                _queryStr = queryStr;
                SQL::execQuery( queryStr );
            
                QSqlQuery query = SQL::getLastQuery();
            
                int row = 0;
                QSqlRecord rec = query.record();
                int colCount = rec.count();
            
                beginResetModel();
                _data.clear();
            
                beginInsertRows( QModelIndex(), 0, query.size() );
                while( query.next() )
                {
                    SqlDataStruct stuc;
                    for( int column = 0; column < colCount; column++ )
                    {
                        stuc._data.insert( column, query.value( column ).toString() );
                    }
                    _data.insert( row, stuc );
                    qDebug() << "Inserted Row: " << insertRow( row );
                    row++;
                }
                endInsertRows();
                endResetModel();
            
                QModelIndex topLeft = index( 0, 0 );
                QModelIndex bottomRight = index( row-1, colCount-1 );
            
                qDebug() << topLeft.isValid();
                qDebug() << bottomRight.isValid();
            
                emit dataChanged( topLeft, bottomRight );
            }
            
            1 Reply Last reply
            0
            • Christian EhrlicherC Offline
              Christian EhrlicherC Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on last edited by Christian Ehrlicher
              #12

              I still don't understand why you implement your own setQuery() function...

              /edit: and beginInsertRows()/endInsertRows() is not needed (and may kill something internally) since you already call being/endResetModel(). Cascading those calls is not supported (and not needed at all)

              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
              Visit the Qt Academy at https://academy.qt.io/catalog

              L 1 Reply Last reply
              1
              • Christian EhrlicherC Christian Ehrlicher

                I still don't understand why you implement your own setQuery() function...

                /edit: and beginInsertRows()/endInsertRows() is not needed (and may kill something internally) since you already call being/endResetModel(). Cascading those calls is not supported (and not needed at all)

                L Offline
                L Offline
                Lachrymology
                wrote on last edited by
                #13

                @Christian-Ehrlicher
                Thanks for the hint.

                1 Reply Last reply
                0
                • F Offline
                  F Offline
                  FrozenTarzan
                  wrote on last edited by
                  #14

                  Despite the fact that this topic is rather old I wanted to clear things up for myself and maybe others as well. This is the first post that solved my problem.

                  The main point is that "read-only" models can still be updated by your code but they are "read-only" for the user. So there is no user interaction/manipulation of the data because the corresponding methods are not implemented in the model.

                  When you now update your internal data e.g. a list or a table or basically any crazy internal representation of your data, you have to notify the model that you did that which in turn notifies all interested views to update them as well.

                  And here is the problem in the documentation Qt 6 version of model/view concepts. It mentions "read-only" models but does not talk ab out the "beginXYZ" methods. When it does talk about those it is always in the context of insert/removeRow/Column which again is not what you need and want for "read-only" models.

                  What you need is the beginReset and endReset methods called from where you update your internal data. Or you have to somehow fiddle with the beginInsert.../endInsert... methods if you really want to.

                  So in short: When implementing models that are read-only from the user's perspective you still need to notify your model when you manipulate your internal data.

                  For @Lachrymology and me the following would have worked. Note that there is no need for any signals to be emitted and there is no nested rows/reset method. It simply tells the model that the data is going to be reset, then resets the data and in the end it lets the model know that the reset has finished. All signals are emitted internally and my view is updated like charme : - )

                  void MyReadOnlyModel::setMyInternalData(QList<int> data)
                  {
                      beginResetModel();
                      m_Data = data;
                      endResetModel();
                  }
                  
                  1 Reply Last reply
                  1
                  • JonBJ JonB

                    @Lachrymology
                    Before you go any further: from your use of SQL & Sql (you don't tell us what they are derived from) all over the place, if this is to serve a SQL database why are you attempting to use QAbstractTableModel etc. when all the stuff is already available to you from the QSql... classes?

                    If you were using, say, QSqlTableModel your SqlTableModel::setQuery() wouldn't look anything like whatever you are doing here. In fact, none of it would, it's written for you!

                    A Offline
                    A Offline
                    ArthurPYQT
                    wrote on last edited by
                    #15

                    @JonB I've a tableview implemented with QSqlQueryModel, I have to override the setData() method, but I cannot find a way to refresh the view except setQuery() method. I just want to refresh a row not the whole view. The reason why I use QSqlQueryModel is I have to fetch data from two tables.

                    JonBJ 1 Reply Last reply
                    0
                    • A ArthurPYQT

                      @JonB I've a tableview implemented with QSqlQueryModel, I have to override the setData() method, but I cannot find a way to refresh the view except setQuery() method. I just want to refresh a row not the whole view. The reason why I use QSqlQueryModel is I have to fetch data from two tables.

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

                      @ArthurPYQT
                      Does this have anything to do with the question you are asking in https://forum.qt.io/topic/126735/insertrow ? Don't know why you posting here and addressing me.

                      You cannot just fetch one row from the database into the model and then expect the model to still show all rows. I don't know what this has to do with setData().

                      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