PDA

View Full Version : Managing data in a TableView



scarleton
6th June 2010, 02:30
First off, I am new somewhat new to using Qt. About two years ago I used it for a specific project, but I never had to dive too deep into the Model/View and never touched the SQL plug-ins. In my current project, I have a product table in which the user needs to be able to add, delete, edit, and sort:

CREATE TABLE Product (
ProductId INTEGER PRIMARY KEY AUTOINCREMENT,
PriceListId INTEGER NOT NULL,
ProductType INTEGER NOT NULL DEFAULT 1,
SortOrder INTEGER NOT NULL,
Description CHAR(80) NOT NULL,
Price NUMERIC(10,4) NOT NULL
)

The only two things displayed are the description and price. I have created a custom QSqlTableModel to display the price correctly. I have implemented my own delegate for the TableView to present the correct editor with the correct limitations on both fields. To add something, I have extra widgets to enter the description and price, then I use this SQL to insert it into the database:


INSERT INTO Product (PriceListId, SortOrder, Description, Price)
VALUES(:priceListId1, (SELECT MAX(P.SortOrder) + 1 FROM Product P WHERE P.PriceListId = :priceListId2), :description, :price)

I am trying to figure out how to delete and to sort, but it is turning out doing it manually seems like a lot of work and I hafe a feeling there is a better way to leverage Qt to make life much easier.


How does one go about adding a none trivial item to a ModelView?
Like in the current .Net datagrids, is it possible to get a blank line at the bottom of the TableView for a user to add a new row?
What is the standard way for a user to delete something from a TableView?
Any and all suggestions on how I am implementing sorting is welcome, but at the DB level and how to implement it at the UI level is welcome.


See the next post for the ui file I generated for this

Sam

scarleton
6th June 2010, 02:30
Here is my ui file, it was too big to fit in the last post:


<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ProductMgrFormClass</class>
<widget class="QWidget" name="ProductMgrFormClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>450</width>
<height>400</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>450</width>
<height>400</height>
</size>
</property>
<property name="windowTitle">
<string>Product Manager</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="priceListLabel">
<property name="text">
<string>Price List:</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QComboBox" name="productListComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>175</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Manage</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="priceListProductsLabel">
<property name="text">
<string>Price List Products:</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QTableView" name="productTableView">
<property name="editTriggers">
<set>QAbstractItemView::AnyKeyPressed|QAbstractItemView ::DoubleClicked|QAbstractItemView::EditKeyPressed| QAbstractItemView::SelectedClicked</set>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderVisible">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderVisible">
<bool>true</bool>
</attribute>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="upButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Move selected product up.</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="salescenter.qrc">
<normaloff>:/SalesCenter/Images/sub_blue_plus-16x16.png</normaloff>:/SalesCenter/Images/sub_blue_plus-16x16.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="downButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Move selected product down.</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="salescenter.qrc">
<normaloff>:/SalesCenter/Images/sub_blue_minus-16x16.png</normaloff>:/SalesCenter/Images/sub_blue_minus-16x16.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="deleteButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Delete the selected product.</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="salescenter.qrc">
<normaloff>:/SalesCenter/Images/sub_blue_delete-16x16.png</normaloff>:/SalesCenter/Images/sub_blue_delete-16x16.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string> Add Product </string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="newProductLabel">
<property name="text">
<string>Product Description</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="newProductLineEdit">
<property name="minimumSize">
<size>
<width>175</width>
<height>0</height>
</size>
</property>
<property name="maxLength">
<number>80</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="newPriceLabel">
<property name="text">
<string>Price:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QDoubleSpinBox" name="newPriceDoubleSpinBox">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>999999999.990000009536743</double>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="addProductButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Add Product</string>
</property>
</widget>
</item>
<item row="2" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>310</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<tabstops>
<tabstop>productListComboBox</tabstop>
<tabstop>pushButton</tabstop>
<tabstop>productTableView</tabstop>
<tabstop>upButton</tabstop>
<tabstop>downButton</tabstop>
<tabstop>deleteButton</tabstop>
<tabstop>newProductLineEdit</tabstop>
<tabstop>newPriceDoubleSpinBox</tabstop>
<tabstop>addProductButton</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources>
<include location="salescenter.qrc"/>
</resources>
<connections/>
</ui>

