Вопрос

Мое приложение хранит несколько объектов типа, который наследуется от QAbstractListModel объекты.

Это генерирует довольно много дублированного кода при переносе простого std::vector<T> или в QList<T> в модель с общей функциональностью добавления, удаления и множественного выбора.

Это тот самый способ QAbstractListModel предполагается использовать или есть какой-то класс адаптера, который может удалить дублированный код (по крайней мере, для контейнеров, которые являются частью Qt)?

Пример:Я хочу завернуть vector<ObjectA> и vector<ObjectB> в модель.Код для insertRows, deleteRows, columnCount и т.д.всегда будет одним и тем же, и я хотел бы закрепить это (с помощью небольшого метапрограммирования, которое могло бы работать даже с tuple и data).

Это было полезно?

Решение

Вы должны сделать это в двух отдельных классах, потому что расширения Qt для c++ (СИГНАЛЫ, слоты и т.д.) плохо сочетаются с шаблонами.Обоснование и обходной путь для этого можно найти по адресу: http://doc.qt.digia.com/qq/qq15-academic.html

Вот приблизительный набросок решения.(Это основано на коде, который мы используем в нашем приложении, и который работает нормально.)

1.Абстрактный класс списка, который выполняет функции Qt

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.Абстрактный класс, который выполняет шаблонные функции

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.Фактический класс списка

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. ...
};

Другие советы

Обычно я бы реализовал свою собственную модель, наследующую от QAbstractItemModel непосредственно и предоставляю свою собственную реализацию для функций презентации, таких как data() для обработки контейнера для хранения данных я даю модель.

Если у вас есть дублирование кода для использования QList<T> и std::vector<T> тогда я бы предложил преобразовать одно в другое, выполнив либо:

QList<T> list = QList::fromVector(QVector::fromStdVector(vector));

или в другую сторону.

std::vector<T> vector = qlist.toVector().toStdVector();

Я бы сделал последнее, но вы можете выбрать и то, и другое.

Основываясь на ваших дополнительных комментариях, вы можете предпринять 2 варианта действий:

Путь 1:

Осуществлять objectA и objectB следующим образом:

class objectA : baseObject

и

class objectB : baseObject

где baseObject является:

struct baseObject
{
    virtual std::string toString() = 0;
};

Вероятно, проще преобразовать в строку, чем что-либо еще.

Путь 2 в основном будет включать в себя использование внутри модели std::vector<boost::any>() в качестве контейнера для хранения данных, таким образом, вы можете реализовать единый подкласс модели QAbstractListModel.

Дело в том, что вы должны учитывать, что если ваш контейнер для хранения данных вы, вероятно, можете сделать общим для представления данных, вы ограничены в том, что вы можете сделать, потому что data() функция, которая передаст вашему представлению, что элемент должен возвращать QVariant и он ограничен тем, из чего вы можете его сконструировать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top