У меня есть:
- класс модели c ++ ( Банк ) для хранения простых объектов данных ( Коэффициент ):
typedef quint32 Coefficient;
class Bank : public QObject
{
Q_OBJECT
Q_PROPERTY(QList<Coefficient> coefficients READ coefficients WRITE setCoefficients NOTIFY coefficientsChanged)
public:
explicit Bank(QList<Coefficient> coefficients = QList<Coefficient>(), QObject *parent = nullptr);
QList<Coefficient> coefficients() const;
void setCoefficients(QList<Coefficient> coefficients);
// ...
signals:
void coefficientsChanged(QList<Coefficient> coefficients);
private:
QList<Coefficient> _coefficients;
};
класс AbstractListModel (
BankClass ) для работы с представлениями через данные:
class Bank;
class BankModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(Bank* bank READ bank WRITE setBank)
public:
enum {
CoefficientRole = Qt::UserRole
};
explicit BankModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = CoefficientRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex& index) const override;
QHash<int, QByteArray> roleNames() const override;
Bank* bank() const;
void setBank(Bank* bank);
private:
Bank* _bank;
};
модель на основе QObjectList для хранения нескольких моделей AbstractListModel (
BankModel )
class CoefficientListModel;
class ConfigModel : public QObject
{
Q_OBJECT
Q_PROPERTY(QList<QObject*> banks READ banks WRITE setBanks NOTIFY banksChanged)
public:
explicit ConfigModel(QList<QObject*> banks = QList<QObject*>(), QObject *parent = nullptr);
QList<QObject*> banks() const;
void setBanks(QList<QObject*> banks);
signals:
void banksChanged(QList<QObject*> banks);
private:
QList<QObject*> _banks;
};
и представление qml, чтобы настроить все это (main.qml):
Window {
// ...
ListView {
// ...
model: cfg // ConfigModel
delegate: ConfigDelegate {
// ...
ListView {
model: model.bank // BankModel
delegate: BankDelegate {
some int property: coefficient // my role in bank model
}
}
}
}
}
, где cfg - это зарегистрированное в main. cpp object:
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<CoefficientListModel>("Config", 1, 0, "CoefficientListModel");
qmlRegisterType<ConfigModel>("Config", 1, 0, "ConfigModel");
ConfigModel cfg;
cfg.setBanks(QList<QObject*>()
<< new CoefficientListModel(QList<Coefficient>({ Coefficient { 11 }, Coefficient { 21 }, Coefficient { 31 }, Coefficient { 41 } }))
// ...
<< new CoefficientListModel(QList<Coefficient>({ Coefficient { 15 }, Coefficient { 25 }, Coefficient { 35 }, Coefficient { 45 } }))
);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty(QStringLiteral("cfg"), &cfg);
engine.rootContext()->setContextProperty(QStringLiteral("client"), &client);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
Итак, как установить модели c ++ в этой глубине qml от верхнего уровня? Или что здесь не так? Это правильная архитектура приложения?
Это должно выглядеть, как на рисунке ниже.
Редактировать:
Теперь у меня есть класс в виде элемента дерева:
class CoefficientItem
{
public:
CoefficientItem(quint32 value = -1, int row = 0, CoefficientItem* parent = nullptr);
~CoefficientItem();
CoefficientItem *childAt(int i);
int childrenCount();
CoefficientItem *parent();
quint32 value() const;
int row() const;
void setValue(const quint32& value);
void setParent(CoefficientItem* parent_item);
void appendChild(CoefficientItem* child);
private:
quint32 _value;
CoefficientItem* _parent_item;
QHash<int, CoefficientItem*> _child_items;
int _row_number;
};
и модель дерева:
class ConfigModel : public QAbstractItemModel
{
Q_OBJECT
enum { CoefficientRole = Qt::UserRole };
public:
explicit ConfigModel(const QVector<QVector<quint32>>& config, CoefficientItem* root = nullptr, QObject *parent = nullptr);
~ConfigModel();
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &index) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = CoefficientRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex& index) const override;
void setModelUp(const QVector<QVector<quint32> >& config);
private:
CoefficientItem* _root_item;
};
И проблема теперь заключается в доступе к внутреннему уровню модели дерева. В main.qml у меня есть представление списка:
ListView {
anchors.fill: parent
model: DelegateModel {
model: cfg
delegate: BankView {}
}
}
BankView.qml - делегат, состоящий из BankViewHeader.qml ( как флажок) и BankViewDescription.qml (как компонент со списком текстовых полей)
BankView.qml :
Rectangle {
id: bank_view
width: parent.width
height: bank_view_column.height
color: "#946782"
Column {
id: bank_view_column
spacing: 0
clip: true
BankViewHeader {
id: checker
text: qsTr("Bank " + model.index)
checked: true
implicitWidth: bank_view.width
}
BankViewDescription {
id: description
isOpened: checker.checked
width: bank_view.width
}
}
Component.onCompleted: checker.checked = false
}
BankViewDescription.qml :
RowLayout {
// ...
ListView {
model: DelegateModel {
model: model // <-- problem here ???
delegate: Row {
TextField {
//... use my role here - coefficient (uint32)
}
}
// ...
}
// ...
}
}
Так что не так? нет ошибок в журнале, и верхний уровень дерева работает нормально (я думаю), представление показывает 4 банка, которые были инициализированы в main. cpp.