PDA

View Full Version : Context Menu on Item Delegate



LynneV
11th February 2010, 22:59
I have an Item Delegate for a TreeView that has several widgets inside a frame for editors at each node. One of the widgets is a QTextEdit that needs to display the 'standard' context menu and also a custom item that unhides a docking window. The docking window is defined at the main window level using the ui designer. I've set the contextmenu policy for the QTextEdit widget to Qt::NoContextMenu, and I get the event in the main window in the ContextMenuEvent. Now, I want to interrogate the event to see if it's from my QTextEdit, and if it is, display the standard context menu with my extra item and if not, display another context menu. I'm stuck on finding out which widget received the right-click. I have tried using :
QTextEdit *txt = qobject_cast<QTextEdit*>( this->childAt( event->globalPos() ) ); and also
QTextEdit *txt = qobject_cast<QTextEdit*>( this->view->childAt( mapFromGlobal( event->globalPos() ) ) ); and several other combinations. But the cast is returning a 0 pointer every time. I need to find out how to use the globalPos() to get the calling widget... but I don't know how to figure it out. Can anyone help? Or suggest a smarter way to approach the issue? Thanks in advance for any assistance.

Coises
12th February 2010, 05:07
I have an Item Delegate for a TreeView that has several widgets inside a frame for editors at each node. One of the widgets is a QTextEdit that needs to display the 'standard' context menu and also a custom item that unhides a docking window. The docking window is defined at the main window level using the ui designer.

It might be better to subclass the QTextEdit, re-implementing QTextEdit::contextMenuEvent as described to add an action. If you’re using signals and slots, you could use one of the QMenu::addAction overloads that take a QString, a QObject address and a the name of a slot to have the new menu item signal an appropriate slot in your main window, which could then show the docking window. Alternatively, you could register a custom QEvent and send it to the main window if the call to QMenu::exec returns the action you added.

Coises
12th February 2010, 05:26
I have tried using :
QTextEdit *txt = qobject_cast<QTextEdit*>( this->childAt( event->globalPos() ) ); and also
QTextEdit *txt = qobject_cast<QTextEdit*>( this->view->childAt( mapFromGlobal( event->globalPos() ) ) ); and several other combinations. But the cast is returning a 0 pointer every time. I need to find out how to use the globalPos() to get the calling widget.

This is only a guess, as I haven’t had occasion to use it... but I think QWidget::childAt returns only the immediate child at the given position, not the topmost descendant at that position. You’d have to iterate, translating the global position to the correct widget coordinates for each descendant and working downward until either you either found a QTextEdit or got 0 back from QWidget::childAt.

But I’m thinking QApplication::widgetAt might give you what you want directly.

LynneV
12th February 2010, 15:52
Thanks so much for the ideas. I actually got about 95% of the way down your first suggestion...but didn't get to the point of being able to have the slot execute the function. I'm going to try both suggestions and see which one works 'best'. Thanks again