[Solved] QAbstractTableModel rowsInserted (const QModelIndex & parent, int start, int end) signal



  • Hi,

    I am trying to connect this signal from my abstracted class to a slot in my MainWindow. However, this signal is never presented as an option from the auto-completion list on the SIGNAL macro. My model is read only and these methods I've re-implemented:
    @
    QVariant data(const QModelIndex &index, int role) const ;
    Qt::ItemFlags flags(const QModelIndex &index) const ;
    QVariant headerData(int section, Qt::Orientation orientation, int role) const ;
    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const ;
    int rowCount(const QModelIndex &parent = QModelIndex()) const ;
    int columnCount(const QModelIndex &parent = QModelIndex()) const ;
    @

    If I proceed and ignore the auto-completion and hard code this connect(ion) I get an error telling me that there is no such signal but according to the documentation it is one of the 18 signals inherited from QAbstractItemModel. I have never really used Qt before (which I know is no excuse) but yet again I am left confused.

    Can anyone point me in the right direction with this please.

    William



  • Normally, you don't need to connect to that signal manually. Views or proxy models automatically make the needed connections when you set a source model on them. So why do you need this?

    Still, you are right, this signal is there in QAbstractItemModel. Are you sure your model publicly inherits from QAbstractItemModel?



  • Are you sure that you have #include'd the header file for your model into the file where you are trying to make the connection?

    Could you post the problematic code please?



  • Hey Guys, thanks for the replies.

    The model's header file is included in MainWindow.h as I need it there as you will see.

    Here is the code I am using in MainWindow.cpp:
    @
    m_Model = new MyDerivedModel(0) ;
    if (m_Model)
    {
    // Load data from file.
    if (m_Model->load("./input.xml"))
    {
    // Assign the model to the view
    ui->myModelView->setModel(m_Model);
    connect(m_Model, SIGNAL(rowsInserted ( const QModelIndex & parent, int start, int end )), this, SLOT(modelRowsInserted ( const QModelIndex & parent, int start, int end ))) ;
    }
    }
    @

    And to answer Andre's question I want know to when rows are added so I can have a look at the new rows' data and take any required action.
    Header:
    @
    class MyDerivedModel : public QAbstractTableModel
    {
    Q_OBJECT
    ...
    } ;
    @
    Source:
    @
    MyDerivedModel::MyDerivedModel(QObject *parent) : QAbstractTableModel(parent)
    }
    @

    Further thoughts would be appreciated.

    --
    William



  • @
    MyDerivedModel::MyDerivedModel(QObject *parent) : QAbstractTableModel(parent)
    {
    ...
    }
    @

    Shouldn't that be:
    @
    MyDerivedModel::MyDerivedModel(QObject *parent) : public QAbstractTableModel(parent)
    {
    ...
    }
    @

    Edit:
    See below: of course it should not. I mistook the code as a declaration, instead of implementation (despite that having been clearly stated). I usually write the implementation like this, hence the confusion I guess:
    @
    MyDerivedModel::MyDerivedModel(QObject *parent) :
    QAbstractTableModel(parent)
    {
    ...
    }
    @



  • Andre, not in the implementation no.

    The problem is in the connect statement. You should not pass argument names in to the connect call. Your connect statement should look like this:

    @
    connect(m_Model, SIGNAL(rowsInserted( const QModelIndex&, int, int) ),
    this, SLOT(modelRowsInserted ( const QModelIndex&, int, int) ) );
    @



  • [quote author="ZapB" date="1304519890"]Andre, not in the implementation no.[/quote]
    "D'oh":http://en.wikipedia.org/wiki/D'oh! !
    Of course not.

    ZabB is absolutely right.



  • Hi Guys,

    The (schoolboy error of mine) with arguments in the connect(ion) now removed has solved the error, thank you but that still doesn't explain why the signal doesn't appear in the auto-completion list!

    Thank's again.

    --
    William



  • That, I think, would be an issue of Qt Creator.



  • That's a separate issue and likely related to Qt-Creator's code model. Which version of creator are you using?



  • To answer your question ZapB I am using v2.1.0 (Qt 4.7.1) 32 bit on Windows Vista x64

    Also now I have my signal connected I don't get notification of any rows being added!

    I have changed the code to this:
    @
    if (m_Model)
    {
    if (connect(m_Model, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(modelRowsInserted(QModelIndex, int, int))))
    {
    // Load model from file.
    if (m_Model->load("./input.xml"))
    {
    // Assign the model to the view
    ui->myModelView->setModel(m_Model);
    }
    }
    }
    @

    With my slot being:
    @
    void MainWindow::modelRowsInserted ( const QModelIndex & parent, int start, int end )
    {
    qDebug() << "Rows Added to Model" ;
    }
    @

    But I never see any output in the Application Output console even though my model correctly displays the (processed) content of the input file. In this instance I would have expected to see two lines in the output console based on the content of the file and what is correctly displayed in the View.

    --
    William



  • That might suggest that your model is not correctly implemented.



  • I agree with Andre. Do you call beginInsertRows() and endInsertRows() around the place where you actually modify your internal data structure? Can you post this piece of code please?



  • Hi,

    Well I cannot see what else I am missing as as far as I can tell I have no need to re-implement anything other than those already listed as this is a read only model. I am relying on (my assumption) that this signal will (should) get emitted (via the default implementation) when a new row is inserted.

    --
    William



  • Hi William,

    who should add rows that emit this signal?
    If you change the content of the model, you have to call the defined methods, like begine/end insert Rows/columns. Same for remove.
    Without calling these, the signals will not be emitted.

    EDIT: I assume, the content of your model is static? Or is it dynamic? if it is dynamic, the model is responsible for notifying the clients.



  • Read-only model means read-only as far as the QAbstractItemModel's interface is concerned. ie an attached view will not allow users to edit the model. However, you are still changing the model when you load your data and so you need to call beginInsertRows() and endInsertRows() around the place where you modify your underlying data structure. It is the call to endInsertRows() that causes your missing signal to be emitted. How else would the model know what you are doing behind it's back?



  • Thanks Gerolf and ZapB, it's just got very bright in here. :-)

    Thanks again.

    --
    William



  • No worries. I remember the pains of learning the modelview architecture. It can be confusing. The trick is to remember that QAbstractItemModel is only an interface to your data that us used by the views. You have to nudge it it the right direction when you change your data behind it's back by calling the appropriate protected functions.

    Good luck with the rest of your project!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.