PDA

View Full Version : DoubleClick functionality in TreeWidget which is uses a delegate when hover over item



torres
24th March 2011, 17:54
I have a treeWidget which displays the items as buttons when hover over them. I use a custom class derived from QStyledItemDelegate to do that.
The problem is that I also need the functionality of doubleClick on an item. SlotItemPressed() never gets called the way it is now. Is there a possibility to do both?




class MyTreeWidget : public QTreeWidget
{
Q_OBJECT

public:
MyTreeWidget(QWidget *parent = NULL);
~MyTreeWidget() {}

void mouseMoveEvent(QMouseEvent *event);

public slots:
void SlotItemPressed(QTreeWidgetItem *item, int index)
{
qDebug() << "slotItemPressed\n";
}

};


Here is the implementation MyTreeWidget.cpp


MyTreeWidget::MyTreeWidget(QWidget *parent) : QTreeWidget(parent)
{
connect( this, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ),
this, SLOT( SlotItemPressed( QTreeWidgetItem*, int ) ) );


setMouseTracking(true);
setEditTriggers(QAbstractItemView::CurrentChanged) ;
}

void MyTreeWidget::mouseMoveEvent(QMouseEvent *event)
{
QTreeWidget::mouseMoveEvent(event);
setCurrentIndex( indexAt(event->pos()));
}

torres
28th March 2011, 18:18
Does anybody have some inputs? Please let me know if my explanation wasn't clear enough. I'm happy to provide more details...

stampede
28th March 2011, 18:32
I've copy-pasted your code and it works with standard QTreeWidgetItems, maybe post your StyledItemDelegate class as well.
Here is code I've tested:


// test.h
#ifndef TEST_H
#define TEST_H
#include <QtGui>
class MyTreeWidget : public QTreeWidget{
Q_OBJECT
public:
MyTreeWidget( QWidget * parent =NULL);
~MyTreeWidget(){}

void mouseMoveEvent(QMouseEvent *event);

public slots:
void SlotItemPressed(QTreeWidgetItem *item, int index)
{
qDebug() << "slotItemPressed" << index;
}
};
#endif

// test.cpp
#include "test.h"
MyTreeWidget::MyTreeWidget(QWidget *parent) : QTreeWidget(parent)
{
connect( this, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ),
this, SLOT( SlotItemPressed( QTreeWidgetItem*, int ) ) );


setMouseTracking(true);
setEditTriggers(QAbstractItemView::CurrentChanged) ;
}

void MyTreeWidget::mouseMoveEvent(QMouseEvent *event)
{
QTreeWidget::mouseMoveEvent(event);
setCurrentIndex( indexAt(event->pos()));
}

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyTreeWidget * w = new MyTreeWidget();
w->addTopLevelItem( new QTreeWidgetItem(QStringList() << "this") );
w->addTopLevelItem( new QTreeWidgetItem(QStringList() << "is") );
w->addTopLevelItem( new QTreeWidgetItem(QStringList() << "test") );

w->show();

return a.exec();
}

torres
28th March 2011, 19:32
Thanks for the reply. The problem is that the delegate is pretty much "in the way" when instantiated while hover over. The underlying QTreeWidgetItem won't get the double click.

Here is the StyleDelegate class:


#pragma once

#include <QStyledItemDelegate>
class QAbstractItemView;

class MyDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
MyDelegate(QAbstractItemView *view, QObject *parent = 0);
~MyDelegate() {}
public:
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const;
private:
QAbstractItemView *view;
};





#include "MyDelegate.h"
#include <QtGui>

MyDelegate::MyDelegate(QAbstractItemView *v, QObject *parent) : QStyledItemDelegate(parent), view(v)
{
}

void MyDelegate::setModelData ( QWidget * editor, QAbstractItemModel * model, const QModelIndex & index ) const
{
if(index.column() == 0)
{
QPushButton *btn = qobject_cast<QPushButton*>(editor);

model->setData(index, btn->text());
} else {
QStyledItemDelegate::setModelData(editor, model, index);
}
}


QWidget * MyDelegate::createEditor ( QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
if(index.column() == 0)
{
QString s1(index.model()->data(index, Qt::EditRole).toString());
QString s2(index.data(Qt::DisplayRole).toString());
QPushButton *btn = new QPushButton(s1, parent);
return btn;
}
return 0;
}



void MyDelegate::setEditorData ( QWidget * editor, const QModelIndex & index ) const
{
QPushButton *btn = qobject_cast<QPushButton*>(editor);
if(!btn)
return;

btn->setText(index.model()->data(index, Qt::EditRole).toString());
}

And in main(), I call:


MyTreeWidget* tree = new MyTreeWidget;

tree->setItemDelegate(new MyDelegate(tree));
tree->setColumnCount(1);

QTreeWidgetItem *item01 = new QTreeWidgetItem(tree);
item01->setFlags(item01->flags() | Qt::ItemIsEditable);
tree->addTopLevelItem(item01);
item01->setText(0, "item01");

