QSqlTableModel
-
Thank you! I've already checked that.(
Problem solved! I've got updated table with another table name. So I just update information in .cpp and all is working now! Thank you all for helping me out!
BTW, are there any possibility to display double number without exponential format in QSqlTableModel? I can use something like this
QString::number(result, 'f', 2)
, but how can I select all date from colomn "Population"? Should I useSqlQuery / .next()
instead of thissqlTableModel->select(); ui->tableView->setModel(sqlTableModel);
Thank you!
-
@Xilit
Yes, use number format to select desired format!You already have all rows read in.
model->data(model->index(row, column))
gives you the column data in a row, e.g.sqlTableModel->data(sqlTableModel->index(0, 1))
,sqlTableModel->data(sqlTableModel->index(1, 1))
for the two items in your picture. -
Hi! Glad to see you!
I've tried this
QModelIndex index = sqlTableModel->index(0,3); sqlTableModel->setData(index, QString::number(sqlTableModel->data(index).toDouble(), 'f', 3)); ui->tableView->setModel(sqlTableModel);
But it nothing change. It still display in exponential format.
-
@Xilit
Don't do this viasetData()
. You don't want to set/change any data, only the way it is displayed.(BTW, my guess here is that if you looked at the return result of your
setData()
[which you ought always do] you might see yours is failing, trying to store a string in a table column known to be a number.)Sub-class from Qt-supplied
QSqlTableModel
. Override thedata()
method, and have it return the desired conversion to formatted string in whatever columns are numeric to be displayed like that. Do so for the (default)DisplayRole
case only.That's how I believe in doing it. I think there are some who would do the conversion/display in a
QStyledItemDelegate
instead.In general, you should only need to set the view's model once at the start, not each time a value changes. However if you change as above you won't be changing any values anyway.
-
Thank you! I'll try to do that.
I think there are some who would do the conversion/display in a QStyledItemDelegate instead.
You know, when I write previous comment I thought about using
QStyledItemDelegate
. If you say so maybe I realy should use it.In general, you should only need to set the view's model once at the start, not each time a value changes. However if you change as above you won't be changing any values anyway.
So if I want to change some values I need to derived from abstractModel and override methods, right? Ok, if I derived from
QAbstractTableModel
and reimplementrowCount()
,columnCount()
,data()
,setData()
andflags()
in my countriestablemodel.cpp and pass this model to mainwindow.cpp to show. And to mainwindow.cpp I also giveQStyledItemDelegate
from countriesstyleditemdelegate.cpp.Something like this:
countriestablemodel.cpp -> mainwindow.cpp (provide model with data from DB)
countriesstyleditemdelegate.cpp -> mainwindow.cpp (provide delegate to model)So, model with data and delegate to this model must "meet" each other in mainwindow.cpp. Is this scheme correct? If you have any suggesions it will be appreciated.
Thank you!
-
@Xilit
Yes, you can do something like this.As I said, personally I do not do this in a
QStyledItemDelegate
at all. I suggested you do it indata()
override forQt::DisplayRole
. Personally I think this is simpler to write, but perhaps that's opinion.Rationale:
QStyledItemDelegate
is only usable in aQTableView
or similar. However, to me the choice to display a numeric in a particular format like you have is not restricted to/has nothing to do with whether you happen to be displaying it as an item in table. If, say, you want to display it in its own widget, or export it to a text file, you would (presumably) still want to display/output it in your chosen format. So I see it best as an attribute of the data, putting the logic indata(Qt::DisplayRole)
makes that available/shareable everywhere. -
BTW is there are recommendation / tutorial how to reimplement
QVariant QAbstractItemModel::data(const QModelIndex &index, int role = Qt::DisplayRole) const
? To know how to reimplement method I need to know how this method works but I don't. Were I can find realization of it? There are no information about it in docs. -
@Xilit
No mention about it in the docs?? Oh, I think you mean you have found the reference page (https://doc.qt.io/qt-5/qabstractitemmodel.html#data), but not examples? One is https://doc.qt.io/qt-5/model-view-programming.html#a-read-only-example-model, another is https://doc.qt.io/qt-5/model-view-programming.html#read-only-access. Read around those two areas. There are perhaps better links, I don't know. Understanding howdata()
&setData()
methods work and can be overridden is important for Qt models. -
Did you follow the Model View Programming Guide ?
There are several examples linked with some of them implementing custom models and views. -
@JonB said in QSqlTableModel:
I suggested you do it in data() override for Qt::DisplayRole. Personally I think this is simpler to write, but perhaps that's opinion.
Strongly disagree. The model is data, it shouldn't care how the data is represented. Also, the model is locale unaware
Just subclass
QStyledItemDelegate
and overridedisplayText
:class NoScNotationDelegate : public QStyledItemDelegate{ Q_OBJECT Q_DISABLE_COPY(NoScNotationDelegate) public: using QStyledItemDelegate::QStyledItemDelegate; QString displayText(const QVariant &value, const QLocale &locale) const override{ switch(value.type()){ case QMetaType::Double: return locale.toString(value.toDouble(),'f'); case QMetaType::Float: return locale.toString(value.toFloat(),'f'); default: return QStyledItemDelegate::displayText(value,locale); } } };
Then you can just use it with
tableView->setItemDelegate(new NoScNotationDelegate(tableView));
(you can also usesetItemDelegateForColumn
to apply it ta a single column) -
@JonB said in QSqlTableModel:
@Xilit
Prefacing my remarks to @VRonin below: Then in view of his post above, I think you should followQStyledItemDelegate
route, as he is much more of a Qt expert than I am.@VRonin
I'll keep it brief here, otherwise perhaps we should take this issue to its own dedicated thread. I respect your expertise, but it does not chime right for me. Just a couple of reasons:-
Somewhere in the existing Qt code for
data(DisplayRole)
there must be the equivalent ofQString::arg(char format = 'g')
to give the results it does. You are saying that is OK, but changing toQString::arg(char format = 'f')
is not. Makes no sense to me. If the model must not care how the data is represented, it should not have aDisplayRole
. -
Your code is all in a
QStyledItemDelegate
for aQTableView
or similar. I do not want special code for displaying a number in a view, I want it just as much for displaying it in, say, a label, or hundreds of other places. So the code has to be refactored to be available from all other places you might want your string representation of a numeric data item, and one will never be able to use plain, defaultdata()
method in practice (given something like the OP's requirement for numeric format).
-
-
@JonB
@SGaist
Thank you guys for links! I'm going to dive in to deeply understand how model works.@VRonin
Thank you that you find time to help me out with my programm and wrote example code! Written code is really very valueble for me because sometimes it's very hard to understand what senior experts talking about without code example.)Thank you all guys that I can always count on your help!
-
@JonB said in QSqlTableModel:
Somewhere in the existing Qt code for data(DisplayRole) there must be the equivalent of QString::arg(char format = 'g')
No, data is converted to string to represent it inside
QStyledItemDelegate::displayText
, nowhere else (and it usesQLocale::toString
instead of the C-locale-onlyQString::number
). The model holds the data in the native format and never cares about how it is represented to the userYour code is all in a QStyledItemDelegate for a QTableView or similar
Yes, my code is for the model-view-delegate architecture
I do not want special code for displaying a number in a view, I want it just as much for displaying it in, say, a label, or hundreds of other places
Then it's the final user that has to take care of knowing how to convert a double to string. Exactly because of the reason you mentioned. the model is agnostic to what you use it in/for
-
@VRonin said in QSqlTableModel:
No, data is converted to string to represent it inside QStyledItemDelegate::displayText, nowhere else. The model holds the data in the native format and never cares about how it is represented to the user
If you are saying that
QStyledItemDelegate::displayText
does its own conversion offdata(EditRole)
then I don't get it, because I changedata(DisplayRole)
for numbers and they come out reflecting that in table views? Unless you are saying I am going mad.If the model never cares about representation to the user, what is the purpose of
DisplayRole
? (Or, for that matter,FontRole
etc. Indeed, why does the model'sdata()
even offer or get called for such roles?) -
For all native Qt Models
EditRole
andDisplayRole
are one and the same. They never get separated. They are distinct only if you implement a custom model.QStyledItemDelegate::displayText
does its own conversion offdata(DisplayRole)
it never cares aboutEditRole
(unless you have some custom implementation that passes editrole to it)what is the purpose of DisplayRole?
The most iconic example of the purpose is thinking abount excel/libre office calc: edit role is the formula, display role is the result of that formula. You can never change the result directly when you modify a cell. You always change the formula (edit role) then the program calculates the result and shows it in dispaly role. The result of
=2+2
(string in editrole) is stored as int/double in the displayrole. The delegate then takes care of taking that number and converting it to something that can be printed on the screen -
@VRonin said in QSqlTableModel:
QStyledItemDelegate::displayText
does its own conversion offdata(DisplayRole)
it never cares aboutEditRole
That is very interesting. So when (for right or for wrong) I made my
data(DisplayRole)
of a floating produce the format I wanted (f
format, 2 decimal places) as a string,displayText
saw a string instead of a number and passed it through without its own formatting, that's why it came out as it did.I know about the spreadsheet case. It is "unusual", compared to 99% of cases. I thought
DisplayRole
was supposed to return the desired string for the default way you wanted the data output, hence why I did it that way for the floating point numbers. I think it was the very first area I did with Qt/PyQt, and I didn't know what you are saying now.Although I know this conversation has been long, I hope @Xilit, the OP, won't mind as it's actually useful for him to see this stuff.
So my last question to @VRonin is: why are there all the other "presentational" roles (
FontRole
,TextAlignmentRole
,ForegroundRole
etc.)? If you are so keen that "The model [...] never cares about how it is represented to the user", why do you let the model provide/handle those? Even worse,data()
returns types likeQFont
andQBrush
for these (not even just a "symbolic" indicator), which is all to do with the presentation to the user. -
@JonB said in QSqlTableModel:
I hope @Xilit, the OP, won't mind as it's actually useful for him to see this stuff.
Nope! Of course I don't mind! Rather I vote for this disscusion! It is really useful information. I'll read all this stuff very carefully after I read all information about model by links above. Then I'll read this comments because I never understand
DisplayRole
properly.((