Catch (imitate) mouse event on tree widget item in QTreeWidget
-
In tree widget I have following signal connected:
connect(mTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*, int)), SLOT(onItemClicked(QTreeWidgetItem*, int)));
where
onItemClicked()
slot is following:void WidgetBox::onItemClicked(QTreeWidgetItem *item, int ) { int index = getPageIndex(item); setCurrentIndex(index); } int WidgetBox::getPageIndex(QTreeWidgetItem *item) { if (!item) return -1; QTreeWidgetItem *parent = item->parent(); if(parent) // Parent is top level item { return mTreeWidget->indexOfTopLevelItem(parent); } else // Current item is top level { return item->treeWidget()->indexOfTopLevelItem(item); } } void WidgetBox::setCurrentIndex(int index) { if (index != currentIndex() && checkIndex(index)) { mTreeWidget->setCurrentItem(mTreeWidget->topLevelItem(index)); emit currentIndexChanged(index); } }
However I can't catch
itemClicked()
signal andonItemClicked()
never executed because top level items has push button widget (set withsetItemWidget()
method) which intercepts mouse event and child items contain container widgets which may have any widget combinations in them.Is there a good method here to invoke this
itemClicked()
signal for both top level and child items of tree widget?- installEventFilter() for all widgets found in an item by something like following:<br>
QList<QWidget *> widgets = parentWidget.findChildren<QWidget *>();
? - Or establish mouse event propagation somehow?
- QCoreApplication::postEvent()?
How to organize such process better so all widgets process mouse event as they need to and TreeWidget issue
SIGNAL(itemClicked())
as well?Full sources to reproduce: https://github.com/akontsevich/WidgetBox
Possible solution:
Created event filter like this:
class PageEventFilter : public QObject { Q_OBJECT public: PageEventFilter(QObject *parent, QTreeWidgetItem *item); protected: bool eventFilter(QObject *obj, QEvent *event); private: QTreeWidgetItem *mItem; }; bool PageEventFilter::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::MouseButtonPress) { // Emitate mouse event for parent QTreeWidget QMouseEvent *oldEvent = (QMouseEvent *)event; QRect itemRect = mItem->treeWidget()->visualItemRect(mItem); QPointF mousePos(itemRect.x() + 1, itemRect.y() + 1); QMouseEvent *newEvent = new QMouseEvent(oldEvent->type(), mousePos, oldEvent->button(), oldEvent->buttons(), oldEvent->modifiers()); QCoreApplication::postEvent(mItem->treeWidget(), newEvent); return false; // Sent event to the object (do not filter it) } else { // standard event processing return QObject::eventFilter(obj, event); } }
Install it to a button in tree widget item. It creates and sends (imitates) mouse event to tree widget, however tree widget still does not send itemClicked(QTreeWidgetItem*, int) signal. What is the problem could be? Wrong mouse pos? Tried to send event to viewport() - no luck as well. Any way to solve this?
- installEventFilter() for all widgets found in an item by something like following:<br>
-
-
So solution is simple and following - just re-send
void itemClicked(QTreeWidgetItem *item, int column);
signal inPageEventFilter
:PageEventFilter::PageEventFilter(QObject *parent, QTreeWidgetItem *item) : QObject(parent) , mItem(item) { connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)), mItem->treeWidget(), SIGNAL(itemClicked(QTreeWidgetItem*,int))); } bool PageEventFilter::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::MouseButtonPress) { // Resend signal to QTreeWidget emit itemClicked(mItem, 0); return false; // Send event to the object (do not filter it) } else { // standard event processing return QObject::eventFilter(obj, event); } }
P.S. Will leave previous answer as well if somebody needs code or idea.