QSqlRelationalTableModel with multiple Joins?
-
@devhobby
http://doc.qt.io/qt-5/qitemdelegate.html#details must be to do with it.I could easily be wrong(!), but I thought the idea of the model/view would be that if you edit it would save the value back to the model, not "just give you some string". You can doubtless play with the delegate to do something else...
P.S.
Look at http://www.qtcentre.org/threads/38338-Can-t-edit-my-QTableView-cells:Check if the item is actually editable: (
MyTable->model()->flags(idx) & Qt::ItemIsEditable
). If not, make it so.Setting a Qt.ItemIsEnabled flag makes the QTableView items editable. To enter the item's editing mode the user can simply double-click it.
EDIT: You have to loop over every item in your table view to make it individually editable....
@JonB said in QSqlRelationalTableModel with multiple Joins?:
@devhobby
http://doc.qt.io/qt-5/qitemdelegate.html#details must be to do with it.I could easily be wrong(!), but I thought the idea of the model/view would be that if you edit it would save the value back to the model, not "just give you some string". You can doubtless play with the delegate to do something else...
P.S.
Look at http://www.qtcentre.org/threads/38338-Can-t-edit-my-QTableView-cells:Check if the item is actually editable: (
MyTable->model()->flags(idx) & Qt::ItemIsEditable
). If not, make it so.Setting a Qt.ItemIsEnabled flag makes the QTableView items editable. To enter the item's editing mode the user can simply double-click it.
I'd like to change Table View's flag to Qt::ItemIsEditable... but can't find a way to do it
There's no setFlags() method here...
-
@JonB said in QSqlRelationalTableModel with multiple Joins?:
@devhobby
http://doc.qt.io/qt-5/qitemdelegate.html#details must be to do with it.I could easily be wrong(!), but I thought the idea of the model/view would be that if you edit it would save the value back to the model, not "just give you some string". You can doubtless play with the delegate to do something else...
P.S.
Look at http://www.qtcentre.org/threads/38338-Can-t-edit-my-QTableView-cells:Check if the item is actually editable: (
MyTable->model()->flags(idx) & Qt::ItemIsEditable
). If not, make it so.Setting a Qt.ItemIsEnabled flag makes the QTableView items editable. To enter the item's editing mode the user can simply double-click it.
I'd like to change Table View's flag to Qt::ItemIsEditable... but can't find a way to do it
There's no setFlags() method here...
@devhobby
You have to loop over every item in your table view to make it individually editable (if you're not creating the items yourself, or unless someone suggests a way to cause that to happen as it binds to your model, e.g. https://stackoverflow.com/a/28226056/489865).... -
@devhobby
You have to loop over every item in your table view to make it individually editable (if you're not creating the items yourself, or unless someone suggests a way to cause that to happen as it binds to your model, e.g. https://stackoverflow.com/a/28226056/489865)....@JonB said in QSqlRelationalTableModel with multiple Joins?:
@devhobby
You have to loop over every item in your table view to make it individually editable (if you're not creating the items yourself, or unless someone suggests a way to cause that to happen as it binds to your model)....Suppose I'm inside a for loop where index is a QModelIndex
ui->tableView->model()->data(index). ???
There's no setFlags here still
-
@JonB said in QSqlRelationalTableModel with multiple Joins?:
@devhobby
You have to loop over every item in your table view to make it individually editable (if you're not creating the items yourself, or unless someone suggests a way to cause that to happen as it binds to your model)....Suppose I'm inside a for loop where index is a QModelIndex
ui->tableView->model()->data(index). ???
There's no setFlags here still
I think we use
QTableWidget
, not justQTableView
.http://www.qtcentre.org/threads/46245-QTableWidgetItem-setflags-strange-behavior?p=209282#post209282 shows you accessing
QTableWidgetItem
. http://doc.qt.io/qt-5/qtablewidget.html#itemhttp://doc.qt.io/qt-5/qtablewidget.html#details:
The QTableWidget class provides an item-based table view with a default model.
Table widgets provide standard table display facilities for applications. The items in a QTableWidget are provided by QTableWidgetItem.
If you want a table that uses your own data model you should use QTableView rather than this class.But for
QTableView
I previously gave you http://www.qtcentre.org/threads/38338-Can-t-edit-my-QTableView-cells?p=176235#post176235:Qt::ItemFlags MyTableModel::flags (const QModelIndex &index) const { return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; }
http://doc.qt.io/qt-5/qabstractitemmodel.html#flags, http://doc.qt.io/qt-5/qabstracttablemodel.html#flags works off the model, so presumably your
ui->tableView->model()->flags(index)
.Ah ha!! Here's what we wanted to know:
http://doc.qt.io/qt-5/qsqlquerymodel.html#detailsThe model is read-only by default. To make it read-write, you must subclass it and reimplement setData() and flags(). Another option is to use QSqlTableModel, which provides a read-write model based on a single database table.
-
I think we use
QTableWidget
, not justQTableView
.http://www.qtcentre.org/threads/46245-QTableWidgetItem-setflags-strange-behavior?p=209282#post209282 shows you accessing
QTableWidgetItem
. http://doc.qt.io/qt-5/qtablewidget.html#itemhttp://doc.qt.io/qt-5/qtablewidget.html#details:
The QTableWidget class provides an item-based table view with a default model.
Table widgets provide standard table display facilities for applications. The items in a QTableWidget are provided by QTableWidgetItem.
If you want a table that uses your own data model you should use QTableView rather than this class.But for
QTableView
I previously gave you http://www.qtcentre.org/threads/38338-Can-t-edit-my-QTableView-cells?p=176235#post176235:Qt::ItemFlags MyTableModel::flags (const QModelIndex &index) const { return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; }
http://doc.qt.io/qt-5/qabstractitemmodel.html#flags, http://doc.qt.io/qt-5/qabstracttablemodel.html#flags works off the model, so presumably your
ui->tableView->model()->flags(index)
.Ah ha!! Here's what we wanted to know:
http://doc.qt.io/qt-5/qsqlquerymodel.html#detailsThe model is read-only by default. To make it read-write, you must subclass it and reimplement setData() and flags(). Another option is to use QSqlTableModel, which provides a read-write model based on a single database table.
@JonB said in QSqlRelationalTableModel with multiple Joins?:
I think we use
QTableWidget
, not justQTableView
.http://www.qtcentre.org/threads/46245-QTableWidgetItem-setflags-strange-behavior?p=209282#post209282 shows you accessing
QTableWidgetItem
. http://doc.qt.io/qt-5/qtablewidget.html#itemhttp://doc.qt.io/qt-5/qtablewidget.html#details:
The QTableWidget class provides an item-based table view with a default model.
Table widgets provide standard table display facilities for applications. The items in a QTableWidget are provided by QTableWidgetItem.
If you want a table that uses your own data model you should use QTableView rather than this class.But for
QTableView
I previously gave you http://www.qtcentre.org/threads/38338-Can-t-edit-my-QTableView-cells?p=176235#post176235:Qt::ItemFlags MyTableModel::flags (const QModelIndex &index) const { return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; }
At this point I don't even know which of the 2 (table view/table widget) is the most appropriate for my situation.
The last post you linked says to reimplement the method flags() but I don't understand: after inheriting from AbstractItemModel (and reimplementing the method), what am I supposed to do?
-
@JonB said in QSqlRelationalTableModel with multiple Joins?:
I think we use
QTableWidget
, not justQTableView
.http://www.qtcentre.org/threads/46245-QTableWidgetItem-setflags-strange-behavior?p=209282#post209282 shows you accessing
QTableWidgetItem
. http://doc.qt.io/qt-5/qtablewidget.html#itemhttp://doc.qt.io/qt-5/qtablewidget.html#details:
The QTableWidget class provides an item-based table view with a default model.
Table widgets provide standard table display facilities for applications. The items in a QTableWidget are provided by QTableWidgetItem.
If you want a table that uses your own data model you should use QTableView rather than this class.But for
QTableView
I previously gave you http://www.qtcentre.org/threads/38338-Can-t-edit-my-QTableView-cells?p=176235#post176235:Qt::ItemFlags MyTableModel::flags (const QModelIndex &index) const { return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; }
At this point I don't even know which of the 2 (table view/table widget) is the most appropriate for my situation.
The last post you linked says to reimplement the method flags() but I don't understand: after inheriting from AbstractItemModel (and reimplementing the method), what am I supposed to do?
@devhobby
Look at the last bit I just added to my post above.To make it [QSqlQueryModel] read-write, you must subclass it and reimplement
setData()
andflags()
.(And BTW when you've done that there won't be any "iterating over items and setting the editable flag", your items will be editable through your reimplementation of
QSqlQueryModel::flags()
.)You understand how to "subclass", and how to "reimplement [override] virtual methods", don't you?
-
@JonB said in QSqlRelationalTableModel with multiple Joins?:
I think we use
QTableWidget
, not justQTableView
.http://www.qtcentre.org/threads/46245-QTableWidgetItem-setflags-strange-behavior?p=209282#post209282 shows you accessing
QTableWidgetItem
. http://doc.qt.io/qt-5/qtablewidget.html#itemhttp://doc.qt.io/qt-5/qtablewidget.html#details:
The QTableWidget class provides an item-based table view with a default model.
Table widgets provide standard table display facilities for applications. The items in a QTableWidget are provided by QTableWidgetItem.
If you want a table that uses your own data model you should use QTableView rather than this class.But for
QTableView
I previously gave you http://www.qtcentre.org/threads/38338-Can-t-edit-my-QTableView-cells?p=176235#post176235:Qt::ItemFlags MyTableModel::flags (const QModelIndex &index) const { return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; }
At this point I don't even know which of the 2 (table view/table widget) is the most appropriate for my situation.
The last post you linked says to reimplement the method flags() but I don't understand: after inheriting from AbstractItemModel (and reimplementing the method), what am I supposed to do?
@devhobby
I'm going back to your very original post and thinking about what you're actually trying to achieve anyway. The code we're talking about is all well & good, if you want to proceed, but I'm wondering about your expectations of the interface.In your pic of Employee table only, you have 1 row per employee. When you say:
I want to join the Employee table with EmployeePosition and EmployeeResource so that I can also see, for each employee, their positions and resources (if they have any!)
what are you expecting the table interface to be for the multiple positions & resources you say employees have?
It's all very well to say:
What I need, hence, is a full outer join
The query above gives me everything I want to know and see on the Table View[I'm trusting that your code implements FULL OUTER JOIN] but left to its own devices this will mean you have many rows per employee, for each position/resource variant. Is that what you intend??
One thing to understand: when you're using
QSqlRelationalTableModel
so that you can "look up" position/resource names, the combobox you'll get will only ever allow single selection, if you're imagining that it might provide multiple selection it won't. -
@devhobby
Look at the last bit I just added to my post above.To make it [QSqlQueryModel] read-write, you must subclass it and reimplement
setData()
andflags()
.(And BTW when you've done that there won't be any "iterating over items and setting the editable flag", your items will be editable through your reimplementation of
QSqlQueryModel::flags()
.)You understand how to "subclass", and how to "reimplement [override] virtual methods", don't you?
@JonB said in QSqlRelationalTableModel with multiple Joins?:
@devhobby
Look at the last bit I just added to my post above.To make it [QSqlQueryModel] read-write, you must subclass it and reimplement
setData()
andflags()
.(And BTW when you've done that there won't be any "iterating over items and setting the editable flag", your items will be editable through your reimplementation of
QSqlQueryModel::flags()
.)You understand how to "subclass", and how to "reimplement [override] virtual methods", don't you?
I have my CustomModel class now deriving from QSqlQueryModel
#ifndef CUSTOMMODEL_H #define CUSTOMMODEL_H #include <QSqlQueryModel> class CustomModel : public QSqlQueryModel { Q_OBJECT public: bool setData(const QModelIndex &index, const QVariant &value, int role) override; Qt::ItemFlags flags(const QModelIndex &index) const override; }; #endif
The problem is...
The linker somehow can't match the signatures... weird.
I checked this link for example [ https://code.woboq.org/qt5/qtbase/src/corelib/itemmodels/qabstractitemmodel.h.html ]
and both setData() and flags() are the same way I overloaded them...
-
@JonB said in QSqlRelationalTableModel with multiple Joins?:
@devhobby
Look at the last bit I just added to my post above.To make it [QSqlQueryModel] read-write, you must subclass it and reimplement
setData()
andflags()
.(And BTW when you've done that there won't be any "iterating over items and setting the editable flag", your items will be editable through your reimplementation of
QSqlQueryModel::flags()
.)You understand how to "subclass", and how to "reimplement [override] virtual methods", don't you?
I have my CustomModel class now deriving from QSqlQueryModel
#ifndef CUSTOMMODEL_H #define CUSTOMMODEL_H #include <QSqlQueryModel> class CustomModel : public QSqlQueryModel { Q_OBJECT public: bool setData(const QModelIndex &index, const QVariant &value, int role) override; Qt::ItemFlags flags(const QModelIndex &index) const override; }; #endif
The problem is...
The linker somehow can't match the signatures... weird.
I checked this link for example [ https://code.woboq.org/qt5/qtbase/src/corelib/itemmodels/qabstractitemmodel.h.html ]
and both setData() and flags() are the same way I overloaded them...
@devhobby
Now you're talking C++ esotericism, and I'm a Python Qt guy anyway. This one is your problem! :) Sometimes signatures don't match if you don't get yourconst
s just right? What about theQ_INVOKABLE
?https://stackoverflow.com/questions/33781346/how-to-write-setdata-in-qsqlquerymodelqabstractitemmodel is an example of what claims to work? (Oohh, it uses
Q_DECL_OVERRIDE
for youroverride
?) -
@devhobby
Now you're talking C++ esotericism, and I'm a Python Qt guy anyway. This one is your problem! :) Sometimes signatures don't match if you don't get yourconst
s just right? What about theQ_INVOKABLE
?https://stackoverflow.com/questions/33781346/how-to-write-setdata-in-qsqlquerymodelqabstractitemmodel is an example of what claims to work? (Oohh, it uses
Q_DECL_OVERRIDE
for youroverride
?)@JonB said in QSqlRelationalTableModel with multiple Joins?:
@devhobby
Oohh, it usesQ_DECL_OVERRIDE
for youroverride
?Yes, it is ALSO that.
Something strange is going on here...
I'll try tagging someone @SGaist @VRonin
--- HEADER FILE ---
#ifndef MYMODEL_H #define MYMODEL_H #include <QObject> #include <QSqlQueryModel> class MyModel : public QSqlQueryModel { Q_OBJECT public: MyModel(QObject *parent = 0); Qt::ItemFlags flags(const QModelIndex &index) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; }; #endif // MYMODEL_H
--- CPP FILE ---
#include "mymodel.h" MyModel::MyModel(QObject *parent) : QSqlQueryModel(parent) { } Qt::ItemFlags MyModel::flags(const QModelIndex &index) const { } bool MyModel::setData(const QModelIndex &index, const QVariant &value, int role) { }
-
Your CPP file contains an error, the default value should be in the declaration of the function.
If you are using Qt >= 5.7, you can simply use the
override
keyword as C++11 support is mandatory since that version. Q_DECL_OVERRIDE was used to allow compatibly with non-C++11 enabled compilers. -
Your CPP file contains an error, the default value should be in the declaration of the function.
If you are using Qt >= 5.7, you can simply use the
override
keyword as C++11 support is mandatory since that version. Q_DECL_OVERRIDE was used to allow compatibly with non-C++11 enabled compilers. -
Your CPP file contains an error, the default value should be in the declaration of the function.
If you are using Qt >= 5.7, you can simply use the
override
keyword as C++11 support is mandatory since that version. Q_DECL_OVERRIDE was used to allow compatibly with non-C++11 enabled compilers.@SGaist said in QSqlRelationalTableModel with multiple Joins?:
Your CPP file contains an error, the default value should be in the declaration of the function.
If you are using Qt >= 5.7, you can simply use the
override
keyword as C++11 support is mandatory since that version. Q_DECL_OVERRIDE was used to allow compatibly with non-C++11 enabled compilers.I hoped it was just that...
I moved the default value in the header file, same issue
[ I will update the code posted above so that I don't repost it everytime ]
-
Did you try re-running
qmake
before building ? -
Did you try re-running
qmake
before building ?Thank you, sir! That solved it :)
I'm going back to your very original post and thinking about what you're actually trying to achieve anyway. The code we're talking about is all well & good, if you want to proceed, but I'm wondering about your expectations of the interface.
Back to the original post... at the moment I can successfully double-click items and edit them.
How they are edited and how the edit is going to affect the table and the database is something I believe I can do by myself now.
I guess I've caught the mechanism behind it!
BUT
One thing that has remained unresolved is the fact that anytime I change a field (setData() is called) the edited cell must change its background color.
I still don't get this one.
P.S: @JonB I wanted to thank you too. It's amazing the way you're helping me. I just can't thank you enough :)
-
Do you mean you want to mark the cell as "edited" ?
-
@SGaist said in QSqlRelationalTableModel with multiple Joins?:
Do you mean you want to mark the cell as "edited" ?
Yes but... my way!
I want to change it's background color to, say, Cyan.
This way the user, before committing the changes, can take a look and see what is going to really change in the database.
-
One way could be to keep a vector of edited cells that you update when
setData
is called with the EditRole and that you will use whendata
is called for the BackgroundRole and you return the colour you want. -
One way could be to keep a vector of edited cells that you update when
setData
is called with the EditRole and that you will use whendata
is called for the BackgroundRole and you return the colour you want.@SGaist said in QSqlRelationalTableModel with multiple Joins?:
One way could be to keep a vector of edited cells that you update when
setData
is called with the EditRole and that you will use whendata
is called for the BackgroundRole and you return the colour you want.Thank you. The problem is I can't find the method which allows me to change te color to a cell. I guess something like setBackgroundColor(row,column)
-
Because there's none. Do you have a custom setData method ? If so you should emit the dataChanged signal properly and it should trigger an update of the view which should request all the roles including the one for background colour.