QAbstractListModel e QList Adattatore
-
29-10-2019 - |
Domanda
La mia applicazione memorizza i pochi oggetti di un tipo che eredita da
QAbstractListModel
oggetti.
Questo genera un bel po ' di codice duplicato quando il confezionamento di un semplice
std::vector<T>
o un QList<T>
nel modello con l'aggiunta generale,
eliminare e multi-selezione funzionalità.
È questo il modo QAbstractListModel
è supposto per essere utilizzato o c'è
alcuni adattatore di classe in grado di rimuovere il codice duplicato (almeno per
i contenitori che sono parte di Qt)?
Esempio:Vorrei concludere vector<ObjectA>
e vector<ObjectB>
in un modello.Il codice per insertRows
, deleteRows
, columnCount
ecc.sta andando sempre essere la stessa e vorrei consolidare (con un po ' di meta-programmazione che potrebbe anche lavorare per la con tuple
e data
).
Soluzione
È necessario eseguire questa operazione in due classi separate a causa di Qt estensioni c++ (SEGNALI, SLOT, ecc.) non si gioca bene con i modelli.La motivazione e la soluzione alternativa per questo può essere trovato a: http://doc.qt.digia.com/qq/qq15-academic.html
Ecco un abbozzo di soluzione.(Questo è basato sul codice che si sta utilizzando nella nostra applicazione, e che sta lavorando bene.)
1.Elenco astratto classe che fa Qt roba
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 astratta che fa il modello di roba
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.Elenco effettivo di classe
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. ...
};
Altri suggerimenti
Di norma, vorrei implementare il proprio modello di ereditare da QAbstractItemModel
direttamente e il mio attuazione per la presentazione di funzioni come data()
per gestire i dati del contenitore di stoccaggio io do il modello.
Se si dispone di una duplicazione del codice per l'utilizzo di QList<T>
e std::vector<T>
allora io suggerirei di conversione da fare:
QList<T> list = QList::fromVector(QVector::fromStdVector(vector));
o in altro modo.
std::vector<T> vector = qlist.toVector().toStdVector();
Mi piacerebbe fare il secondo, ma si può scegliere.
Basato sui vostri ulteriori commenti ci sono 2 percorsi di azione che si può prendere:
Percorso 1:
Implementare objectA
e objectB
come segue:
class objectA : baseObject
e
class objectB : baseObject
dove baseObject
è:
struct baseObject
{
virtual std::string toString() = 0;
};
Probabilmente più facile da convertire in stringa di qualsiasi altra cosa.
Percorso 2 sarà essenzialmente coinvolgere all'interno del modello utilizzando std::vector<boost::any>()
come l'archiviazione dei dati contenitore, in questo modo è possibile implementare un modello unico e la creazione di sottoclassi QAbstractListModel
.
La cosa che devi considerare che, se i dati del contenitore di stoccaggio probabilmente si può fare in comune la presentazione dei dati si sono limitati a ciò che si può fare, perché data()
funzione che darà vostro punto di vista l'elemento di ritorno QVariant
ed è limitata a ciò che si può costruire da.