How to identify when the current tab is changing in a QTabWidget? - qt

I'm using a QTabWidget and I need a way to handle the change of the current tab before it actually happens, and possibly cancel it if certain conditions are met. The QTabWidget::currentChanged signal is received after the current tab has changed, but is there a QTabWidget::currentChanging signal or another way to achieve the behavior I need?

In my case, I connect SIGNAL and SLOT like this:
//check if user clicked at a tab
connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabSelected()));
and in tabSelected() function, I check current Tab Index:
void MainWindow::tabSelected(){
if(ui->tabWidget->currentIndex()==0){
// Do something here when user clicked at tab1
}
if(ui->tabWidget->currentIndex()==3){
// Do something here when user clicked at tab4
}
}

This is how I solved it
void MainWindow::on_tabWidget_currentChanged(int index)
{
if (lockTabs) ui->tabWidget->setCurrentIndex(lockedTab);
}
On click of a button, I set lockTabs to true and save the current tab index to lockedTab (int). No matter what tab you click it will just throw you back to the locked tab.
I do agree with the first comment that disabling tabs is the better way tho. This is my solution for disabling tabs:
void MainWindow::lockTabs(int except){
for (int i=0; i<ui->tabWidget->count(); i++) {
if (i!=except) ui->tabWidget->setTabEnabled(i, false);
}
}
void MainWindow::unlockTabs() {
for (int i=0; i<ui->tabWidget->count(); i++) {
ui->tabWidget->setTabEnabled(i, true);
}
}

In your header, declare:
QWidget *saveTab
Create a routine tabChanged have the slot for the currentChanged() signal. Then:
void pkgName::tabChanged
//"ask your question"
if "bad reply"
// This is where you'll "set back to your old tab"
ui->tabWidget->setCurrentWidget(savedWidget)
end if
savedWidget = ui->tabWidget-> getCurrentWidget()
// Process

Using a regular QTabWidget and flipping back to previous tab after currentChanged was emitted if change was forbidden does not look right for user as the new tab is made visible before the previous one is re-selected, this is due to QTabWidget informing the tab "changed", not "is about to change".
One option is to create your own QTabWidget. Thanks to QTabBar, this is pretty obvious.
You'll also need to create QTabWidget like function to use it "like" a QTabWidget, but there's not so many function you'll need.
Here is an example of QTabWidget like class with a aboutToChangeTab signal being emitted informing that tab is about to be changed, one may set allowed to false to forbid tab change.
#pragma once
#include <QWidget>
class QTabBar;
class QStackedWidget;
class SmartTabWidget : public QWidget
{
Q_OBJECT
typedef QWidget baseClass;
public:
SmartTabWidget( QWidget* parent );
int addTab(QWidget* page, const QString& label);
int addTab(QWidget* page, const QIcon& icon, const QString& label);
int currentIndex() const;
QWidget* widget( int index );
signals:
void aboutToChangeTab( QWidget* curTab, QWidget* nextTab, bool* allowed );
private slots:
void tryToChangeTab( int index );
private:
QTabBar* m_tab;
QStackedWidget* m_stack;
};
And:
#include "smart_tab_widget.h"
#include <QTabBar>
#include <QStackedWidget>
#include <QVBoxLayout>
#include <QIcon>
SmartTabWidget::SmartTabWidget( QWidget* widget ) :
baseClass( widget )
{
new QVBoxLayout( this );
layout()->setContentsMargins( 0,0,0,0 );
layout()->addWidget( m_tab = new QTabBar(this) );
layout()->addWidget( m_stack = new QStackedWidget(this) );
connect(m_tab, SIGNAL(currentChanged(int)), this, SLOT(tryToChangeTab(int)));
}
int SmartTabWidget::addTab(QWidget* page, const QString& label)
{
return addTab( page, QIcon(), label );
}
int SmartTabWidget::addTab(QWidget* page, const QIcon& icon, const QString & label)
{
m_stack->addWidget( page );
int index = m_tab->addTab( icon, label );
assert( m_stack->count() == index+1 );
return index;
}
int SmartTabWidget::currentIndex() const
{
return m_tab->currentIndex();
}
QWidget* SmartTabWidget::widget( int index )
{
return m_stack->widget( index );
}
void SmartTabWidget::tryToChangeTab( int index )
{
int currentIndex = m_stack->currentIndex();
bool canChange = true;
emit aboutToChangeTab( m_stack->widget( currentIndex ),
m_stack->widget( index ),
&canChange );
if ( canChange )
{
m_stack->setCurrentIndex( index );
}
else
{
// prevent this function to be called again
bool blocked = m_tab->blockSignals( true );
// unselect requested tab as change is not allowed
m_tab->setCurrentIndex( currentIndex );
m_tab->blockSignals( blocked );
}
}
One can connect aboutToChangeTab to a slot (allowTabChange) and do something like:
void MyWidget::allowTabChange( QWidget* curTab, QWidget* nextTab, bool* allowed )
{
if ( !canChange( curTab, nextTab ) )
*allowed = false;
}

There is a simple solution with event filters that doesn't require to subclass QTabWidget. In my case I needed to disable switching to a particular tab
ui->tabWidget->tabBar()->installEventFilter(this);
then:
bool MainWindow::eventFilter(QObject* watched, QEvent* event)
{
if(watched == ui->tabWidget->tabBar())
{
if(event->type() == QEvent::MouseButtonPress)// || event->type() == QEvent::MouseButtonRelease)
{
auto pos = dynamic_cast<QMouseEvent*>(event)->pos();
auto index = ui->tabWidget->tabBar()->tabAt(pos);
if(ui->tabWidget->widget(index) == ui->addButtonTab)
return true; // cancell event
}
}
return QMainWindow::eventFilter(watched, event);
}
At the stage of mouse click it is possible to retrieve index of a currently selected tab and prepare it for being switched(or cancel switching as done in my example).

Related

Office like QToolButton

I currently try to make a QToolButton looks like equivalent in Office.
It should look like this:
I know I can access menu button with QToolButton::menu-button, but QToolButton::menu-button:hover is same as QToolButton:hover so I can't differ between both and I can't set a border just for QToolButton::menu-button. Any idea?
You can create something like split button.
class SplitButton : public QPushButton
{
Q_OBJECT
public:
explicit SplitButton(QWidget *parent = 0);
void setMenu(QMenu* menu);
protected:
void resizeEvent ( QResizeEvent * );
void mousePressEvent ( QMouseEvent * );
private:
QFrame* line;
};
Added opportunity to insert menu by setMenu() method. QFrame is needed for separating button and popup menu.
At constructor just initialize base class:
#include <QFrame>
#include <QMenu>
#include <QResizeEvent>
SplitButton::SplitButton(QWidget *parent):
QPushButton(parent)
{
}
Popup menu will be added like this:
void SplitButton::setMenu( QMenu* menu )
{
if (menu) {
line = new QFrame(this);
line->setFrameShape(QFrame::VLine);
line->setFrameShadow(QFrame::Sunken);
QPushButton::setMenu(menu);
connect(menu, &QMenu::triggered, [=](QAction *act) {
setText(act->text());
});
}
}
As you can see we used QPushButton::setMenu() method and connect menu triggered signal to slot, realized with labda, so you need include c++11 compatibility.
After we need to override resize, mousePress and keyPressed events. As minimal exmaple i done second ones.
void SplitButton::resizeEvent ( QResizeEvent * event )
{
if (menu()) {
int width = event->size().width();
int height = event->size().height();
line->setGeometry(QRect(width - 18, 4, 3, height - 8));
}
}
At resize event if menu is available we add frame by offset for pseudo-button.
void SplitButton::mousePressEvent( QMouseEvent * event )
{
if (menu()) {
if ( width()-event->x() <= 15 )
showMenu();
else
setDown(true);
} else {
QPushButton::mousePressEvent(event);
}
}
For mousePress event we just select what we want to do: show menu or push button.
Usage:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), m_file(QString())
{
setupUi(this);
SplitButton *split = new SplitButton;
split->setText("B");
QMenu *menu = new QMenu;
menu->addAction("Y");
menu->addAction("B");
menu->addAction("U");
split->setMenu(menu);
split->setCheckable(true);
Ui::MainWindow::mainToolBar->addWidget(split);
}
And you can set button chechable for Office-like effects.
It's just one of possible ways to realize this, I hope it will be helpful for you.
It look like on screen for me:
Of cource, it is not final result, you need repaint it like you want or use styles for flat-style.

How do I implement the ability to edit a QTableWidget's vertical and horizontal header text in-line from the GUI instead of programmatically?

I have a QTableWidget that is displayed in the user interface that I can add and remove rows and columns using buttons. The problem is, when I add a row or column, I can change the data in the actual cells, but I cannot name the row or column. The name is simply a static number.
Is there a way to allow the user of my program to perhaps double-click on a row/column header and edit the name in-line or something similar?
Thanks.
As far as I know there is no built-in way to do this. However this can be implemented manually. The main idea of the following code is to detect double clicks on header items, place QLineEdit over them and save edited text once it loses focus. The example is based on Qt generated Designer Form Class with a table named ui->tableWidget which can be either QTableWidget or QTableView.
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
QLineEdit* header_editor;
int editor_index;
bool eventFilter(QObject*, QEvent*);
};
Source:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
header_editor = 0;
ui->setupUi(this);
ui->tableWidget->horizontalHeader()->viewport()->installEventFilter(this);
ui->tableWidget->verticalHeader()->viewport()->installEventFilter(this);
}
MainWindow::~MainWindow() {
delete ui;
}
bool MainWindow::eventFilter(QObject* object, QEvent* event) {
if ((object == ui->tableWidget->horizontalHeader()->viewport() ||
object == ui->tableWidget->verticalHeader()->viewport()) &&
event->type() == QEvent::MouseButtonDblClick) {
if (header_editor) { //delete previous editor just in case
header_editor->deleteLater();
header_editor = 0;
}
QMouseEvent* e = static_cast<QMouseEvent*>(event);
QHeaderView* header = static_cast<QHeaderView*>(object->parent());
int mouse_pos = header->orientation() == Qt::Horizontal ? e->x() : e->y();
int logical_index = header->logicalIndex(header->visualIndexAt(mouse_pos));
if (logical_index >= 0) { // if mouse is over an item
QRect rect; // line edit rect in header's viewport's coordinates
if (header->orientation() == Qt::Horizontal) {
rect.setLeft(header->sectionPosition(logical_index));
rect.setWidth(header->sectionSize(logical_index));
rect.setTop(0);
rect.setHeight(header->height());
} else {
rect.setTop(header->sectionPosition(logical_index));
rect.setHeight(header->sectionSize(logical_index));
rect.setLeft(0);
rect.setWidth(header->width());
}
rect.adjust(1, 1, -1, -1);
header_editor = new QLineEdit(header->viewport());
header_editor->move(rect.topLeft());
header_editor->resize(rect.size());
header_editor->setFrame(false);
//get current item text
QString text = header->model()->
headerData(logical_index, header->orientation()).toString();
header_editor->setText(text);
header_editor->setFocus();
editor_index = logical_index; //save for future use
header_editor->installEventFilter(this); //catch focus out event
//if user presses Enter it should close editor
connect(header_editor, SIGNAL(returnPressed()),
ui->tableWidget, SLOT(setFocus()));
header_editor->show();
}
return true; // filter out event
} else if (object == header_editor && event->type() == QEvent::FocusOut) {
QHeaderView* header = static_cast<QHeaderView*>(
header_editor->parentWidget()->parentWidget());
//save item text
header->model()->setHeaderData(editor_index, header->orientation(),
header_editor->text());
header_editor->deleteLater(); //safely delete editor
header_editor = 0;
}
return false;
}
Downsides of this method are that it's hacky, things go bad when headers are resized or table is scrolled. It's just an example that can be improved.
I have a feeling there has to be a simpler way. But Qt headers ignore Qt::ItemIsEditable flag and can't use delegates.

Need QGraphicsScene signal or event for _after_ change

I use QGraphicsScene of the Qt framework. Inside the scene I have some QGraphicsItems which the user can select and move.
I would like to have an info label where the current x and y coordinate of the currently moved selection (can consist of many items) is displayed.
I have tried with the signal changed of QGraphicsScene. But it is fired before the x() and y() property of the items is set to the new values. So the labels always show the second-to-last coordinates. If one moves the mouse slowly, the display is not very wrong. But with fast moves and sudden stops, the labels are wrong. I need a signal that is fired after the scene hast changed.
I have also tried to override the itemChange method of QGraphicsItem. But it is the same. It is fired before the change. (The new coordinates are inside the parameters of this method, but I need the new coordinates of all selected items at once)
I have also tried to override the mouseMove events of QGraphicsScene and of QGraphicsView but they, too, are before the new coordinates are set.
I did a test: I used a oneshot timer so that the labels are updated 100 ms after the signals. Then everything works fine. But a timer is no solution for me.
What can I do?
Make all items un-moveable and handle everything by my own?
QGraphicsItem::itemChange() is the correct approach, you were probably just checking the wrong flag. Something like this should work fine:
QVariant::myGraphicsItem( GraphicsItemChange change, const QVariant &value )
{
if( change == QGraphicsItem::ItemPositionHasChanged )
{
// ...
}
}
Note the use of QGraphicsItem::ItemPositionHasChanged rather than QGraphicsItem::ItemPositionChange, the former is called after the position changes rather than before.
The solution is to combine various things that you're already doing. Instrument itemChange, looking for and count the items with updated geometry. Once you've counted as many items as there are in the current selection, fire off a signal that will have everything ready for updating your status. Make sure you've set the QGraphicsItem::ItemSendsGeometryChanges flag on all your items!
This code was edited to remove the lag inherent in using a zero-timer approach. Below is a sscce that demonstrates it.
You create circles of random radius by clicking in the window. The selection is toggled with Ctrl-click or ⌘-click. When you move the items, a centroid diamond follows the centroid of the selected group. This gives a visual confirmation that the code does indeed work. When the selection is empty, the centroid is not displayed.
I've gratuitously added code to show how to leverage Qt's property system so that the items can be generic and leverage the notifier property of a scene if it has one. In its absence, the items simply don't notify, and that's it.
// https://github.com/KubaO/stackoverflown/tree/master/questions/scenemod-11232425
#include <QtWidgets>
const char kNotifier[] = "notifier";
class Notifier : public QObject
{
Q_OBJECT
int m_count = {};
public:
int count() const { return m_count; }
void inc() { m_count ++; }
void notify() { m_count = {}; emit notification(); }
Q_SIGNAL void notification();
};
typedef QPointer<Notifier> NotifierPointer;
Q_DECLARE_METATYPE(NotifierPointer)
template <typename T> class NotifyingItem : public T
{
protected:
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override {
QVariant v;
if (change == T::ItemPositionHasChanged &&
this->scene() &&
(v=this->scene()->property(kNotifier)).isValid())
{
auto notifier = v.value<NotifierPointer>();
notifier->inc();
if (notifier->count() >= this->scene()->selectedItems().count()) {
notifier->notify();
}
}
return T::itemChange(change, value);
}
};
// Note that all you need to make Circle a notifying item is to derive from
// NotifyingItem<basetype>.
class Circle : public NotifyingItem<QGraphicsEllipseItem>
{
QBrush m_brush;
public:
Circle(const QPointF & c) : m_brush(Qt::lightGray) {
const qreal r = 10.0 + (50.0*qrand())/RAND_MAX;
setRect({-r, -r, 2.0*r, 2.0*r});
setPos(c);
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable |
QGraphicsItem::ItemSendsGeometryChanges);
setPen({Qt::red});
setBrush(m_brush);
}
};
class View : public QGraphicsView
{
Q_OBJECT
QGraphicsScene scene;
QGraphicsSimpleTextItem text;
QGraphicsRectItem centroid{-5, -5, 10, 10};
Notifier notifier;
int deltaCounter = {};
public:
explicit View(QWidget *parent = {});
protected:
Q_SLOT void gotUpdates();
void mousePressEvent(QMouseEvent *event) override;
};
View::View(QWidget *parent) : QGraphicsView(parent)
{
centroid.hide();
centroid.setRotation(45.0);
centroid.setPen({Qt::blue});
centroid.setZValue(2);
scene.addItem(&centroid);
text.setPos(5, 470);
text.setZValue(1);
scene.addItem(&text);
setRenderHint(QPainter::Antialiasing);
setScene(&scene);
setSceneRect(0,0,500,500);
scene.setProperty(kNotifier, QVariant::fromValue(NotifierPointer(&notifier)));
connect(&notifier, &Notifier::notification, this, &View::gotUpdates);
connect(&scene, &QGraphicsScene::selectionChanged, &notifier, &Notifier::notification);
}
void View::gotUpdates()
{
if (scene.selectedItems().isEmpty()) {
centroid.hide();
return;
}
centroid.show();
QPointF centroid;
qreal area = {};
for (auto item : scene.selectedItems()) {
const QRectF r = item->boundingRect();
const qreal a = r.width() * r.height();
centroid += item->pos() * a;
area += a;
}
if (area > 0) centroid /= area;
auto st = QStringLiteral("delta #%1 with %2 items, centroid at %3, %4")
.arg(deltaCounter++).arg(scene.selectedItems().count())
.arg(centroid.x(), 0, 'f', 1).arg(centroid.y(), 0, 'f', 1);
this->centroid.setPos(centroid);
text.setText(st);
}
void View::mousePressEvent(QMouseEvent *event)
{
const auto center = mapToScene(event->pos());
if (! scene.itemAt(center, {})) scene.addItem(new Circle{center});
QGraphicsView::mousePressEvent(event);
}
int main(int argc, char *argv[])
{
QApplication app{argc, argv};
View v;
v.show();
return app.exec();
}
#include "main.moc"

mouse press over event and qtabwidget

need that when a mouse ( with press button ) is on top of tab, it gets activated.
How is it possible.
You can intercept the mouseMoveEvent event from the QTabBar.
Edit: How To
To intercept it Qt offers you a great functionalities. You can install an event filter on a widget you have created so it will be able to get filtered event of its child widgets. See documentation about the installEventFilter function.
Just create your own EventFilter.
// TabBarEventHandler
class TabBarEventHandler : public QObject
{
public:
explicit TabBarEventHandler( QTabWidget * tabWidget );
virtual ~TabBarEventHandler();
void Initialize();
protected:
QTabWidget * mTabWidget;
virtual bool eventFilter( QObject* obj, QEvent* event ) override;
};
// TabBarEventHandler
TabBarEventHandler::TabBarEventHandler( TabBar * tabWidget )
: mTabWidget( tabWidget )
{
}
TabBarEventHandler::~TabBarEventHandler()
{
mTabWidget->tabBar()->removeEventFilter( this );
}
void TabBarEventHandler::Initialize()
{
mTabWidget->tabBar()->installEventFilter( this );
}
bool TabBarEventHandler::eventFilter(QObject* obj, QEvent* event)
{
qDebug() << event->type();
return QObject::eventFilter( obj, event );
}
void TabBarEventHandler::timerEvent(QTimerEvent* event)
{
}
And in your widget:
MyTabWidget::MyTabWidget( QWidget * parent ) : QTabWidget( parent )
{
mEventHandler = new TabBarEventHandler( this );
mEventHandler->Initialize();
}
MyTabWidget::~MyTabWidget()
{
delete mEventHandler;
}
The debug output:
QEvent::Type(HoverMove) QEvent::Type(HoverMove)
QEvent::Type(MouseButtonPress) QEvent::Type(InputMethodQuery)
QEvent::Type(InputMethodQuery) QEvent::Type(InputMethodQuery)
QEvent::Type(Paint) QEvent::Type(Paint)
QEvent::Type(MouseButtonRelease) QEvent::Type(HoverMove)
QEvent::Type(HoverMove) QEvent::Type(Leave)

Determine if QTableView has an open editor

