@kromignon Thanks.
I had also read that article, but that also not defines how Qt handle this stuation:
In this version, we pass monitor as a context to connect(). It won't affect the execution of our lambda, but when monitor is deleted, Qt will notice and will disconnect Worker::progress() from our lambda.
I tried with below, but could not find how to detect I have already disconnect:
connect(receiver, &QObject::destroyed, [this](){
qDebug() << "receiver destroyed";
m_msgBox->disconnect();
});
Full code with receiver (deletes btn after 10 sec!):
#include <QApplication>
#include <QMessageBox>
#include <QPushButton>
#include <QDebug>
#include <QScreen>
#include <QStyle>
#include <QTimer>
class Button : public QPushButton
{
Q_OBJECT
public:
Button(QWidget *parent = nullptr) : QPushButton(parent) {
setText(tr("Click"));
m_msgBox = new QMessageBox(this);
connect(this, &QPushButton::clicked, [this](){
ask(tr("Which do you prefer?"),
QStringList() << tr("Apple") << tr("Pineapple"),
0, 1, this,
[](int result) {
if (result == 0)
qDebug() << "Selected Apple";
else if (result == 1)
qDebug() << "Selected Pineapple";
else
qDebug() << "Unexpected result = " << result;
});
});
}
virtual ~Button() {}
void ask(
const QString & text,
const QStringList & buttons,
int acceptButton,
int rejectButton,
const QObject * receiver,
std::function<void(int)> func)
{
m_msgBox->setText(text);
m_msgBox->setIcon(QMessageBox::Question);
m_msgBox->setStandardButtons(QMessageBox::NoButton);
QList<QAbstractButton*> buttonList;
for (int i = 0; i < buttons.count(); ++i) {
if (i == acceptButton) {
QPushButton * btn = m_msgBox->addButton(buttons.at(i), QMessageBox::AcceptRole);
m_msgBox->setDefaultButton(btn);
buttonList.append((QAbstractButton*)btn);
}
else if (i == rejectButton) {
QPushButton * btn = m_msgBox->addButton(buttons.at(i), QMessageBox::RejectRole);
m_msgBox->setEscapeButton((QAbstractButton*)btn);
buttonList.append((QAbstractButton*)btn);
}
else {
Q_ASSERT(false);
}
}
connect(m_msgBox, &QMessageBox::finished, [this, rejectButton, buttonList, func](int) {
m_msgBox->disconnect();
int res = rejectButton;
for (int i = 0; i < buttonList.count(); ++i) {
if (m_msgBox->clickedButton() == buttonList.at(i)) {
res = i;
break;
}
}
QList<QAbstractButton*> listToDelete = m_msgBox->buttons();
foreach (QAbstractButton * btn, listToDelete) {
m_msgBox->removeButton(btn);
btn->deleteLater();
}
func(res);
});
connect(receiver, &QObject::destroyed, [this](){
qDebug() << "receiver destroyed";
m_msgBox->disconnect();
});
m_msgBox->open();
}
private:
QMessageBox * m_msgBox = nullptr;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Button * btn = new Button;
btn->resize(100, 30);
btn->setGeometry(
QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, btn->size(),
qApp->screens().first()->availableGeometry()));
btn->show();
QTimer::singleShot(10000, [&](){
delete btn;
btn = nullptr;
});
int res = a.exec();
if (btn)
delete btn;
return res;
}
#include "main.moc"