PDA

View Full Version : QTreeWidgetItem questions



Michiel
14th May 2007, 14:08
I need a way for certain items in a QTreeWidget to have only one editable column. A double click on any of the other columns on that item should not show the edit-widget. How can I accomplish this? I suppose I could intercept the mouse-event, but how do I know which column was clicked? Or is there an even easier way that I overlooked?

And is it possible for certain columns to show a QDateTimeEdit widget as their edit widget instead of a QLineEdit?

Thanks!

jpn
14th May 2007, 14:16
I need a way for certain items in a QTreeWidget to have only one editable column. A double click on any of the other columns on that item should not show the edit-widget. How can I accomplish this?
The problem is that with model-view you can specify flags per index but for tree widget items you can specify flags only as per whole row. One way could be using a custom delegate (http://doc.trolltech.com/4.2/model-view-delegate.html) to prevent editing in certain columns.


And is it possible for certain columns to show a QDateTimeEdit widget as their edit widget instead of a QLineEdit?
Set the data as QDateTime, not as QString and you'll get corresponding editor out of the box:


QTreeWidgetItem* item = ...
// item->setText(0, "2007-05-14"); // <-- not like this
item->setData(0, Qt::DisplayRole, dateTime) // <-- but like this (dateTime is a QDateTime)

Michiel
14th May 2007, 14:45
Hm. It's actually a subclass of QTreeWidgetItem. I don't really understand these roles yet, and I've been using Qt::EditRole and Qt::UserRole for editing (through the editor and through the rest of the program respectively). But I reimplemented setData() to pass the request on to QTreeWidgetItem::setData() in case of other roles.

I did as you said and used Qt::DisplayRole instead of Qt::UserRole when setting the value from the code. But it still uses a line-edit. (Plus it causes a few other bugs with displaying the data, but that's just because I'm not storing it anymore.)

Could you explain more clearly please?

jpn
14th May 2007, 15:43
Maybe the QTreeWidgetItem subclass mixes up the role or something? Works fine for me:


#include <QtGui>

int main(int argc, char* argv[])
{
QApplication a(argc, argv);
QTreeWidget treeWidget;
treeWidget.setColumnCount(2);
QTreeWidgetItem* item = new QTreeWidgetItem(&treeWidget);
item->setFlags(item->flags() | Qt::ItemIsEditable);
// notice the difference while editing these two columns
item->setText(0, "Text");
item->setData(1, Qt::DisplayRole, QDateTime::currentDateTime());
treeWidget.show();
return a.exec();
}

jcooperddtd
14th May 2007, 23:40
I have had good success simply not specifying Qt::ItemIsEditable in the item->setFlags() call. By providing Qt::ItemIsEnabled | Qt::ItemIsSelectable only, you effectively disable editing on a cell by cell basis.

Michiel
14th May 2007, 23:50
I have had good success simply not specifying Qt::ItemIsEditable in the item->setFlags() call. By providing Qt::ItemIsEnabled | Qt::ItemIsSelectable only, you effectively disable editing on a cell by cell basis.

But 'item' is the whole row. If you do not specify Qt::itemIsEditable, none of the cells in the row is editable. Maybe you're thinking about tables?

By the way: I'm now trying a whole new approach. Using QTreeView and a real model instead of QTreeWidget. I think it will work.

jpn
15th May 2007, 07:01
By the way: I'm now trying a whole new approach. Using QTreeView and a real model instead of QTreeWidget. I think it will work.
I don't see any reason why wouldn't it work. The model-view approach is way more flexible. :)

Anyway, just for completeness, here's the solution for a tree widget:


class MyItemDelegate : public QItemDelegate
{
public:
MyItemDelegate(QObject* parent = 0) : QItemDelegate(parent) {}

QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
// allow only specific column to be edited, second column in this example
if (index.column() == 1)
return QItemDelegate::createEditor(parent, option, index);
return 0;
}
};

// usage:
// treeWidget->setItemDelegate(new MyItemDelegate(treeWidget));

Michiel
15th May 2007, 08:11
Cool! Looks like that would work. I'm still going to use a real model now, but here's a "thanks" for your trouble. :)