QTreeWidgetItem *item02 = new QTreeWidgetItem(tree);
item02->setFlags(item02->flags() | Qt::ItemIsEditable);
tree->addTopLevelItem(item02);
item02->setText(0, "item02");

tree->show();

wysota
28th March 2011, 21:02
There is nothing in your delegate that would prevent signals to be delivered. You probably have double click enabled as one of the edit triggers for your view. Try changing that and it should work.

torres
28th March 2011, 21:34
No, I don't set the only trigger I set is in TreeWidget:


setEditTriggers(QAbstractItemView::CurrentChanged) ;


Any other ideas?

wysota
29th March 2011, 00:01
Please provide a minimal compilable example reproducing the problem.

torres
29th March 2011, 00:38
here is all the code to reproduce the problem: SlotItemPressed() will never be called when double clicking the row:



// MyTreeWidget.h
#pragma once
#include <QTreeWidget>
#include <iostream>
#include <QDebug>
class QWidget;

class MyTreeWidget : public QTreeWidget
{
Q_OBJECT

public:
MyTreeWidget(QWidget *parent = NULL);

void mouseMoveEvent(QMouseEvent *event);

public slots:
void SlotItemPressed(QTreeWidgetItem *item, int index);
};

// MyTreeWidget.cpp
#include "MyTreeWidget.h"
#include <QMouseEvent>
#include <QWidget>

MyTreeWidget::MyTreeWidget(QWidget *parent) : QTreeWidget(parent)
{
connect( this, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ),
this, SLOT( SlotItemPressed( QTreeWidgetItem*, int ) ) );

setMouseTracking(true);
setEditTriggers(QAbstractItemView::CurrentChanged) ;
}

void MyTreeWidget::mouseMoveEvent(QMouseEvent *event)
{
QTreeWidget::mouseMoveEvent(event);
setCurrentIndex( indexAt(event->pos()));
}

void MyTreeWidget::SlotItemPressed(QTreeWidgetItem *item, int index)
{
qDebug() << "I never get here\n";
}

#include "moc_MyTreeWidget.cpp"

// MyDelegate.h
#pragma once

#include <QStyledItemDelegate>
class QAbstractItemView;

class MyDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
MyDelegate(QObject *parent = 0);

public:

QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const;
};

// MyDelegate.cpp

#include "MyDelegate.h"
#include <QtGui>

MyDelegate::MyDelegate(QObject *parent) : QStyledItemDelegate(parent)
{

}

void MyDelegate::setModelData ( QWidget * editor, QAbstractItemModel * model, const QModelIndex & index ) const
{
if(index.column() == 0)
{
QPushButton *btn = qobject_cast<QPushButton*>(editor);

model->setData(index, btn->text());
} else {
QStyledItemDelegate::setModelData(editor, model, index);
}
}

QWidget * MyDelegate::createEditor ( QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
if(index.column() == 0)
{
QString s1(index.model()->data(index, Qt::EditRole).toString());
QString s2(index.data(Qt::DisplayRole).toString());
QPushButton *btn = new QPushButton(s1, parent);
return btn;
}
return 0;
}

void MyDelegate::setEditorData ( QWidget * editor, const QModelIndex & index ) const
{
QPushButton *btn = qobject_cast<QPushButton*>(editor);
if(!btn)
return;

btn->setText(index.model()->data(index, Qt::EditRole).toString());
}

// main.cpp
#include <QtGui/QApplication>
#include "MyDelegate.h"
#include "MyTreeWidget.h"

int main(int argc, char *argv[])
{
QApplication app(argc,argv);

MyTreeWidget* tree = new MyTreeWidget;
tree->setItemDelegate(new MyDelegate(tree));
tree->setColumnCount(1);

QTreeWidgetItem *item01 = new QTreeWidgetItem(tree);
item01->setFlags(item01->flags() | Qt::ItemIsEditable);
tree->addTopLevelItem(item01);
item01->setText(0, "item01");

QTreeWidgetItem *item02 = new QTreeWidgetItem(tree);
item02->setFlags(item02->flags() | Qt::ItemIsEditable);
tree->addTopLevelItem(item02);
item02->setText(0, "item02");
tree->show();
return app.exec();
}

wysota
29th March 2011, 02:48
Works fine for me... Unless of course the editor is opened and intercepts the double click but that's rather obvious.

torres
29th March 2011, 14:56
Works fine for me... Unless of course the editor is opened and intercepts the double click but that's rather obvious.

You mean it works for you and SlotItemPressed() gets called? You mentioned earlier: "There is nothing in your delegate that would prevent signals to be delivered." Does the delegate now intercept the double click or deliver it?

wysota
29th March 2011, 20:37
You mean it works for you and SlotItemPressed() gets called?
Yes.

You mentioned earlier: "There is nothing in your delegate that would prevent signals to be delivered." Does the delegate now intercept the double click or deliver it?
Why would the delegate intercept double click? You'd have to reimplement editorEvent() for that to happen.