42

I'm writing a Qt desktop application in c++ with Qt Creator.

I declared in my main window a treeView, and a compatible model.

Now, I would like to have a right-click menu for the tree item. Not for all of the items, but for a part of them, for example: for the tree elements with an even index.

I tried adding a simple context menu with the following code:

in the .h file:

QStandardItemModel* model;
QMenu* contextMenu;
QAction* uninstallAction;
private slots:
    void uninstallAppletClickedSlot();

and in the .cpp file:

in the constructor:

ui->treeView->setModel(model);
contextMenu = new QMenu(ui->treeView);
ui->treeView->setContextMenuPolicy(Qt::ActionsContextMenu);
uninstallAction = new QAction("Uninstall TA",contextMenu);
ui->treeView->addAction(uninstallAction);
connect(uninstallAction, SIGNAL(triggered()), this, SLOT(uninstallAppletClickedSlot()));

and a slot:

void MainWindow::uninstallAppletClickedSlot()
{

}

this code gives me a context menu with the wanted action, but do you have any idea how can I add this action only for the QStandardItems with the even indexes??

BTW, I'm adding items to the treeView by the following way:

void MainWindow::AddItem(QString name)
{
QStandardItem *parentItem = model->invisibleRootItem();
QStandardItem *app = new QStandardItem(name);
parentItem->appendRow(app);
}

I googled a lot, but found nothing :(

thanks in advance!

user1835297
  • 1,059
  • 2
  • 12
  • 24

1 Answers1

64

I would do this in the following way:

Configure the context menu

ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->treeView, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onCustomContextMenu(const QPoint &)));

Implement the context menu handling

void MainWindow::onCustomContextMenu(const QPoint &point)
{
    QModelIndex index = ui->treeView->indexAt(point);
    if (index.isValid() && index.row() % 2 == 0) {
        contextMenu->exec(ui->treeView->viewport()->mapToGlobal(point));
    }    
}
dom0
  • 7,356
  • 3
  • 28
  • 50
vahancho
  • 20,808
  • 3
  • 47
  • 55
  • thanks, @vahancho, I followed your instructions, but the result is: once I press on a row with an even index - I can see a little point appears in the form, and once I press on a row with odd index - nothing appears. this is good, but the menu doesn't appear at all! i.e, the exec() function doesn't do the wanted action. Do you have any more idea? thanks a lot! – user1835297 Mar 05 '14 at 14:42
  • 2
    @user1835297, actually you have to construct your menu beforehand. I did not include that code in my answer. You simply need to: `contextMenu->addAction("Uninstall TA", this, SLOT(uninstallAppletClickedSlot());` or so. – vahancho Mar 05 '14 at 14:51
  • 2
    Use `ui->treeview->viewport()->mapToGlobal(point)` instead, if you experience a strange offset of the menu. – Sebastian Wagner Apr 22 '17 at 20:12
  • 1
    That's because item views are QAbstractScrollareas. Thus "The exception to this rule is QAbstractScrollArea and its subclasses that map the context menu event to coordinates of the viewport()." from the docs applies. – dom0 Aug 11 '18 at 20:58