PDA

View Full Version : Storing QList of QPair in QStandardItem then rendering it in QComboBox of QTableView.



toglia3d
15th June 2010, 06:14
Hello.

Well the question sums it up. I have a data structure that has a list of pair values per object and I would like to show them in a QComboBox of a QTableView.


typedef QPair<QString, QString> MyPair;
typedef QList<MyPair> MyList;
struct MyObject{
MyList myList;
};

How can I translate that into a QStandardItemModel?
How can I render that in a QComboBox?

I have already done it using a QTableWidget but maintaining both, the real data and the showed data, updated is getting messy.

Thanks for your help.

tbscope
15th June 2010, 06:29
There is no need to store a qlist of qpairs in a model. Just add rows and collumns

Since a combobox can only show one collumn, you will need to create a delegate that combines two columns.

aamer4yu
15th June 2010, 06:36
You can simply set the text into combobox,, cant you ?
Something like -
comboBox->setItemText(index, QString("<%1 , %2 >").arg(myList.at(index).first).arg(myList.at(index) .second));

And can you explain how you used in table widget, it will help to understand better what you are trying to do.

toglia3d
15th June 2010, 07:13
@tbscope
I got that. But in my case, since my object has this list of pairs, I need a way of storing this too. Its like some sort of inner table.

@aamer4yu
Yeah, I wouldn't mind rendering it that way. But how can I get a QStandardItem hold both Strings?

Say you were showing this parsed xml in a QTableView:

<item name="A">
<texture name="active" file="red.jpg"/>
<texture name="unactive" file="blue.jpg"/>
</item>
<item name="B">
<texture name="ok" file="ok.jpg"/>
<texture name="cancel" file="cancel.jpg"/>
</item>

The table should show 2 rows, each row with a combo box showing the list of textures.

tbscope
15th June 2010, 07:31
I got that. But in my case, since my object has this list of pairs, I need a way of storing this too. Its like some sort of inner table.

I understand. In theory you are working with two models that are combined in a complex way.
Why don't you use the model directly in your object?

However, you can add a qlist of qpairs to the model. Just use setData and a custom role.
Beware though, you might need to register your custom type for QVariant to be able to work with it.

If I would write this code, I would get rid of the qlist of qpairs and just use the model.

In all cases, you need to create a delegate.

aamer4yu
15th June 2010, 07:34
I dont even see the need for table view...
you can use layouts ... QLabels as item names, and QComboBox having list of textures.

Combining combobox in tableview will not be easy,,, and as tbscope said, delegates will be needed.

toglia3d
15th June 2010, 07:47
I understand. In theory you are working with two models that are combined in a complex way.
Why don't you use the model directly in your object?


Sure, I was thinking on doing that. Maybe inheriting from QStandardItem to add the stuff I need.


In all cases, you need to create a delegate. Can you please point an example of this to use with combo boxes.

Thanks.

toglia3d
15th June 2010, 07:52
I dont even see the need for table view...
Well, I'm not only showing the items, other stuff is needed like adding/removing textures, changing the order of items, etc. I'm using the table to get the selected items and stuff.

EDIT: My example showed two items... Real files have hundreds.

tbscope
15th June 2010, 08:14
Can you please point an example of this to use with combo boxes.

It's with a spin box, but the technique is completely the same for a combo box too:
http://doc.qt.nokia.com/4.6/itemviews-spinboxdelegate.html

More examples:
http://doc.qt.nokia.com/4.6/itemviews-stardelegate.html
http://doc.qt.nokia.com/4.6/examples-itemviews.html

toglia3d
15th June 2010, 09:37
Ok. Thanks. I managed to pull a simple demo.
One thing to notice is that with:


QModelIndex index = model.index(i,i, QModelIndex());
tableView->openPersistentEditor(index);

It is possible to have the widget render by default.


Beware though, you might need to register your custom type for QVariant to be able to work with it.
What I wasn't aware was that I needed to retrieve my list of "textures" with a QModelIndex.data. So I think I'll need to do what you're saying.

I'll seee that tommorrow.

toglia3d
20th June 2010, 23:29
Well to make a final conclusion this is what needs to be done:

1) Register the custom struct:

struct MyObject {
typedef QPair<QString, QString> MyPair;
typedef QList<MyPair> MyList;
MyList myList;
};
Q_DECLARE_METATYPE(MyObject)

2) Inserting items to the model:

QModelIndex index = model->index(row, column);
MyObject myObject;
myObject.myList.push_back(
MyObject::MyPair(QString("default"),QString("hello.png"))
);
myObject.myList.push_back(
MyObject::MyPair(QString("active"),QString("world.png"))
);
model->setData(index, qVariantFromValue(myObject));
tableView->openPersistentEditor(index);

3) Create the item delegate like the star delegate (http://doc.qt.nokia.com/4.6/itemviews-stardelegate.html) example:

QWidget* MyDelegate::createEditor(
QWidget* parent,
const QStyleOptionViewItem& option,
const QModelIndex& index) const
{
if(qVariantCanConvert<MyObject>(index.data())){
QComboBox* editor = new QComboBox(parent);
editor->setAutoFillBackground(true);
return editor;
}else{
return QItemDelegate::createEditor(parent, option, index);
}
}

void MyDelegate::setEditorData(
QWidget *editor,
const QModelIndex &index) const
{
if(qVariantCanConvert<MyObject>(index.data())){
QComboBox* comboBox = static_cast<QComboBox*>(editor);
MyObject auxObject = qVariantValue<MyObject>(index.data());
foreach(MyObject::MyPair par, auxObject.myList){
comboBox->addItem(par.first+"\t"+par.first);
}
}else{
return QItemDelegate::setEditorData(editor, index);
}
}

4) Set the item delegate to the QTableView:

MyDelegate* myDelegate = new MyDelegate();
tableView->setItemDelegate(myDelegate);

Thats it.

But I have some last question, By default items that are not "MyObject" are editable, this is because I'm making them with QItemDelegate::createEditor I think. I have tried customizing this widget but I cant see a setEditable method. So, what is the real default widget of a QTableView item?