QSortFilterProxyModel subclass for text alignment and readonly columns

When using the model/view framework it is not possible to:

  1. enable or disable different columns of the table
  2. set text alignment for different columns
    For this I created the following code after a thread I posted link [developer.qt.nokia.com]. Here it is the code:

Header

  1. #ifndef PROXYMODEL_HPP
  2. #define PROXYMODEL_HPP
  3.  
  4. #include <QSortFilterProxyModel>
  5. #include <QMap>
  6.  
  7. class ProxyModel : public QSortFilterProxyModel {
  8. Q_OBJECT
  9. // PRIVATE VARIABLES
  10. QMap<int,Qt::Alignment> alignMap;
  11. QMap<int,Qt::ItemFlags> flagMap;
  12.  
  13. public:
  14. // CONSTRUCTOR
  15. explicit ProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent) {}
  16.  
  17. // VIRTUAL FUNCTIONS INHERITED FROM QT SORT FILTER MODEL
  18. QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
  19. Qt::ItemFlags flags(const QModelIndex &index) const;
  20.  
  21. // PUBLIC FUNCTIONS
  22. void setAlignment(unsigned int, Qt::Alignment);
  23. void setAlignmentToAll(Qt::Alignment);
  24. void clearAlignment();
  25.  
  26. void setFlag(unsigned int, Qt::ItemFlags);
  27. void setFlagToAll(Qt::ItemFlags);
  28. void clearFlag();
  29.  
  30. void setEnabled(unsigned int index, bool FLAG);
  31. void setEditable(unsigned int index, bool FLAG);
  32. };
  33.  
  34. #endif // PROXYMODEL_HPP

Source file

  1. #include "proxymodel.hpp"
  2.  
  3. // ================== DATA ===================
  4.  
  5. QVariant ProxyModel::data(const QModelIndex &index, int role) const {
  6.  // if text alignment is asked for enters
  7.  if(role == Qt::TextAlignmentRole) {
  8.   // if the column alignment was set-up for all columns
  9.   if(alignMap.contains(-1))
  10.    return QVariant(alignMap.value(-1));
  11.   // searches if the column alignment was set-up and returns the flag
  12.   if(alignMap.contains(index.column())) {
  13.    return QVariant(alignMap.value(index.column()));
  14.   }
  15.  }
  16.  // if the column wasn't found or if alignment wasn't requested returns default QVariant
  17.  return QSortFilterProxyModel::data(index, role);
  18. }
  19.  
  20. void ProxyModel::setAlignment(unsigned int index, Qt::Alignment flag) {
  21.  // checks if setAlignmentToAll() was called and, if so, rests alignMap
  22.  if(alignMap.contains(-1))
  23.   clearAlignment();
  24.  // inserts flag
  25.  alignMap.insert(index, flag);
  26. }
  27.  
  28. void ProxyModel::setAlignmentToAll(Qt::Alignment flag) {
  29.  // reset QMap
  30.  clearAlignment();
  31.  // inserts flag
  32.  alignMap.insert(-1, flag);
  33. }
  34.  
  35. void ProxyModel::clearAlignment() {
  36.  // deletes all items
  37.  alignMap.clear();
  38. }
  39.  
  40. // ================== FLAGS ==================
  41.  
  42. Qt::ItemFlags ProxyModel::flags(const QModelIndex &index) const {
  43.  // if the column alignment was set-up for all columns
  44.  if(flagMap.contains(-1))
  45.   return flagMap.value(-1);
  46.  // searches if the column alignment was set-up and returns the flag
  47.  if(flagMap.contains(index.column())) {
  48.   return flagMap.value(index.column());
  49.  }
  50.  return QSortFilterProxyModel::flags(index);
  51. }
  52.  
  53. void ProxyModel::setFlag(unsigned int index, Qt::ItemFlags flag) {
  54.  // checks if setFlagToAll() was called and, if so, rests flagMap
  55.  if(flagMap.contains(-1))
  56.   clearFlag();
  57.  // inserts flag
  58.  flagMap.insert(index, flag);
  59. }
  60.  
  61. void ProxyModel::setFlagToAll(Qt::ItemFlags flag) {
  62.  // reset QMap
  63.  clearFlag();
  64.  // inserts flag
  65.  flagMap.insert(-1, flag);
  66. }
  67.  
  68. void ProxyModel::clearFlag() {
  69.  // deletes all items
  70.  flagMap.clear();
  71. }
  72.  
  73. void ProxyModel::setEnabled(unsigned int index, bool FLAG) {
  74.  if(FLAG)
  75.   setFlag(index, Qt::NoItemFlags | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled);
  76.  else
  77.   setFlag(index, Qt::NoItemFlags);
  78. }
  79.  
  80. void ProxyModel::setEditable(unsigned int index, bool FLAG) {
  81.  if(FLAG)
  82.   setFlag(index, Qt::NoItemFlags | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled);
  83.  else
  84.   setFlag(index, Qt::NoItemFlags | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled);
  85. }

Example

  1. table_model = new QSqlTableModel(this, QSqlDatabase::database(connection_name));
  2. proxyModel = new ProxyModel(this);
  3.  
  4. // TABLE'S PROXY SET-UP
  5. proxyModel->setAlignment(0, Qt::AlignCenter); // Align center in both vertical and horizontal the first column
  6. proxyModel->setAlignment(1, Qt::AlignCenter);
  7. ...
  8.  
  9. proxyModel->setEditable(0, 0); // set the column enabled and selectable but not editable
  10. proxyModel->setEnabled(1, 0); // set the column disabled
  11. ...
  12.  
  13. // TABLE MODEL SET-UP
  14. table_model->setTable("account");
  15. table_model->select(); // query execution
  16.  
  17. // TABLE VIEW SET-UP
  18. proxyModel->setSourceModel(table_model);
  19. ui->tableView->setModel(proxyModel); // the model used for the view is the proxymodel

Note that you do not need to connect the proxy with the source model before starting to configure it. It is independent. You can assign infinite (limited by hardware) column properties and apply them to any model (to be tested). You can find all the existant Qt::Alignment and Qt::ItemFlags in Qt documentation.

In my program, I am using a QSqlRelationalTableModel and when this proxymodel was applied the combo boxes were replaced with text edit boxes on the QTableView… the solution for this you can find it here [developer.qt.nokia.com].

Categories: