Context menus for a single column
-
I am trying to implement a context menu for a specific column. In the code attached it works for all columns. Is there a way that I can have multiple context menu's in a single view. Below is a sample of the code I am working with.
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QTableView>
#include <QStandardItemModel>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{
Q_OBJECTpublic:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();public slots:
void customMenuRequested(QPoint pos);
void customHeaderMenuRequested(QPoint pos);private:
Ui::MainWindow *ui;
QTableView *table;
QStandardItemModel *model;
};#endif // MAINWINDOW_H
#include "mainwindow.h"
#include <QApplication>int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QVBoxLayout>MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
model=new QStandardItemModel(10,10,this);ui->setupUi(this); QVBoxLayout *l=new QVBoxLayout(this); table=new QTableView(this); table->setModel(model); table->setContextMenuPolicy(Qt::CustomContextMenu); connect(table, SIGNAL(customContextMenuRequested(QPoint)), SLOT(customMenuRequested(QPoint))); table->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); connect(table->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(customHeaderMenuRequested(QPoint))); ui->tableView->setModel(model); ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(customMenuRequested(QPoint))); ui->tableView->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->tableView->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(customHeaderMenuRequested(QPoint))); l->addWidget(table);
}
MainWindow::~MainWindow()
{
delete ui;
}void MainWindow::customMenuRequested(QPoint pos){
QModelIndex index=table->indexAt(pos);QMenu *menu=new QMenu(this); menu->addAction(new QAction("Action 1", this)); menu->addAction(new QAction("Action 2", this)); menu->addAction(new QAction("Action 3", this)); menu->popup(table->viewport()->mapToGlobal(pos));
}
void MainWindow::customHeaderMenuRequested(QPoint pos){
int column=table->horizontalHeader()->logicalIndexAt(pos);QMenu *menu=new QMenu(this); menu->addAction(new QAction("Header Action 1", this)); menu->addAction(new QAction("Header Action 2", this)); menu->addAction(new QAction("Header Action 3", this)); menu->popup(table->horizontalHeader()->viewport()->mapToGlobal(pos));
}
END MainWIndow.cppMainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QTableView" name="tableView">
<property name="geometry">
<rect>
<x>110</x>
<y>30</y>
<width>256</width>
<height>192</height>
</rect>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>30</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>End Of Ui
This was taken from examples that I had found online and I modified. They work great but not for a single column context menu.
I'm sure it must be a simple answer.
jdc -
I am trying to implement a context menu for a specific column. In the code attached it works for all columns. Is there a way that I can have multiple context menu's in a single view. Below is a sample of the code I am working with.
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QTableView>
#include <QStandardItemModel>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{
Q_OBJECTpublic:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();public slots:
void customMenuRequested(QPoint pos);
void customHeaderMenuRequested(QPoint pos);private:
Ui::MainWindow *ui;
QTableView *table;
QStandardItemModel *model;
};#endif // MAINWINDOW_H
#include "mainwindow.h"
#include <QApplication>int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QVBoxLayout>MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
model=new QStandardItemModel(10,10,this);ui->setupUi(this); QVBoxLayout *l=new QVBoxLayout(this); table=new QTableView(this); table->setModel(model); table->setContextMenuPolicy(Qt::CustomContextMenu); connect(table, SIGNAL(customContextMenuRequested(QPoint)), SLOT(customMenuRequested(QPoint))); table->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); connect(table->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(customHeaderMenuRequested(QPoint))); ui->tableView->setModel(model); ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(customMenuRequested(QPoint))); ui->tableView->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->tableView->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(customHeaderMenuRequested(QPoint))); l->addWidget(table);
}
MainWindow::~MainWindow()
{
delete ui;
}void MainWindow::customMenuRequested(QPoint pos){
QModelIndex index=table->indexAt(pos);QMenu *menu=new QMenu(this); menu->addAction(new QAction("Action 1", this)); menu->addAction(new QAction("Action 2", this)); menu->addAction(new QAction("Action 3", this)); menu->popup(table->viewport()->mapToGlobal(pos));
}
void MainWindow::customHeaderMenuRequested(QPoint pos){
int column=table->horizontalHeader()->logicalIndexAt(pos);QMenu *menu=new QMenu(this); menu->addAction(new QAction("Header Action 1", this)); menu->addAction(new QAction("Header Action 2", this)); menu->addAction(new QAction("Header Action 3", this)); menu->popup(table->horizontalHeader()->viewport()->mapToGlobal(pos));
}
END MainWIndow.cppMainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QTableView" name="tableView">
<property name="geometry">
<rect>
<x>110</x>
<y>30</y>
<width>256</width>
<height>192</height>
</rect>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>30</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>End Of Ui
This was taken from examples that I had found online and I modified. They work great but not for a single column context menu.
I'm sure it must be a simple answer.
jdcPlease properly format your code with code tags (
</>
button or ``` in front and at the end for the code) so someone else can read your code.When you want the context menu only for one column then check the modelIndex return from table->indexAt() to match your desired column.
-
Please properly format your code with code tags (
</>
button or ``` in front and at the end for the code) so someone else can read your code.When you want the context menu only for one column then check the modelIndex return from table->indexAt() to match your desired column.
@Christian-Ehrlicher Thanks for the feedback I will try to do better with the code display I have not had much experiance with this forum.
I will try your suggestion.
Thanks jdc -
-
This post is deleted!
-
Your program has memory leak, in customMenuRequested() every time you creating new object of QMenu on heap and not deleting it. I have two ways how to fix it:
-
Create QMenu object not on heap (by new) but on stack, like this
QMenu menu(this)
.
Than execute it bymenu.exec((table->viewport()->mapToGlobal(pos))
. -
Create
QScopedPointer<QMenu> menu
as yourMainWindow
field.
And change yourcustomMenuRequested(QPoint pos)
to this:void MainWindow::customMenuRequested(QPoint pos) { menu.reset(new QMenu(this)); menu->addAction(new QAction("Action 1", this)); menu->addAction(new QAction("Action 2", this)); menu->addAction(new QAction("Action 3", this)); menu->popup(table->viewport()->mapToGlobal(pos)); }
Sorry for my bad english.
-