PDA

View Full Version : Combobox + bool + DataWidgetMapper not good



RolandHughes
13th November 2008, 22:12
Hello,

64-bit Ubuntu 8.10 (version of Qt and C++ that came with distro)
8.3.4 PostgreSQL

Table layout as follows:

CREATE TABLE expenses (
-- tran_id serial not null primary key,
tran_dt date,
category char(25) CONSTRAINT valid_cat REFERENCES categories (category) MATCH FULL ON DELETE RESTRICT,
tax_ded boolean,
payee char(50) CONSTRAINT valid_payee REFERENCES payees (payee) MATCH FULL ON DELETE RESTRICT,
amount numeric(10,2) CONSTRAINT amt_constraint NOT NULL);



here are some snippets for the mapping

tax_dedComboBox = new QComboBox;
tax_dedComboBox->addItem( "true");
tax_dedComboBox->addItem( "false");

tax_dedLabel = new QLabel(tr("Ta&x_Ded:"));
tax_dedLabel->setBuddy(tax_dedComboBox);



mapper = new QDataWidgetMapper(this);
mapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);
mapper->setModel(tableModel);
mapper->setItemDelegate(new QSqlRelationalDelegate(this));
mapper->addMapping(tran_dtDateEdit, tableModel->fieldIndex("tran_dt"));
mapper->addMapping(categoryComboBox, tableModel->fieldIndex("category"));
mapper->addMapping(tax_dedComboBox, tableModel->fieldIndex("tax_ded"));
mapper->addMapping(payeeComboBox, tableModel->fieldIndex("payee"));
mapper->addMapping(amountLineEdit, tableModel->fieldIndex("amount"));



The combobox has to have the values "true" and "false" since that is the way the mapper seems to return them. It does not translate values correctly when performing inserts, but will correctly set the combobox value if the boolean exists in the database.

wysota
13th November 2008, 23:31
Is there a question here somewhere?

caduel
14th November 2008, 07:03
Just about all the QWidgets you map to are not really able to support NULL, i.e. distinguish between 0 and NULL, "" and NULL, false and NULL...
So be careful when mapping column that might be NULL to a widget.

wysota
14th November 2008, 08:04
It's enough to provide an alternative item delegate that handles such cases. Widgets themselves have nothing to do with it, at least not directly. It is the delegate that sets the data on them and reads it back to the model.

RolandHughes
14th November 2008, 18:23
Just about all the QWidgets you map to are not really able to support NULL, i.e. distinguish between 0 and NULL, "" and NULL, false and NULL...
So be careful when mapping column that might be NULL to a widget.

The database always returns 't' or 'f'. Code in Qt is changing it to 'true' and 'false', then trying to send those words back to the database.

All of this happened because I made the mistake of trying out the QSqlRelationalTableModel convenience class. I'm going to wait for Qt 6 to come out before trying that class again. It appears to only have been tested with SQLite at this point. Two days wasted trying to make a "convenience" class work when the entire little program can be coded the hard way in a day.

I flagged the item here because the developers haven't been testing with boolean columns. Hopefully, pointing this out and providing a simple table layout will give them additional test cases to work with in the future.

tax_2138=# \d expenses
Table "public.expenses"
Column | Type | Modifiers
----------+---------------+------------------------------------------------------------
tran_id | integer | not null default nextval('expenses_tran_id_seq'::regclass)
tran_dt | date |
category | character(25) |
tax_ded | boolean |
payee | character(50) |
amount | numeric(10,2) | not null
Indexes:
"expenses_pkey" PRIMARY KEY, btree (tran_id)
Foreign-key constraints:
"valid_cat" FOREIGN KEY (category) REFERENCES categories(category) MATCH FULL ON DELETE RESTRICT
"valid_payee" FOREIGN KEY (payee) REFERENCES payees(payee) MATCH FULL ON DELETE RESTRICT

wysota
14th November 2008, 22:37
Of course you could have simply provided a proper delegate (like at least the relational table delegate or something smarter if you need it)... :-)

caduel
15th November 2008, 08:05
(But how does a proper delegate help with the issue of "how to represent (or set) NULL and how to distinguish it from an empty string" with a QLineEdit? Of course, you could provide an extra checkbox or something like that... is that what you meant?)

Happily waiting for good ideas (really!)

wysota
15th November 2008, 08:21
This depends on the exact usecase. For instance if you had NULL before and the field is empty, it should probably stay null. If it wasn't empty and now it is, it could become one but it doesn't have to. An automagic delegate won't solve it for you - you have to make the decision and implement it in appropriate methods.