numbat
6th June 2010, 14:09
This does everything except delete nicely. Someone else will probably suggest a lot simpler method.
Header:


#include <QtSql>
#include <QtGui>

class EditableSqlModel : public QSqlQueryModel
{
Q_OBJECT

public:
EditableSqlModel(QObject * parent = 0);
bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole );
Qt::ItemFlags flags ( const QModelIndex & index ) const;
QVariant data ( const QModelIndex & item, int role = Qt::DisplayRole ) const;
int rowCount ( const QModelIndex & parent = QModelIndex() ) const;
void sort ( int column, Qt::SortOrder order = Qt::AscendingOrder );
bool removeRows ( int row, int count, const QModelIndex & parent = QModelIndex() );
private:
QHash<QString, QString> hash;
int rows;
QString sortField, ordering;
};


class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget * parent = 0);
public slots:
void deleteEntry();

private:
EditableSqlModel model;
QTableView tv;
QAction deleteAction;
};

and source


#include <QtGui>
#include "test11.h"


EditableSqlModel::EditableSqlModel(QObject * parent) :
QSqlQueryModel(parent), rows(1), sortField("First"), ordering("ASC")
{}

QVariant EditableSqlModel::data ( const QModelIndex & item, int role ) const
{
if (item.row() == rowCount() - 1)
return QVariant(); /* Our empty row for inserts. */

if (role == Qt::DisplayRole)
{
QString where = QString("%1_%2").arg(item.row()).arg(item.column());
QString original;

if (hash.contains(where))
original = hash.value(where); /* New data from the hash. */
else
original = QSqlQueryModel::data(item, role).toString(); /* Old data from the original model. */

if (item.column() == 1)
{
/* Custom formatting goes here. */
original = original.prepend('$');
}

return original;
}

return QSqlQueryModel::data(item, role);
}


bool EditableSqlModel::setData ( const QModelIndex & itemIndex, const QVariant & value, int role )
{
if (itemIndex.column() < 0 || itemIndex.column() > 2)
return false;

QSqlQuery query;
bool fInserted;

if (itemIndex.row() == rowCount() - 1)
{
QString first = itemIndex.column() == 1 ? value.toString() : "";
QString last = itemIndex.column() == 2 ? value.toString() : "";

query.prepare("INSERT INTO T1(First, Last) VALUES(:first, :last)");
query.bindValue(":first", first);
query.bindValue(":last", last);
query.exec();

/* Store our primary key. */
QString where = QString("%1_%2").arg(itemIndex.row()).arg(0);
hash.insert(where, query.lastInsertId().toString());

beginInsertRows(itemIndex.parent(), itemIndex.row(), itemIndex.row());
rows++;
fInserted = true;
}
else
{
int primaryKey = data(index(itemIndex.row(), 0), Qt::DisplayRole).toInt();

if (itemIndex.column() == 1)
{
query.prepare("UPDATE T1 SET First=:first WHERE id = :id");
query.bindValue(":first", value);
query.bindValue(":id", primaryKey);
query.exec();
}
else if (itemIndex.column() == 2)
{
query.prepare("UPDATE T1 SET Last=:last WHERE id = :id");
query.bindValue(":last", value);
query.bindValue(":id", primaryKey);
query.exec();
}
}

/* Store the new value in a hash to retrieve later. */
QString where = QString("%1_%2").arg(itemIndex.row()).arg(itemIndex.column());
hash.insert(where, value.toString());

if (fInserted)
endInsertRows();

return true;
}

int EditableSqlModel::rowCount ( const QModelIndex & parent) const
{
if (parent.isValid()) return 0;
return QSqlQueryModel::rowCount(parent) + rows;
}


Qt::ItemFlags EditableSqlModel::flags ( const QModelIndex & index ) const
{
return QSqlQueryModel::flags(index) | Qt::ItemIsEditable;
}

