0

I want to generate the right click menu from the entry of a QTreeView. Currently I tried this, but I don't want the whole treeView to generate the right click and then me to filter the position on which the mouse is. I want that the signal to be generated from the entry.

connect(mtreeView, SIGNAL(customContextMenuRequested(const QPoint&)),
        this, SLOT(showContextMenu(const QPoint&)));

Thanks!

yonutix
  • 1,964
  • 1
  • 22
  • 51
  • 3
    What's the problem? You can use `QAbstractItemView::indexAt (const QPoint &point)` in your slot to get the item that requested a menu. – hank May 27 '15 at 06:51
  • Ok, but is it possible to generate the signal from the entry element? – yonutix May 27 '15 at 06:57
  • I would also recommend using `QAbstractItemView::indexAt (const QPoint &point)` like @hank said. But if you really want to get a signal of the item itself, you could use a `QTreeWidget` instead of `QTreeView`. To get the signal you could set `QPushButton` or `QToolButton` as item widget with a call of `QTreeWidget::setItemWidget` and connect to the button's clicked signal. – tomvodi May 27 '15 at 07:20
  • possible duplicate of [Adding a right-click menu for specific items in QTreeView](http://stackoverflow.com/questions/22198427/adding-a-right-click-menu-for-specific-items-in-qtreeview) – tomvodi May 27 '15 at 07:24

3 Answers3

8

Method 1

It is better to use the ContextMenuEvent rather than MouseReleaseEvent as it is a more portable way to trigger the context menu, will support accessibility on certain platforms, etc... The right click is not the only way to open a context menu.

If you do not want to subclass QTreeView , install an event handler from the main window:

ui->myTreeView->installEventFilter(this);

Then handle the event in the main window filterEvent

bool MainWindow::eventFilter(QObject *target, QEvent *event)
{
    if (target == ui->myTreeView)
    {
        QContextMenuEvent* m = dynamic_cast<QContextMenuEvent*>(event);
        if (event->type() == QEvent::ContextMenu && e!=0)
        {
                //Create context menu here
                return true;
        }
    }
    return false;
}

Method 2

Change the context menu mode to a signal:

ui->myTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->myTreeView, SIGNAL(customContextMenuRequested(QPoint)),
    this, SLOT(treeCustomMenu(QPoint)));

Then implement your slot:

void MainWindow::treeCustomMenu(const QPoint & pos)
{
    //Implement your menu here using myTreeView->itemAt(pos);
}
galinette
  • 8,896
  • 2
  • 36
  • 87
3

What I do is to override mouseReleaseEvent and check manually.

void MyTreeView::mouseReleaseEvent(QMouseEvent *e) {
    if (e->button() == Qt::RightButton) {
        QTreeWidgetItem *item = itemAt(e->pos());
        if (item) {
            QMenu m;
            m.addAction("hello");
            m.addAction("world");
            QAction *selected = m.exec(mapToGlobal(e->pos()));
            if (selected) {
                qDebug() << "selected" << selected->text();
            }
        }
    } else {
        QTreeView::mouseReleaseEvent(e);
    }
}
Ziming Song
  • 1,176
  • 1
  • 9
  • 22
  • mouseReleaseEvent is linked to what signal? – yonutix May 27 '15 at 07:00
  • It's not a slot, but a protected virtual function inherited from `QWidget`. It gets called automatically everytime user releases mouse button. – Ziming Song May 27 '15 at 07:03
  • This is helpful for actually showing how to create and use the *menu*, but as galinette notes, please use `ContextMenuEvent` rather than `MouseReleaseEvent` – Matthew Feb 01 '19 at 18:39
0

What you mean by the entry is not represented by a QObject in Qt. Only the item model is a QObject, but the individual tree nodes are not QObjects in Qt item/view system.

Therefore, they cannot emit any signal

galinette
  • 8,896
  • 2
  • 36
  • 87