PDA

View Full Version : Nesting TableViews under TreeView items



marcuso
24th March 2012, 00:04
So the idea is to be able to expand and minimize items that contain 1 table each. The items may have children of their own, each of which may also have 1 table each.

My spontaneous solution would be to use a treeview with the parent item being a standard AbstractItem, but the child would be something that a custom QStyledItemDelegate could pick up on to draw a TableView in it's place.

I'm with PyQt but could read most languages I suppose.

Adding an image that may help clarify what I mean.
7527

Thanks,
Marcus

Added after 26 minutes:

Guess a question might be appropriate here.. :) sorry, it's late.

So, how would you guys do it?

marcuso
24th March 2012, 14:04
This is pretty close to what I'm looking for. Let me know if there are any drawbacks to the way this works.


import sys

from PyQt4.QtGui import *
from PyQt4.QtCore import *

class EditorDelegate(QStyledItemDelegate):
def createEditor(self, parent, option, index):
if index.column() == 0:
#item = index.internalPointer()

table = QTableWidget(parent)
table.insertRow(0)
table.insertRow(1)
table.insertColumn(0)

item1 = QTableWidgetItem()
item1.setText('item1')
table.setItem(0, 0, item1)

return table

else:
return QStyledItemDelegate.createEditor(self, parent, option, index)


app = QApplication(sys.argv)

delegate = EditorDelegate()

tree = QTreeWidget()
tree.setItemDelegate(delegate)

item1 = QTreeWidgetItem(tree)
item1.setText(0, 'item1')
tableChild = QTreeWidgetItem(item1)
tableChild.setText(0, 'table')

item2 = QTreeWidgetItem(item1)
item2.setText(0, 'item2')
tableChild2 = QTreeWidgetItem(item2)
tableChild2.setText(0, 'table2')

tree.openPersistentEditor(tableChild)
tree.openPersistentEditor(tableChild2)

tree.show()

app.exec_()

Getting the internalPointer from the item I'm creating an editor from causes a crash. My understanding is very limited at this point and so I fail to see why. Ideally, I'd like to query an attribute of the tree node and only draw the editor on item's that are designed to have one. I can however live with manually specifying the persistentEditor state on items I wan't to have editable and simply have all other items not be able to enter or go out of an editable state since the tableViews are supposed to always stay open.

wysota
24th March 2012, 14:12
Why don't you just use a QTreeView or QTreeWidget, potentially with custom drawing?

marcuso
24th March 2012, 14:59
Hey wysota, thanks for your reply.

I've got very limited knowledge of custom drawing, could you please help clarify how that would help me in this case? What are the benefits of that compared to how I did it in the example posted above? Also, I was using a TreeView. How do you suggest I use it differently?

wysota
24th March 2012, 15:22
The benefits are quite obvious -- you get a working single view as opposed to what you have which is multiple views unrelated to each other placed inside yet another view again completely unrelated to anything. I would start by simply using QTreeView::setFirstColumnSpanned() to make the first column of the items you want to span the whole width of the view.


#include <QtGui>

int main(int argc, char **argv) {
QApplication app(argc, argv);
QStandardItemModel model;
model.setColumnCount(2);
model.setHorizontalHeaderLabels(QStringList() << "Key" << "Value");
for(int i=0;i<10;++i) {
QList<QStandardItem*> top;
QStandardItem *topItem = new QStandardItem(QString("row %1").arg(i+1));
top << topItem;
model.appendRow(top);
for(int j=0;j<5;++j) {
QList<QStandardItem*> child;
child << new QStandardItem(QString::number(qrand()%100)) << new QStandardItem(QString::number(qrand() % 100));
topItem->appendRow(child);
}
}
QTreeView view;
view.setModel(&model);
view.expandAll();
for(int i=0;i<model.rowCount();++i) {
view.setFirstColumnSpanned(i, QModelIndex(), true);
}
view.show();
return app.exec();
}

7528

The rest is just a matter of drawing according to your needs.

marcuso
24th March 2012, 17:52
I see. How about if I wish to edit the items in this TableView?

What I have is a browser with items, and some of the items has properties stored within it along with children that may also have properties. What I'm looking to do is to visualize this data and also let the user edit it.

So, one treeview for browsing the items, and another for showing the currently selected item along with it's properties and children with additional properties.

I'm currently trying out making another custom AbstractItemModel for this Editor along with a QStyledItemDelegate attached to the View of that model. The model would be able to use the same data (being dragged and dropped from the browser onto the Editor) but display it according to the Delegate.

Does this seem reasonable or is custom drawing still the way to go? Again, this is very new territory to me.

Thanks for your help!

wysota
24th March 2012, 17:58
I see. How about if I wish to edit the items in this TableView?
Then edit them :) What's the big deal?

I think you are making things more complex than they really are.

marcuso
24th March 2012, 18:07
I think you are right. :)

But okay, I was getting used to having the benefits of a TableView, such as the default behaviour of the delegate to get spinboxes and such for values that are supposed to be numerical only, and the drawing of lines inbetween fields. Wouldn't I have to draw that myself if going with the custom drawing approach? Is there a middleground somewhere?

wysota
24th March 2012, 18:39
But okay, I was getting used to having the benefits of a TableView, such as the default behaviour of the delegate to get spinboxes and such for values that are supposed to be numerical only
You should be getting those for a tree view as well. It's using the same delegate.

Wouldn't I have to draw that myself if going with the custom drawing approach?
The default delegate doesn't draw the grid for a tree view. That's why I said you needed custom drawing but it's not a big issue. Certainly a smaller one than embedding a view in another view.

marcuso
24th March 2012, 19:00
Okay. I've been experimenting a bit while chatting with you and it all sounds and looks really good. I'm gonna give this a go and get back to you. Thanks for your help.