Frage

Meine Anwendung speichert einige Objekte eines Typs, der von erbt QAbstractListModel Gegenst.

Dies erzeugt beim Umschließen eines einfachen Codes ziemlich viel doppelten Code std::vector<T> oder ein QList<T> in das Modell mit dem allgemeinen add, lösch- und Mehrfachauswahl-Funktionalität.

Ist das der Weg QAbstractListModel soll benutzt werden oder ist da einige Adapterklassen, die den doppelten Code entfernen können (zumindest für container, die Teil von Qt sind)?

Beispiel:Ich möchte wickeln vector<ObjectA> und vector<ObjectB> in ein Modell.Der Code für insertRows, deleteRows, columnCount usw.wird immer gleich sein und ich möchte das konsolidieren (mit ein wenig Metaprogrammierung, die sogar mit funktionieren könnte tuple und data).

War es hilfreich?

Lösung

Sie müssen dies in zwei separaten Klassen tun, da die Erweiterungen von Qt zu c ++ (SIGNALE, SLOTS usw.).) spielen Sie nicht gut mit Vorlagen.Die Begründung und Problemumgehung dafür finden Sie unter: http://doc.qt.digia.com/qq/qq15-academic.html

Hier ist eine grobe Skizze einer Lösung.(Dies basiert auf Code, den wir in unserer Anwendung verwenden und der einwandfrei funktioniert.)

1.Abstrakte Listenklasse, die Qt-Sachen macht

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.Abstrakte Klasse, die Template-Sachen macht

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.Aktuelle Listenklasse

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

Andere Tipps

Normalerweise würde ich mein eigenes Modell implementieren, das von erbt QAbstractItemModel direkt und stelle meine eigene Implementierung für die Präsentationsfunktionen wie z data() um mit dem Datenspeichercontainer umzugehen, gebe ich das Modell.

Wenn Sie Code-Duplizierung zur Verwendung haben QList<T> und std::vector<T> dann würde ich vorschlagen, das eine in das andere umzuwandeln, indem ich entweder folgendes tue:

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

oder andersherum.

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

Ich würde Letzteres tun, aber Sie können auch wählen.

Basierend auf Ihren zusätzlichen Kommentaren gibt es 2 Handlungsmöglichkeiten, die Sie ergreifen können:

Weg 1:

Implementieren objectA und objectB wie folgt:

class objectA : baseObject

und

class objectB : baseObject

wo baseObject is:

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

Wahrscheinlich einfacher in String zu konvertieren als alles andere.

Pfad 2 beinhaltet im Wesentlichen die Verwendung innerhalb des Modells std::vector<boost::any>() auf diese Weise können Sie als Datenspeichercontainer eine einzelne Modellunterklasse implementieren QAbstractListModel.

Die Sache, die Sie berücksichtigen müssen, dass, wenn Ihr Datenspeichercontainer Sie wahrscheinlich die Datenpräsentation gemeinsam machen können, Sie begrenzt sind, was Sie tun können, weil data() funktion, die Ihrer Ansicht gibt, dass das Element zurückgegeben werden muss QVariant und es ist begrenzt auf das, woraus Sie es konstruieren können.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top