Question

Mon application stocke quelques objets d'un type qui hérite deQAbstractListModel objets.

Cela génère beaucoup de code dupliqué lors de l'emballage d'un simplestd::vector<T> ou un QList<T> dans le modèle avec les fonctionnalités générales d'ajout, de suppression et multi-sélection.

Est-ce le chemin QAbstractListModel est censé être utilisé ou y a-t-il une classe d'adaptateur qui peut supprimer le code dupliqué (au moins pour les conteneurs qui font partie de QT)?

Exemple: je veux envelopper vector<ObjectA> et vector<ObjectB> dans un modèle. Le code pour insertRows, deleteRows, columnCount etc. va toujours être le même et je voudrais consolider cela (avec une petite méta-programmation qui pourrait même fonctionner avec tuple et data).

Était-ce utile?

La solution

Vous devez le faire dans deux classes distinctes car les extensions de QT vers C ++ (signaux, machines à sous, etc.) ne jouent pas bien avec les modèles. La justification et la solution de contournement pour cela peuvent être trouvées à: http://doc.qt.digia.com/qq/qq15-academic.html

Voici un aperçu approximatif d'une solution. (Ceci est basé sur le code que nous utilisons dans notre application et cela fonctionne bien.)

1. Classe de liste abstraite qui fait des trucs 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. classe abstraite qui fait des trucs de modèle

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. Classe de liste réelle

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

Autres conseils

Normalement, j'implémenterais mon propre modèle héritant de QAbstractItemModel directement et fournir ma propre implémentation pour les fonctions de présentation telles que data() Pour gérer le conteneur de stockage de données, je donne le modèle.

Si vous avez du code de duplication pour l'utilisation QList<T> et std::vector<T> Ensuite, je suggérerais de convertir l'un à l'autre en faisant soit:

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

ou dans l'autre sens.

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

Je ferais ce dernier mais vous pouvez choisir non plus.

Sur la base de vos commentaires supplémentaires, vous pouvez emprunter 2 chemins d'action:

Chemin 1:

Mettre en place objectA et objectB comme suit:

class objectA : baseObject

et

class objectB : baseObject

baseObject est:

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

Probablement plus facile à convertir en chaîne que toute autre chose.

Le chemin 2 impliquera essentiellement à l'intérieur du modèle en utilisant std::vector<boost::any>() Comme votre conteneur de stockage de données, vous pouvez implémenter un seul modèle de sous-classe QAbstractListModel.

La chose que vous devez considérer que si votre conteneur de stockage de données, vous pouvez probablement faire de la présentation des données, vous êtes limité à ce que vous pouvez faire parce que data() Fonction qui donnera votre avis que l'élément doit revenir QVariant Et c'est limité à ce à quoi vous pouvez le construire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top