void EditableSqlModel::sort ( int column, Qt::SortOrder order)
{
sortField = column == 1 ? "First" : "Last";
ordering = order == Qt::AscendingOrder ? "ASC" : "DESC";
rows = 1;
hash.clear();
beginResetModel();
setQuery(QString("SELECT id, First, Last FROM T1 ORDER BY %1 %2").arg(sortField, ordering));
endResetModel();
}

bool EditableSqlModel::removeRows ( int row, int count, const QModelIndex & parent)
{
beginResetModel();
QSqlQuery query;
query.prepare("DELETE FROM T1 WHERE id=:id");
for (int i = row; i < row + count; i++)
{
query.bindValue(":id", data(index(i, 0), Qt::DisplayRole));
query.exec();
}
rows = 1;
hash.clear();
setQuery(QString("SELECT id, First, Last FROM T1 ORDER BY %1 %2").arg(sortField, ordering));
endResetModel();
}

void MainWindow::deleteEntry()
{
QModelIndexList idxs = tv.selectionModel()->selectedRows();

for (int i = idxs.length() - 1; i >= 0; i--)
{
tv.model()->removeRow(idxs.at(i).row(), idxs.at(i).parent());
}
}

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), deleteAction("Delete", this), tv(this)
{
model.setQuery("SELECT id, First, Last FROM T1 ORDER BY First ASC");

tv.setModel(&model);
tv.setColumnHidden(0, true); /* Hide primary key */
tv.setSortingEnabled(true);
tv.addAction(&deleteAction);
tv.setContextMenuPolicy(Qt::ActionsContextMenu);

connect(&deleteAction, SIGNAL(triggered()), this, SLOT(deleteEntry()));

setCentralWidget(&tv);
tv.show();

}

void setupDb(QSqlDatabase & db)
{
db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:");
db.open();

QString sql = QString("CREATE TABLE T1(id INTEGER PRIMARY KEY AUTOINCREMENT, First, Last)");
QSqlQuery query(db);
query.exec(sql);

db.transaction();

query.prepare("INSERT INTO T1 (First, Last) "
"VALUES (:2, :3)");

for (int i = 0; i < 100; i++)
{
query.bindValue(":2", QString("Bart %1").arg(i));
query.bindValue(":3", "Simpson");
query.exec();
}

db.commit();
}



int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QSqlDatabase db;
setupDb(db);

MainWindow win(0);
win.show();

return a.exec();

}

scarleton
6th June 2010, 15:46
This is GREAT, thank you!!! Do you have any thoughts on how to detect when a user clicks on the row number, to the left of the first column? If I can get that piece of info, I can implement a <Delete> button outside of the TableView.

Sam

scarleton
8th June 2010, 03:23
Someone posted to another question along the same lines, the solution was to capture the sectionClicked signal on the TableView's verticalHeader.

numbat
8th June 2010, 10:32
Here is version 2. It does delete elegantly (without refreshing the model). It turned out to be very difficult to get working, so test well if you use it.
Header:


#include <QtSql>
#include <QtGui>

class EditableSqlModel : public QAbstractItemModel
{
Q_OBJECT

public:
EditableSqlModel(QObject * parent = 0);
bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole );
Qt::ItemFlags flags ( const QModelIndex & index ) const;
QVariant data ( const QModelIndex & item, int role = Qt::DisplayRole ) const;
int rowCount ( const QModelIndex & parent = QModelIndex() ) const;
void sort ( int column, Qt::SortOrder order = Qt::AscendingOrder );
bool removeRows ( int row, int count, const QModelIndex & parent = QModelIndex() );
QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const;
bool hasIndex ( int row, int column, const QModelIndex & parent = QModelIndex() ) const;
QModelIndex parent(const QModelIndex &child) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
void setQuery(QString sql);

private:
void refreshOffsets();
void resizeVectors();

QString lastSql;
QSqlQueryModel mod;
QHash<QString, QString> hash;
int rows;
QString sortField, ordering;
QVector<int> rowOffsets;
QVector<bool> available;
enum { UNAVAILABLE = 1, AVAILABLE = 0 };
};


