Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QAbstractListModel and QList Adapter

My application stores a few objects of a type that inherits from QAbstractListModel objects.

This generates quite a lot of duplicated code when wrapping a simple std::vector<T> or a QList<T> into model with the general add, delete and multi-selection functionality.

Is that the way QAbstractListModel is supposed to be used or is there some adapter class that can remove the duplicated code (at least for containers that are part of Qt)?

Example: I want to wrap vector<ObjectA> and vector<ObjectB> into a model. The code for insertRows, deleteRows, columnCount etc. is always going to be the same and I would like to consolidate that (with a little meta-programming that could even work for with tuple and data).

like image 564
pmr Avatar asked Jan 17 '12 13:01

pmr


1 Answers

You have to do this in two separate classes because Qt's extensions to c++ (SIGNALS, SLOTS, etc.) do not play well with templates. The rationale and workaround for this can be found at: https://doc.qt.io/archives/qq/qq15-academic.html

Here is a rough outline of a solution. (This is based on code we are using in our application and that is working fine.)

1. Abstract list class that does Qt stuff

class FooListModelQt : public QAbstractTableModel {
  Q_OBJECT

public:
  // Non-template methods, signals, slots, etc. can be used here. For example...
  QSet<int> SelectedRows() const;
  // ... etc. ...

signals:
  void SelectionChanged();
  // ... etc. ...

protected:
  explicit FooListModelQt(QObject *parent = NULL);
  virtual ~FooListModelQt() = 0;
  // ... etc. ...

};

2. Abstract class that does template stuff

template <typename T>
class FooListModel : public FooListModelQt {
public:
  const T* at(int index) const { return items_.at(index); }
  int count() const { return items_.count(); }
  void Append(T *item);
  // ... etc. ...

protected:
  explicit FooListModel(QObject *parent = NULL);
  virtual ~FooListModel();

private:
  QList<T*> items_;
};

3. Actual list class

class BarListModel : public FooListModel<Bar> {
  Q_OBJECT

public:
  explicit BarListModel(QObject *parent = NULL);
  int columnCount(const QModelIndex &parent) const;
  QVariant data(const QModelIndex &index, int role) const;
  // ... etc. ...
};
like image 182
Dave Mateer Avatar answered Nov 15 '22 05:11

Dave Mateer