Need help from QT Experts ( Model / View for QDateTimeEdit widget)
-
You can use
QDataWidgetMapper
with custom delegate.void MyDelegate::setEditorData(QWidget* parent, const QModelIndex& index) const { if (auto dte = qobject_cast<QDateTimeEdit*>(editor); dte) { auto* model = index.model(); const auto& year = model->index(0, 0, index.parent()).data().toString(); const auto& month = model->index(1, 0, index.parent()).data().toString(); // ... QDateTime dt = QDateTime::fromString(/*combine above to QDateTime*/); dte->setDateTime(dt); } }
Then map your
QDateTimeEdit
withQDataWidgetMapper
, set delegate. and voila -
Something like this minimal example is what you want or did I miss something?
#include <QApplication> #include <QTreeWidget> #include <QVBoxLayout> #include <QDateTimeEdit> #include <QStandardItemModel> class ExampleWid : public QWidget{ //Q_OBJECT Q_DISABLE_COPY(ExampleWid) public: explicit ExampleWid(QWidget *parent = Q_NULLPTR) :QWidget(parent) ,view(new QTreeView(this)) ,editor(new QDateTimeEdit(this)) { QAbstractItemModel* model = new QStandardItemModel(this); model->insertColumn(0); model->insertRows(0,2); QModelIndex parIdx= model->index(0,0); model->setData(parIdx,QStringLiteral("Parent A")); model->insertColumn(0,parIdx); model->insertRows(0,7,parIdx); model->setData(model->index(0,0,parIdx),2019); model->setData(model->index(1,0,parIdx),12); model->setData(model->index(2,0,parIdx),25); model->setData(model->index(3,0,parIdx),13); model->setData(model->index(4,0,parIdx),58); model->setData(model->index(5,0,parIdx),15); model->setData(model->index(6,0,parIdx),QStringLiteral("Wednesday")); parIdx= model->index(1,0); model->setData(parIdx,QStringLiteral("Parent B")); model->insertColumn(0,parIdx); model->insertRows(0,7,parIdx); model->setData(model->index(0,0,parIdx),2019); model->setData(model->index(1,0,parIdx),5); model->setData(model->index(2,0,parIdx),30); model->setData(model->index(3,0,parIdx),20); model->setData(model->index(4,0,parIdx),30); model->setData(model->index(5,0,parIdx),55); model->setData(model->index(6,0,parIdx),QStringLiteral("Thursday")); view->setModel(model); QVBoxLayout* minLay = new QVBoxLayout(this); minLay->addWidget(editor); minLay->addWidget(view); QObject::connect(view->selectionModel(),&QItemSelectionModel::currentChanged,this,[this](QModelIndex idx)->void{ if(!idx.isValid()) return; while(idx.parent().isValid()) idx =idx.parent(); lastIdx = QPersistentModelIndex(); editor->setDateTime(QDateTime( QDate( idx.model()->index(0,0,idx).data().toInt() ,idx.model()->index(1,0,idx).data().toInt() ,idx.model()->index(2,0,idx).data().toInt() ) , QTime( idx.model()->index(3,0,idx).data().toInt() ,idx.model()->index(4,0,idx).data().toInt() ,idx.model()->index(5,0,idx).data().toInt() ) )); lastIdx = idx; }); QObject::connect(editor,&QDateTimeEdit::dateTimeChanged,this,[this](const QDateTime &datetime)->void { if(!lastIdx.isValid()) return; QAbstractItemModel * model = view->model(); model->setData(model->index(0,0,lastIdx),datetime.date().year()); model->setData(model->index(1,0,lastIdx),datetime.date().month()); model->setData(model->index(2,0,lastIdx),datetime.date().day()); model->setData(model->index(3,0,lastIdx),datetime.time().hour()); model->setData(model->index(4,0,lastIdx),datetime.time().minute()); model->setData(model->index(5,0,lastIdx),datetime.time().second()); model->setData(model->index(6,0,lastIdx),view->locale().toString(datetime.date(),QStringLiteral("dddd"))); }); } private: QTreeView* view; QDateTimeEdit *editor; QPersistentModelIndex lastIdx; }; int main(int argc, char **argv) { QApplication app(argc,argv); ExampleWid wid; wid.show(); return app.exec(); }
-
@VRonin said in Need help from QT Experts ( Model / View for QDateTimeEdit widget):
view
HI VRonin,
Thank you for your reply. This would work but my model is not a local one , it is set from a different class using a set-model function(example). I need it because the model might change during run time. in this case i need dynamic signal slot right ?. I have a requirement of sessions in my program if a session is changed then the model changes which i have to set it externally.
Thanks and regards
-
Nothing difficult, mine was just an example, just remove everything in the constructor before
QVBoxLayout* minLay = new QVBoxLayout(this);
and add a publicvoid setModel(QAbstractItemModel* model){view->setModel(model);}
that you can use to set a new model from outside this class. Everything else is all the same -
Yes i tried that but when the model data is changed then the signal is not fired , it never comes to this function . why is that ?
QObject::connect(lView->selectionModel(), &QItemSelectionModel::currentChanged, this, [this](QModelIndex idx) -> void { qDebug() << "modelchanged " << idx; }
-
I need it because the model might change during run time
Do you mean the whole model is changed, or just one item? If it's the former:
https://doc.qt.io/qt-5/qitemselectionmodel.html#currentChangedNote that this signal will not be emitted when the item model is reset.
and you might mean:
https://doc.qt.io/qt-5/qitemselectionmodel.html#modelChangedThis signal is emitted when the model is successfully set with setModel().
or am I grasping the wrong end of the stick for what you are saying?
-
@JonB Thank you .
sorry i want to correct few things . Your code is working fine with view and set model i have just verified that. The reason it didnt work was i was not displaying my view.
I must not show view to user . i just have to map the model to widget(QDateTimeEdit) and show that widget to user. I thought with view it might work if i dont show this to user. just set everything but not showing. This dont work right? please correct me.I meant both cases. in one case , one child value will be changed in another case a new model is set.I can connect these signals as you mentioned but they work with TreeView when visible right?
-
@chakry said in Need help from QT Experts ( Model / View for QDateTimeEdit widget):
The reason it didnt work was i was not displaying my view.
I must not show view to user . i just have to map the model to widgetSo how do you decide what parent item of the model should be edited in the widget?
-
@VRonin parent has a name , which is fixed. I will find it based on the name. The respective Model index is used unless a new model is updated.
just a bit more explanation to be clear. I have a tree model and all these elements/children in tree model should be shown in view as a widget easily editable( ex: text box, checkbox, combobox, spinbox ..etc) . These standard items are working using widget mapper. I search for a parent and map its model index to one of the these standard widgets. In this model i also have 6 children's having date ,time info. I wanted to map these 6 children's to a single widget datetimeedit. This was my main issue . This is not possible with restriction on datawidgetmapper ( only one property can be mapped ).
thanks and regards.
-
@chakry said in Need help from QT Experts ( Model / View for QDateTimeEdit widget):
I wanted to map these 6 children's to a single widget datetimeedit. This was my main issue . This is not possible with restriction on datawidgetmapper ( only one property can be mapped ).
This is what the code in my 2
connect
do:
This puts an index inside theQDatetimeEdit
if(!idx.isValid()) return; while(idx.parent().isValid()) idx =idx.parent(); lastIdx = QPersistentModelIndex(); editor->setDateTime(QDateTime( QDate( idx.model()->index(0,0,idx).data().toInt() ,idx.model()->index(1,0,idx).data().toInt() ,idx.model()->index(2,0,idx).data().toInt() ) , QTime( idx.model()->index(3,0,idx).data().toInt() ,idx.model()->index(4,0,idx).data().toInt() ,idx.model()->index(5,0,idx).data().toInt() ) )); lastIdx = idx;
This puts the data from the
QDatetimeEdit
back into the modelif(!lastIdx.isValid()) return; model->setData(model->index(0,0,lastIdx),datetime.date().year()); model->setData(model->index(1,0,lastIdx),datetime.date().month()); model->setData(model->index(2,0,lastIdx),datetime.date().day()); model->setData(model->index(3,0,lastIdx),datetime.time().hour()); model->setData(model->index(4,0,lastIdx),datetime.time().minute()); model->setData(model->index(5,0,lastIdx),datetime.time().second()); model->setData(model->index(6,0,lastIdx),view->locale().toString(datetime.date(),QStringLiteral("dddd")));
-
@VRonin said in Need help from QT Experts ( Model / View for QDateTimeEdit widget):
@chakry said in Need help from QT Experts ( Model / View for QDateTimeEdit widget):
I wanted to map these 6 children's to a single widget datetimeedit. This was my main issue . This is not possible with restriction on datawidgetmapper ( only one property can be mapped ).
Thank you VRonin for helping
This is what the code in my 2connect
do:
This puts an index inside theQDatetimeEdit
```
( Its true but where should i add this code , view and selectionmodel as you mentioned before doesnot work as there is no view in my case , any suggestion where to keep this )> ```cpp > if(!idx.isValid()) > return; > while(idx.parent().isValid()) > idx =idx.parent(); > lastIdx = QPersistentModelIndex(); > editor->setDateTime(QDateTime( > QDate( > idx.model()->index(0,0,idx).data().toInt() > ,idx.model()->index(1,0,idx).data().toInt() > ,idx.model()->index(2,0,idx).data().toInt() > ) > , QTime( > idx.model()->index(3,0,idx).data().toInt() > ,idx.model()->index(4,0,idx).data().toInt() > ,idx.model()->index(5,0,idx).data().toInt() > ) > )); > lastIdx = idx; > ``` > > This puts the data from the `QDatetimeEdit` back into the model ``` **( This works as in this case i use dateTimechanged from QDateTimeEditsignal and set the passed model data)**
if(!lastIdx.isValid()) return; model->setData(model->index(0,0,lastIdx),datetime.date().year()); model->setData(model->index(1,0,lastIdx),datetime.date().month()); model->setData(model->index(2,0,lastIdx),datetime.date().day()); model->setData(model->index(3,0,lastIdx),datetime.time().hour()); model->setData(model->index(4,0,lastIdx),datetime.time().minute()); model->setData(model->index(5,0,lastIdx),datetime.time().second()); model->setData(model->index(6,0,lastIdx),view->locale().toString(datetime.date(),QStringLiteral("dddd")));