Mapper fails to submit: QDataWidgetMapper, QSqlRelationalTableModel
-
I am facing a problem with a C++ Qt4 Widget. This widget is to be used for adding rows into a SQLite database. Here are the database tables which are used in this code snippet:
@
CREATE TABLE 'statuses' ('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE , 'name' VARCHAR(50) NOT NULL UNIQUE , 'bgcolor' VARCHAR(6) NOT NULL DEFAULT ffffff, 'fgcolor' VARCHAR(6) NOT NULL DEFAULT 000000)
CREATE TABLE 'addresses' ('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE , 'name' VARCHAR(50) NOT NULL UNIQUE , 'country' VARCHAR(25), 'town' VARCHAR(50), 'postal_code' VARCHAR(10), 'street' TEXT check(typeof('street') = 'text') , 'ref' VARCHAR(5) NOT NULL , 'status_id' INTEGER NOT NULL, FOREIGN KEY(status_id) REFERENCES statuses(id))
@
The code I wrote, which follows exactly the Qt tutorial [url=http://doc.qt.nokia.com/latest/sql-sqlwidgetmapper.html]SQL WidgetMapper[/url], follows:
@
CreateAddressDialog::CreateAddressDialog(QWidget parent) :
QDialog(parent),
ui(new Ui::CreateAddressDialog)
{
ui->setupUi(this);
/ Set up "buddies" */
ui->nameLabel->setBuddy(ui->nameLineEdit);
ui->refLabel->setBuddy(ui->refLineEdit);
ui->townLabel->setBuddy(ui->townLineEdit);
ui->streetLabel->setBuddy(ui->streetLineEdit);
ui->countryLabel->setBuddy(ui->countryLineEdit);
ui->postalCodeLabel->setBuddy(ui->postalCodeLineEdit);
ui->statusLabel->setBuddy(ui->statusCB);/* Set up status model */ ui->statusCB->clear(); statusModel = new QSqlRelationalTableModel(this, backbone::instance()->db); statusModel->setEditStrategy(QSqlTableModel::OnManualSubmit); statusModel->setTable("addresses"); int statusFieldId = statusModel->fieldIndex("status_id"); /***** Warning: after next instruction fieldIndex('status_id') will return -1. */ statusModel->setRelation(statusFieldId,QSqlRelation("statuses", "id", "name")); statusModel->select(); relModel = statusModel->relationModel(statusFieldId); ui->statusCB->setModel(relModel); ui->statusCB->setModelColumn(relModel->fieldIndex("name")); mapper = new QDataWidgetMapper(this); mapper->setItemDelegate(new QSqlRelationalDelegate(this)); mapper->setModel(statusModel); mapper->addMapping(ui->refLineEdit, statusModel->fieldIndex("ref")); mapper->addMapping(ui->nameLineEdit, statusModel->fieldIndex("name")); mapper->addMapping(ui->statusCB, statusFieldId);
}
@
The submission process is as simple as the following:
@
void CreateAddressDialog::accept()
{
if(ui->nameLineEdit->text().length() < 5){
QMessageBox::critical(0, tr("Error"),tr("The name must be at least 5 characters long."), QMessageBox::Cancel);
return;
}else if(ui->refLineEdit->text().length() > 10){
QMessageBox::critical(0, tr("Error"),tr("The reference may not be more than 10 characters long."), QMessageBox::Cancel);
return;
}else if(ui->statusCB->currentIndex() < 0){
QMessageBox::critical(0, tr("Error"),tr("The item must have a status."), QMessageBox::Cancel);
return;
}
qDebug() << mapper->submit();
this->close();
}
@The problem, is that mapper->submit() failed ("false" is displayed). If I call the model's lastError, nothing shows up. The fields which are mapped to this mapper are the mandatory fields of the table (id excepted because it is marked as autoincrement).
Any help is greatly appreciated as I really don't understand (and can't seem to find out) why this widget doesn't add anything to the database. Let me mention that I checked with a standard SQLite database viewer to be sure of the contents of the SQLite database were like.
P.S.: You can browse the full code if you think it's needed to solve this problem on [url=https://code.google.com/p/invensile/source/browse/#svn/trunk]Google code[/url].
Thanks in advance!
-
Hi,
Please format your code in an appropriate way for this forum.
If you are really following exactly the Qt tutorial about "SQL Widget Mapper Example":http://doc.qt.nokia.com/latest/sql-sqlwidgetmapper.html why don;t you download the provided files at the tutorial and using them to find and solve your problem?
Regards,
Leon -
Hi,
Could you explain me what is the appropriate way for formatting code on Qt? There is no "help" link when posting a new thread (even when you're new on the forum just like me) nor bbcode cheat sheet. As for the HTML tags which showed (because I suppose that is what you are referring to), I added the [ code ] bb tags and the preview showed the post correctly. It was only upon submitting it that the < div > blocks showed up. I tried editing my post to remove them but they weren't in the message to be edited. I think it's a forum bug.
As for the example, there is a major difference: my program is far more complex than that of the example. In fact, my main model which is used to display the results, is defined in the main window widget. The problem I am facing occurs in another widget (a widget with ok and close buttons). In C++, b.h can't include a.h if a.h already includes b.h . Since the main window calls this widget, I can't include the main window header in this widget. So the only solution would be to extract these variables into c.h and have both widgets include c.h . In my case, I prefered to simply recreate a QSqlRelationnalTable objects which is defined exactly as the one in the main window. In the main window, it works marvelously. For an obscure reason, it doesn't work in the widget. This is why I cam to get help.
In addition, the example isn't complete and probably won't compile. If you look at the code (which I have for at least one hour total), some slots are called but never defined (neither in the .c nor in the header). That said, in my code, I follow line by line the procedure of the example.
Thanks in advance for additional help.
-
[quote author="Xionbox" date="1304247979"]Could you explain me what is the appropriate way for formatting code on Qt? There is no "help" link when posting a new thread (even when you're new on the forum just like me) nor bbcode cheat sheet. [/quote]
Please read the "Forum Help":http://developer.qt.nokia.com/wiki/ForumHelp About code wrapping check "this part of the help":http://developer.qt.nokia.com/wiki/ForumHelp#e3f82045ad0f480d3fb9e0ac2d58fb01
[quote author="Xionbox" date="1304247979"]Hi,
The problem I am facing occurs in another widget (a widget with ok and close buttons). In C++, b.h can't include a.h if a.h already includes b.h . Since the main window calls this widget, I can't include the main window header in this widget. So the only solution would be to extract these variables into c.h and have both widgets include c.h .[/quote]Can't you solve the issue using C++ forward declarations?
Cheers,
Leon -
Thank you for the help links. I've corrected my original post. I'll look into forward declaration and reply once I've tested that.
-
I don't seem to be able to do a forward declaration and don't understand why. Maybe could someone help, here's what I do.
In "createaddressdialog.h" (we can call it A.h), I added the following line:
@
namespace Ui {
class MainWindow; // this is the new line
class CreateAddressDialog;
}
@
In "mainwindow.h" (we can call it B.h) I added the following line:
@
namespace Ui {
class MainWindow; // this is the new line
class CreateAddressDialog;
}
@Then in "createaddressdialog.cpp" (A.cpp), I added the following:
@
#include "createaddressdialog.h" // our A.h
#include "mainwindow.h" // our B.h
@Identically, I added the following in "mainwindow.cpp" (B.cpp):
@
#include "mainwindow.h" // our B.h
#include "createaddressdialog.h" // our A.h
@The problem is a major one: the program no longer compiles and display the following error.
@
In file included from main.cpp:3:0:
mainwindow.h:55:5: error: ‘CreateAddressDialog’ does not name a type
make: Leaving directory `xyz'
make: *** [main.o] Error 1
Exited with code 2.
Error while building project Inventory
When executing build step 'Make'
@To make sure I was doing this properly, I had a look at this page: http://www.adp-gmbh.ch/cpp/forward_decl.html
Any idea why this doesn't work?
Additionally, is there a way to retrieve the lats error of "mapper->submit()"? I looked in the documentation and didn't seem to find anything. I also had a look at the model documentation (thinking of mapper->model->lastError() or something similar) but I didn't find anything there either.
Thank you in advance.
-
I duplicated this problem, did you ever resolve it, if so how?
I did note that in my code, the function returned true; but the database did not persist the data changes.
Update: I tried submitAll on the model and it worked; I think that is your problem as well.