PDA

View Full Version : QTableView in ui with model/delegate



tpf80
5th November 2008, 00:21
Using the Spin Box Delegate Example, I was able to create a more complex delegate system that included QDateTime, QLineEdit, and QComboBox for the columns. My class works perfectly when I use the example main.cpp from the spinbox delegate example.

I made a window in designer with a QTableView in it, and attempted to apply the the model and delegate to it as follows:



//setup interface of main window:
DialogAddInventoryMass::DialogAddInventoryMass(QWi dget *parent, QSqlDatabase db) : QDialog(parent) {

setupUi(this);

QStandardItemModel model(10, 9);
inventoryDelegate delegate;

tableView->setModel(&model);
tableView->setItemDelegate(&delegate);



//connect form item signals to slots that arent in the UI file here:
connect(buttonBox, SIGNAL(accepted()), this, SLOT(returnVars()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));

database = db;
}


What I expected to see (as I did using the spin box example main.cpp) would be my QTableView with 10 rows, and 9 columns, and the delegate working properly.

What actually happens, is a blank QTableView, no rows/columns in it, and there are no errors (either in compilation or runtime). I also have cell borders enabled in the .ui file and console enabled.

What might the reason be that the QStandardItemModel is not applied to the QTableView in my UI?

aamer4yu
5th November 2008, 05:37
Your model is on stack.
Try using heap
QStandardItemModel *model = new QStandardItemModel;

tpf80
5th November 2008, 19:45
ah yes your right, thanks for the tip!

tpf80
5th November 2008, 21:26
ok another question, I have a combobox delegate, which I want to have the item name in the QComboBox with an ID in it. Heres my current code:



void inventoryDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
//if its the combobox column:
if (index.column() == 3) {
QString value = index.model()->data(index, Qt::DisplayRole).toString();

QComboBox *comboBox = static_cast<QComboBox*>(editor);
comboBox->addItem("", "0");

for (int i = 0; i < category->itemList1.size(); ++i) {
comboBox->addItem(category->itemList1.at(i), category->itemList2.at(i));
}

comboBox->setCurrentIndex(comboBox->findText(value));

//if its not a combobox column
} else {
//do stuff for non-combobox delegates
}
}

void inventoryDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
if (index.column() == 3) {
QComboBox *comboBox = static_cast<QComboBox*>(editor);
model->setData(index, comboBox->currentText(), Qt::EditRole);

//if its not a combobox column
} else {
//do stuff for non-combobox delegates
}
}

Notice that in setEditorData, I use:


comboBox->setCurrentIndex(comboBox->findText(value));

and in setModelData I use:


model->setData(index, comboBox->currentText(), Qt::EditRole);


what I would like to be able to do, is when I setData to the model be able to store the QComboBox text/data pair that was selected to the model, so that in setEditorData i could use:


comboBox->setCurrentIndex(comboBox->findData(data));

to not only make sure that the correct listing in the combobox is selected when it populates, but have the user be able to see the selected "Text" in the table cell, but the program uses the "data" associated with it for its internal uses.

How can I store data in a QStandardItemModel cell in a similar fashion as the items are in a QComboBox item?

aamer4yu
6th November 2008, 08:15
I didnt fully understand what you require.
But if you are talking about displaying some data, and using some other data, you can use roles.

For text to appear, Qt has Qt::DisplayRole. You can define your own roles and set data for it.
something like -
QString value = index.data(MYROLE).toString();

Hope you get the idea :)

tpf80
6th November 2008, 20:23
I have modified my code to the following, using the custom role:



enum {
comboDataRole = Qt::UserRole
};

void inventoryDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
//grab data from the model
QString value = index.model()->data(index, Qt::DisplayRole).toString();
QString data = index.model()->data(index, comboDataRole).toString();
//make a combobox, add a blank line as the first item in case there has not been an item selected
QComboBox *comboBox = static_cast<QComboBox*>(editor);
comboBox->addItem("", "0");
//fill the combobox with our stored list items
for (int i = 0; i < category.itemList1.size(); ++i) {
comboBox->addItem(category.itemList1.at(i), category.itemList2.at(i));
}
//move the selected item of the combobox to the contents stored already in the cell
comboBox->setCurrentIndex(comboBox->findData(data));

}

void inventoryDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {

QComboBox *comboBox = static_cast<QComboBox*>(editor);
//store the text in a user viewable role, and the itemdata somewhere the user can't see
model->setData(index, comboBox->currentText(), Qt::EditRole);
model->setData(index, comboBox->itemData(comboBox->currentIndex()).toString(), comboDataRole);

}


Somehow the itemdata from the QComboBox is either not storing in the model in setModelData, or not being retrieved from the model in setEditorData. What else might I be missing to make this work?

tpf80
6th November 2008, 23:18
actually from further testing, it *can* store the data as I want, but only if I select the same item in the combobox 2 times in a row, otherwise the data will be retrieved as whatever was previously in the model, rather than what was last selected. Still trying to figure out why this is..

tpf80
7th November 2008, 00:00
Now its working. When i changed this:


model->setData(index, comboBox->currentText(), Qt::EditRole);
model->setData(index, comboBox->itemData(comboBox->currentIndex()).toString(), Qt::UserRole);

to this:


QString combotext = comboBox->currentText();
QString combodata = comboBox->itemData(comboBox->currentIndex()).toString();

model->setData(index, combotext, Qt::EditRole);
model->setData(index, combodata, Qt::UserRole);

it decided to behave like I would expect.