QCustomPlot Discussion and Comments

Cannot create Context Menu on Legend Item Return to overview

Hi there,

I'm still new with qcustomplot and trying to understand the interaction functionality. I studied the interaction example and wanted to adapt it a little bit to my needs. I'd like to be able to open a context menu on an item in the legend and/or on any graph in the plot. Unfortunately I couldn't find out yet how to accomplish this.
I understood that in mainwindow.cpp, line 56, this connect statement ...

  connect(ui->customPlot, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequest(QPoint)));


... together with the slot method contextMenuRequest(QPoint) manages the creation of a context menu when the cursor is placed on the legend and then a secondary click is issued. In the above mentioned method the menu is created and populated with actions to move the legend. In case a legend item was at the cursor position when the secondary click was issued I want to add a menu entry which shows a popup window that allow for editing some properties of the respective graph.
So in the contextMenuRequest() method I need to be able to

1. determine which graph's legend item was below the cursor and

2. pass this information to the menu action that brings up the editing window for
the graph.

For step 1. I tried this (in the method contextMenuRequest() at line 234):

    auto legendItem = qobject_cast<QCPAbstractLegendItem*>(itemAt(pos));

But unfortunately the call to itemAt(pos) always returns 0. What am I doing wrong?

i dont know if it still works this way in 2.0, but in the old version, there was a signal for 'legendClick', which you would connect to.

i dont think the 'itemAt' function can return a legendItem, i think it is only plottable items.

I can help you with left button click :)
I think you must enable legend selection with:

setInteraction(QCP::iSelectLegend,true);

Then, connect some slot, for ex:
connect(plot,SIGNAL(selectionChangedByUser()), SLOT(plotSelectionChanged()));

And inside plotSelectionChanged() you must check:
...
if (plot->legend->selectedParts().testFlag(QCPLegend::spItems))
{
    // open menu
    QMenu m;
    ...
    // next line if you want clear selection
    plot->legend->setSelectedParts(QCPLegend::spNone);
}
...

Next code from some old project and it can be incorrect :) Maybe you can find more correct way for it.
Get graph from legend item:

QCPGraph* selectedGraph = 0;
QCPPlottableLegendItem* item = 0;
for (int i = 0; i < plot->graphCount(); i++)
{
    item = plot->legend->itemWithPlottable(plot->graph(i));
    if ((item != 0) && (item->selected()))
        selectedGraph = plot->graph(i);
}

Hi Ian!

I tried out the legendClick signal but with no success. This signal seems to be emitted only on a primary mouse button (normally the left mouse button) click. When attempting to open a context menu a secondary mouse click is performed.

Hi raandoom!

Just tried your proposal. Unfortunately it doesn't work for me. Seems to me we have a little misunderstanding: To open a context menu one has to perform a secondary mouse click. For right handed mouse usage this means a click with the right(!) mouse button. The signal you proposed ...

selectionChangedByUser
... seems to be emitted on a primary (left button) mouse click only.

I made some more experiments in between and found a solution for my problem:

In the slot method given in the connect statement for the signal customContextMenuRequested(QPoint) I can use not only the method
itemAt(QPoint). There exist other methods to determine the item at the cursor position:

layoutElementAt(QPoint) -- This method returns the QCPPlottableLegendItem or a QCPTextElement or a QCPAxisRectat the cursor position.

plottableAt(QPoint) -- This returns a graph at the cursor position. Using these methods in my slot method I can easily determine the kind of object under the cursor and create the proper context menu entries and provide the necessary data.