class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget * parent = 0);
public slots:
void deleteEntry();

private:
EditableSqlModel model;
QAction deleteAction;
QTableView tv;
};

Source:


#include <QtGui>
#include "test11.h"


EditableSqlModel::EditableSqlModel(QObject * parent) :
QAbstractItemModel(parent), rows(1), sortField("First"), ordering("ASC")
{}


QModelIndex EditableSqlModel::parent(const QModelIndex &child) const
{
Q_UNUSED(child);
return QModelIndex();
}

int EditableSqlModel::columnCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;

return 3;
}

bool EditableSqlModel::hasIndex ( int row, int column, const QModelIndex & parent ) const
{
if (column < 0 || column > 2 || row < 0 || row >= rowCount() || parent.isValid())
return false;

return true;
}

QModelIndex EditableSqlModel::index ( int row, int column, const QModelIndex & parent ) const
{
return hasIndex(row, column, parent) ? createIndex(row, column, 0) : QModelIndex();
}


QVariant EditableSqlModel::data ( const QModelIndex & item, int role ) const
{
if (!item.isValid() || !hasIndex(item.row(), item.column(), item.parent()))
return QVariant();

if (item.row() == rowCount() - 1)
return QVariant(); /* Our empty row for inserts. */

/* Adjust for deleted rows. */
int row = item.row() + rowOffsets.at(item.row());

if (role == Qt::DisplayRole || role == Qt::EditRole)
{
QString where = QString("%1_%2").arg(row).arg(item.column());
QString original;

if (hash.contains(where) || hash.contains(QString("%1_0").arg(row)))
original = hash.value(where); /* New data from the hash. */
else
original = mod.data(mod.index(row, item.column()), role).toString(); /* Old data from the original model. */

if (item.column() == 1)
{
/* Custom formatting goes here. */
original = original.prepend('$');
}

return original;
}

return QVariant();
}


bool EditableSqlModel::setData ( const QModelIndex & itemIndex, const QVariant & value, int role )
{
if (!itemIndex.isValid() || !hasIndex(itemIndex.row(), itemIndex.column(), itemIndex.parent()))
return false;

if (role != Qt::DisplayRole && role != Qt::EditRole)
return false;

QSqlQuery query;
bool fInserted;

/* Adjust for deleted rows. */
int row = itemIndex.row() + rowOffsets.at(itemIndex.row());

if (itemIndex.row() == rowCount() - 1 &&
!hash.contains(QString("%1_0").arg(row)))
{
/* A new record, so insert it into the database. */
QString first = itemIndex.column() == 1 ? value.toString() : "";
QString last = itemIndex.column() == 2 ? value.toString() : "";

query.prepare("INSERT INTO T1(First, Last) VALUES(:first, :last)");
query.bindValue(":first", first);
query.bindValue(":last", last);
query.exec();

/* Store our primary key. */
QString where = QString("%1_0").arg(row);
hash.insert(where, query.lastInsertId().toString());

beginInsertRows(itemIndex.parent(), itemIndex.row() + 1, itemIndex.row() + 1);
rows = rowCount() + 1;
resizeVectors();
fInserted = true;
}
else
{
/* An existing record, so update it in the database. */
int primaryKey = data(index(itemIndex.row(), 0), Qt::DisplayRole).toInt();

if (itemIndex.column() == 1)
{
query.prepare("UPDATE T1 SET First=:first WHERE id = :id");
query.bindValue(":first", value);
query.bindValue(":id", primaryKey);
query.exec();
}
else if (itemIndex.column() == 2)
{
query.prepare("UPDATE T1 SET Last=:last WHERE id = :id");
query.bindValue(":last", value);
query.bindValue(":id", primaryKey);
query.exec();
}
}

/* Store the new value in a hash to retrieve later. */
QString where = QString("%1_%2").arg(row).arg(itemIndex.column());
hash.insert(where, value.toString());

if (fInserted)
endInsertRows();

return true;
}

int EditableSqlModel::rowCount ( const QModelIndex & parent) const
{
return parent.isValid() ? 0 : rows;
}


