0

This question is an upgrade on the following two questions:

Here is the situation:

enter image description here

MODEL has a pointer to the SERVER (SERVER represents Data) through which it gets the required data and formats them into QStrings, so that the VIEW can understand them. The model keeps no internal copies of the QList, it accesses it directly and converts the requ QTcpSocket * to QStrings in the QVariant QAbstractItemModel::data method.

However the list of sockets can change without the Model or View knowing about it if a new connection to the SERVER is established. In that case another QTcpSOcket * is appended to the SERVERs QList.

How to notify the View on the Model/Data change?

  • Call QAbstractItemModel::reset() from the SERVER on each new connection. I consider this bad for it requires to modify the SERVER for the needs of the MODEL in which case i could of just had the MODEL and the SERVER as a single entity.

  • connect(&server, QTcpServer::newConnection, &model, &StationListModel::reset) Try to connect the SERVER and MODEL via Signals and Slots. However, &StationListModel::reset ISN'T a slot, so i believe this isn't the right way.

I would like to hear which of the mentioned approaches (if any) is considered appropriate in the given situation. And is the insisting on MODEL-SERVER loose coupling a bad design choice?

Community
  • 1
  • 1
TheMeaningfulEngineer
  • 15,679
  • 27
  • 85
  • 143

3 Answers3

1

Here is how it should be done:

  1. Create signals in SERVER that notify about data change (or use existing QTcpServer::newConnection signal if it is sufficient).
  2. Create a slot (or slots) in your model class and connect SERVER's signal to this slot.
  3. In the slot's implementation emit signals or call internal methods (e.g. beginInsertRows, endInsertRows) or just reset the model to notify the view about new changes.
Pavel Strakhov
  • 39,123
  • 5
  • 88
  • 127
0

Since you need to incrementally append new items to your view, I would do this in the following way:

In your model class

// A slot
void MyModel::onNewConnection()
{
    // Append new socket to the list QList<QTcpSocket *>
    m_socketList.puch_back(new QTcpSocket);
    // Update the model.
    insertRow(0);
}

// Virtual function
bool MyModel::insertRows(int row, int count, const QModelIndex &parent)
{
    if (!parent.isValid()) {
        // We need to append a row to the bottom of the view.
        int rows = rowCount() - 1;

        beginInsertRows(parent, rows, rows);
        // Do nothing, but just inform view(s) that the internal data has changed
        // and these rows should be added.
        endInsertRows();
        return true;
    }
    return QAbstractItemModel::insertRows(row, count, parent);
}

Somewhere in your code

[..]
connect(&server, QTcpServer::newConnection, &model, &StationListModel::onNewConnection)
vahancho
  • 20,808
  • 3
  • 47
  • 55
0

I know this is an old question, but I would like to share what I do when I was working on the exactly same issue. If you are placing the server pointer into the model implementation and you get all the model information from the QList< QTcpSocket *> use this connection:

connect(server, SIGNAL(newConnection()), this, SIGNAL(modelReset()));
lennon310
  • 12,503
  • 11
  • 43
  • 61
albertTaberner
  • 1,969
  • 1
  • 26
  • 35