PDA

View Full Version : Setting QTreeWidget flag to Qt::ItemIsEditable seems to disable itemActivated SIGNAL



y.shan
21st November 2011, 12:14
Hi,

I'm working on a model to list some user defined data. For this I'm using the QTreeWidget class with 4 columns. The first column is a checkbox indicating whether the item is activated or not. In the second and third column I've inserted QComboBox Widgets using the setItemWidget(...) function to display possible options (The reason why i have chosen QTreeWidget and not QTableWidget). The last column should show a string which will be initialized empty.

However as the first three columns are very eye-catching due to their widgets, the last column with the empty string could be ignored by the user. Therefore I've implemented an UpdateWidgetState() function to check whether the last column is empty and if that's the case I set the font to italic, the foregroundcolor to grey and set the text to "enter function here". The UpdateWidgetState() function is called in the initiliazation routine and everytime when the QTreeWidget emits the itemChanged signal. This routine clears the tree widget and refills the view with the actual data.

The code looks something like this:



int num_items = GetNumberOfItems....
treeWidget->clear();
QList<QTreeWidgetItem *> items;
int i;
for (i = 0; i < num_items ; i++)
{
QString FunctionValue;

//get data for FunctionValue....

QStringList list;
list << "" << "" << "" << FunctionValue;

disconnect(treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
this, SLOT(treeWidgetItemChanged(QTreeWidgetItem*,int))) ;

QTreeWidgetItem * treeWidgetItem = new QTreeWidgetItem(treeWidget, list);
treeWidgetItem->setFlags(treeWidget->flags()|Qt::ItemIsEditable);
treeWidgetItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowI ndicator);

QFont item_font = treeWidget->font(3);
QBrush item_brush = treeWidget->foreground(3);
if (FunctionValue.isEmpty())
{
item_font.setItalic(TRUE);
item_brush.setColor(Qt::gray);
treeWidget->setText(3, "enter function here ...");
}
else
{
item_font.setItalic(FALSE);
item_brush.setColor(Qt::black);
}

treeWidget->setFont(3, item_font);
treeWidget->setForeground(3, item_brush);

connect(treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
this, SLOT(treeWidgetItemChanged(QTreeWidgetItem*,int))) ;

//data for first, second and third column.....

items.append(treeWidgetItem);
}
treeWidget->insertTopLevelItems(0, items);


The problem now is, that I want to show an empty text when the last column is edited (if the edit begins I don't want to have the "enter function here ..." string selected). For this I'm catching the itemActivated(...) signal and setting the text to an empty string manually:



void myDialog::treeWidgetItemActivated(QTreeWidgetItem * item, int column)
{
if (column == 3)
{
QString FunctionValue = get function value ....
if (FunctionValue.isEmpty())
{
disconnect(treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
this, SLOT(treeWidgetItemChanged(QTreeWidgetItem*,int))) ;

item->setText(3,"");
connect(treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
this, SLOT(treeWidgetItemChanged(QTreeWidgetItem*,int))) ;
}

}
}


However this signal is not triggered when I set the QTreeWidgetItem flag to Qt::ItemIsEditable and double click on it. However the signal is entered if i press the enter key (in which case the dialog is also closed). When I don't set the flag, then everything works well and the signal is catched. However I can't edit the text in this case. I've tried to do a workaround using openPersistentEditor and closePersistentEditor but that doesn't work very well.
Is this behaviour normal? If yes, is there a possibility to edit the text in the tree widget starting with a blank field (without using an extra Widget or subclassing the QTreeView model).

Thank you for you help!

y.shan
22nd November 2011, 13:03
I've summarized the problem in a small demonstration: If I set the ItemIsEditable flag then the itemActivated signal is not triggered on double clicking. Else it works fine.



Window::Window()
{
treeWidget = new QTreeWidget();

QStringList list;
list << "";

QTreeWidgetItem * treeWidgetItem = new QTreeWidgetItem(treeWidget, list);

//setting this flag disables itemActivated signal for double clicking
treeWidgetItem->setFlags(treeWidgetItem->flags()|Qt::ItemIsEditable);

treeWidget->insertTopLevelItem(0, treeWidgetItem);

connect(treeWidget, SIGNAL(itemActivated(QTreeWidgetItem*, int)),
this, SLOT(treeWidgetItemActivated(QTreeWidgetItem*, int)));

QGridLayout * layout = new QGridLayout;
layout->addWidget(treeWidget);

setLayout(layout);
}

void Window::treeWidgetItemActivated(QTreeWidgetItem * item, int column)
{
QMessageBox::information(this, "", "itemActivated triggered");
}

norobro
22nd November 2011, 18:58
As I read the source code, that is the expected behavior: link (http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/itemviews/qtreeview.cpp#line1840)

Two possible solutions:

Use QTreeWidget::itemDoubleClicked (QTreeWidgetItem * item, int column) which has the same signature.

Subclass QTreeWidget and emit the signal yourself:
void MyTreeWidget::mouseDoubleClickEvent(QMouseEvent *event){
emit activated(indexAt(event->pos()));
QTreeWidget::mouseDoubleClickEvent(event);
}