Search code examples
qtloopsmodelalignmenttableview

How to set text alignment for all the data in the tableView without using FOR loop?


I have create a tableView from database. Then, how to make set text alignment for all the data in this tableView? I do not want to use for loop to set each item in the tableView since it is time consuming.

The main code is as follows:

QSqlRelationalTableModel *model= new QSqlRelationalTableModel(NULL, db);    
model->setTable(dbName);
model->select();

QTableView *tableView = new QTableView(NULL);
tableView->setModel(model);

Some may suggest to make a subclass of QSqlRelationalTableModel, but this also need a for loop to set all the data. Is there any other option? Thank you.


Solution

  • Use QIdentityProxyModel (since 4.8 - however, the idea is the same using a QAbstractProxyModel, the former is simply a convenience class that saves you time by allowing to reimplement only the methods you need). This approach avoids using a for loop since the data is set and returned at the moment it is being requested request on a per-element basis. In other words, instead of iterating over all the data and setting the required value (i.e. an imperative approach), you modify a method in the class that provides data to the view (more of a declarative approach), and the view pulls the data when necessary on its own.

    To quote the docs:

    http://doc.qt.io/qt-5/qidentityproxymodel.html

    The QIdentityProxyModel class proxies its source model unmodified. Because it does no sorting or filtering, this class is most suitable to proxy models which transform the data() of the source model. For example, a proxy model could be created to define the font used, or the background colour, or the tooltip etc. This removes the need to implement all data handling in the same class that creates the structure of the model, and can also be used to create re-usable components.

    For our case, a possible implementation follows:

    class StylingProxyModel : public QIdentityProxyModel
    {
      QVariant data(const QModelIndex &index, int role) const
      {
        if (role != Qt::TextAlignmentRole)
          return QIdentityProxyModel::data(index, role);
    
        return Qt::AlignCenter;
      }
    };
    

    As you can see, the model will pass through itself the part of the data that doesn't match Qt::TextAlignmentRole, and return the desired value otherwise.

    Set the QSqlRelationalTableModel as the source of this custom identity model, and set the proxy model to be the source for the view.

    The "heavy artillery" option would be to subclass QStyledItemDelegate but I feel it's overkill for the case in question, being better suited for tasks that modify the view / delegate appearance in more profound ways than just setting text alignment.

    See Set color to a QTableView row for further reading.