问题
Here's one of my ViewModels:
class MainVM : public QObject
{
Q_OBJECT
PROPERTY(QVector<View*>, views)
// Created with new operator from database
PROPERTY(QVector<Plot*>, plots)
PROPERTY(QVector<Space*>, spaces)
PROPERTY(QVector<Tenant*>, tenants)
PROPERTY(QVector<ControlHead*>, controlHeads)
PROPERTY(QVector<Head*>, heads)
PROPERTY(QVector<Lease*>, leases)
PROPERTY(QVector<Receivable*>, receivables)
PROPERTY(QVector<Space*>, filteredSpaces) // adds few pointers from PROPERTY(QVector<Space*>, spaces)
PROPERTY(QVector<Head*>, filteredHeads) // adds few pointers from PROPERTY(QVector<Head*>, heads)
PROPERTY(QVector<Head*>, receivableHeads) // adds few pointers from PROPERTY(QVector<Head*>, heads)
PROPERTY(int, selectedPlot)
PROPERTY(int, selectedSpace)
PROPERTY(int, selectedTenant)
PROPERTY(int, selectedHead)
PROPERTY(int, selectedLease)
public:
explicit MainVM(QObject *parent = nullptr);
QSqlDatabase db;
int maxPlotId, maxSpaceId, maxTenantId, maxHeadId, maxLeaseId;
private:
void createDatabase();
void fillVectors();
void setMaxIds();
template<class T> int getMaxId(QVector<T> &vec);
void setSelected();
void hookupSignalSlot();
private slots:
void onSelectedPlotChanged();
};
First seven PROPERTY
, except views
, are created with new
operator. For example spaces
is filled in this way:
while (query.next()) {
auto space = new Space();
space->setid(query.value(0).toInt());
space->setplotId(query.value(1).toInt());
space->setname(query.value(2).toString());
space->setdescription(query.value(3).toString());
space->setisVacant(query.value(4).toBool());
m_spaces.push_back(space);
}
the PROPERTY(int, selectedPlot)
can be set both ways, in my qml
, for the combobox associated with PROPERTY(QVector<Plot*>, plots)
, I've these:
Binding{
target: mainContext
property: "selectedPlot"
value: c3.currentIndex
}
Binding{
target: c3
property: "currentIndex"
value: mainContext.selectedPlot
}
in the slot onSelectedPlotChanged
I've these:
void MainVM::onSelectedPlotChanged()
{
m_filteredSpaces.clear();
auto plotId = m_plots[m_selectedPlot]->id();
for(int i = 0; i < m_spaces.size(); i++){
if(m_spaces[i]->plotId() == plotId)
m_filteredSpaces.push_back(m_spaces[i]);
}
emit filteredSpacesChanged();
if(m_filteredHeads.size() > 0)
setselectedSpace(m_filteredSpaces.first()->id());
}
it just clears the QVector
associated with PROPERTY(QVector<Space*>, filteredSpaces)
and adds pointers from PROPERTY(QVector<Space*>, spaces)
. All of my data structures for ViewModels are defined in this way:
class Space : public QObject{
Q_OBJECT
PROPERTY(int, id)
PROPERTY(int, plotId)
PROPERTY(QString, name)
PROPERTY(QString, description)
PROPERTY(bool, isVacant)
};
and this is the macro I'm using for Q_PROPERTY
:
#define PROPERTY(QType, name) \
Q_PROPERTY(QType name READ name WRITE set##name NOTIFY name##Changed) \
public: \
QType name(){return m_##name;}\
void set##name(QType value){if(m_##name != value){m_##name = value; emit name##Changed();}} \
Q_SIGNAL void name##Changed(); \
private: \
QType m_##name;
Do I have to do anything more for properties that borrows pointers from its siblings OR I'm on the right track?
EDIT
I actually don't need two separate Binding
objects for two way binding between c++ and qml, this works:
currentIndex: mainContext.selectedPlot
onCurrentIndexChanged: mainContext.selectedPlot = currentIndex
来源:https://stackoverflow.com/questions/62787149/do-i-have-to-delete-these-qobject-when-i-reset-qvectorqobject