Is there any way to determine if a QTableView has an open editor in the current cell? I need to handle the following situation:
A user double-clicks a cell and edits the data, but leaves the cell in the "edit" state.
On another part of the UI, an action is taken that changes the selected row of the underlying model.
Back on my view, I want to determine if the newly selected row is the same as the open row. If not, I need to take an action. (Prompt the user? Commit automatically? Revert?)
I see how to get the current item, and can get the delegate on that item, but I don't see any isEditMode() property I was hoping to find.
Can someone point me in the right direction?
Just check whether the return value of
State QAbstractItemView::state () const
is
QTableView::EditingState
Connect to underlying model dataChanged signal
void QAbstractItemModel::dataChanged ( const QModelIndex & topLeft, const QModelIndex & bottomRight )
You can check if the cell where data has changed is the same than the currentIndex
QModelIndex QAbstractItemView::currentIndex () const
You cannot know if the current cell had an open editor straight, but can check if the view is in QAbstractItemView::EditingState
State QAbstractItemView::state () const
It should be enough to do what you want.
You can subclass QTableView in order to be able to access the state() function, which is unfortunately protected. However, I did not try that.
If you already have an QStyledItemDelegate subclass, you can use it to track whether an editor is currently open. However, you can't just use setEditorData/setModelData, because setModelData won't be called, when the user cancels editing. Instead, you can track the creation and destruction of the editor itself.
class MyItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
MyItemDelegate( QObject* parent = nullptr );
~MyItemDelegate();
QWidget* createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
void setEditorData( QWidget* editor, const QModelIndex& index ) const;
void setModelData( QWidget* editor, QAbstractItemModel* model, const QModelIndex& index ) const;
bool isEditorOpen() const { return *m_editorCount > 0; }
protected:
int* m_editorCount;
protected slots:
void onEditorDestroyed( QObject* obj );
};
Implementation:
MyItemDelegate::MyItemDelegate( QObject* parent ) :
QStyledItemDelegate( parent )
{
m_editorCount = new int;
*m_editorCount = 0;
}
MyItemDelegate::~MyItemDelegate()
{
delete m_editorCount;
}
QWidget* MyItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
// create an editor, can be changed as needed
QWidget* editor = QStyledItemDelegate::createEditor( parent, option, index );
connect( editor, SIGNAL(destroyed(QObject*)), SLOT(onEditorDestroyed(QObject*)));
printf( "editor %p created\n", (void*) editor );
(*m_editorCount)++;
return editor;
}
void MyItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
...
}
void MyItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
...
}
void MyItemDelegate::onEditorDestroyed( QObject* obj )
{
printf( "editor %p destroyed\n", (void*) obj );
(*m_editorCount)--;
}
On some occasions, e.g. when moving to the next item in the tree using the cursor keys, Qt will create the new editor first and then destroy the old one. Hence, m_editorCount must be an integer instead of a bool.
Unfortunately, createEditor() is a const function. Therefore, you cannot create an int-member. Instead, create a pointer to an int and use that.
Subclass your delegate so that it includes an accessor that tells you when it's editing:
void MyDelegate::setEditorData ( QWidget * editor, const QModelIndex & index ) const {
// _isEditing will have to be mutable because this method is const
_isEditing = true;
QStyledItemDelegate::setEditorData(editor, index);
}
void MyDelegate::setModelData ( QWidget * editor, QAbstractItemModel * model, const QModelIndex & index ) const {
QStyledItemDelegate::setModelData(editor, model, index);
_isEditing = false;
}
bool MyDelegate::isEditing() const { return _isEditing; }
Then you can just check the delegate to see what's going on. Alternatively and/or if you don't like the mutable, you can emit signals so you know what state the delegate is in.
If you know the index of the item being edited, you can call indexWidget() and attempt to cast it. If it's valid, you not only know you're editing, but you also have your editor widget handy.
EditWidget *editWidget = qobject_cast<EditWidget*>(tableView->indexWidget(tableView->currentIndex()));
if(editWidget)
{
//yep, ur editing bro
}
Here is an idea, its even helpful to get the edit/combo widget before the edit begins...
just emit a signal and consume it in the mainwindow... this is what I used one to get combo box in QTableWidget before editing...
first create a signal in ComoBoxItemDelegate...
signals:
void OnComboEdit(QComboBox* pCombo) const;
then emit the signal in the createEditor method...
QWidget* ComboBoxItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
// Create the combobox and populate it
QComboBox* cb = new QComboBox(parent);
emit OnComboEdit(cb);
return cb;
}
and in the MainWindow declare a function to receive the singal...
void MainWindow::OnComboEidt(QComboBox *pCB) const
{
qDebug() << "Combo Eidt Singal Received";
}
Then finally in the constructor of MainWindow connect it...
ComboBoxItemDelegate* cbid = new ComboBoxItemDelegate(ui->tableWidget);
connect(cbid, &ComboBoxItemDelegate::OnComboEdit, this, &MainWindow::OnComboEidt);
ui->tableWidget->setItemDelegateForColumn(0, cbid);

Resources