Qt::ItemFlags EditableSqlModel::flags ( const QModelIndex & index ) const
{
Q_UNUSED(index);
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
}

void EditableSqlModel::setQuery(QString sql)
{
if (sql == lastSql) return;
beginResetModel();
beginRemoveRows(QModelIndex(), 0, rowCount() - 1);
endRemoveRows();

mod.setQuery(sql);
rows = mod.rowCount() + 1;
resizeVectors();

beginInsertRows(QModelIndex(), 0, rows - 1);
hash.clear();
qFill(rowOffsets, 0);
qFill(available, 0);

endInsertRows();
endResetModel();
lastSql = sql;
}

void EditableSqlModel::sort ( int column, Qt::SortOrder order)
{
sortField = column == 1 ? "First" : "Last";
ordering = order == Qt::AscendingOrder ? "ASC" : "DESC";
setQuery(QString("SELECT id, First, Last FROM T1 ORDER BY %1 %2").arg(sortField, ordering));
}

void EditableSqlModel::resizeVectors()
{
rowOffsets.resize(qMax(rowOffsets.count() + 1, rows));
available.resize(qMax(available.count() + 1, rows));

refreshOffsets();
}

void EditableSqlModel::refreshOffsets()
{
/* Now calculate the offsets. */
for (int i = 0, j = 0; i < available.count(); i++)
{
if (available.at(i) == AVAILABLE)
{
rowOffsets[j] = i - j;
j++;
}
}
}

bool EditableSqlModel::removeRows ( int row, int count, const QModelIndex & parent)
{
beginRemoveRows(parent, row, row + count - 1);

if (row == rowCount() - 1)
{
/* Don't let the new addition row be deleted. */
endRemoveRows();
beginInsertRows(parent, row, row);
endInsertRows();
return false;
}

QSqlQuery query;
query.prepare("DELETE FROM T1 WHERE id=:id");
for (int i = row + count - 1; i >= row; i--)
{
query.bindValue(":id", data(index(i, 0)).toInt());
query.exec();
}

/* Get real rows deleted and mark as deleted. */
for (int i = row; i < row + count; i++)
{
int rowreal = i + rowOffsets.at(i);
available[rowreal] = UNAVAILABLE;

hash.remove(QString("%1_0").arg(rowreal));
hash.remove(QString("%1_1").arg(rowreal));
hash.remove(QString("%1_2").arg(rowreal));
}

refreshOffsets();
rows -= count;
endRemoveRows();
return true;
}

void MainWindow::deleteEntry()
{
QModelIndexList idxs = tv.selectionModel()->selectedRows();

/* Must do this one at a time or sort and go backwards. */
while (!idxs.isEmpty())
{
tv.model()->removeRow(idxs.at(0).row(), idxs.at(0).parent());
idxs = tv.selectionModel()->selectedRows();
}
}

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), deleteAction("Delete", this), tv(this)
{
model.setQuery("SELECT id, First, Last FROM T1");

tv.setModel(&model);
tv.setColumnHidden(0, true); /* Hide primary key */
tv.setSortingEnabled(true);
tv.addAction(&deleteAction);
tv.setContextMenuPolicy(Qt::ActionsContextMenu);

connect(&deleteAction, SIGNAL(triggered()), this, SLOT(deleteEntry()));
setCentralWidget(&tv);
tv.show();
}

void setupDb(QSqlDatabase & db)
{
db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:");
db.open();

QString sql = QString("CREATE TABLE T1(id INTEGER PRIMARY KEY AUTOINCREMENT, First, Last)");
QSqlQuery query(db);
query.exec(sql);

db.transaction();

query.prepare("INSERT INTO T1 (First, Last) "
"VALUES (:2, :3)");

for (int i = 0; i < 5; i++)
{
query.bindValue(":2", QString("Bart %1").arg(i));
query.bindValue(":3", "Simpson");
query.exec();
}

db.commit();
}


int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QSqlDatabase db;
setupDb(db);

MainWindow win(0);
win.show();

return a.exec();
}

wysota
11th June 2010, 00:48
Please do not inline such large quantities of code in your posts. Attach files to your posts instead.