PDA

View Full Version : QDialog - get parent name



bandito
24th August 2016, 02:04
My program has to QListwidgets. When I right click on the list I have a QDialog popup. When the QDialog pops up I would like to know which QListWidget has opened it. I tried using this line of code
qDebug()<<QDialog->parentWidget()->objectName(); but it crashed my program.

Here is some code from my .cpp file.

(this is in the main function/constructor)



lists = new QTabWidget;
lists->setFixedWidth(200);
etfList = new QListWidget;
ipoList = new QListWidget;
etfList->setObjectName("ETFList");
etfList->setContextMenuPolicy(Qt::CustomContextMenu);
ipoList->setObjectName("IPOList");
ipoList->setContextMenuPolicy(Qt::CustomContextMenu);
lists->addTab(etfList, "ETF List");
lists->addTab(ipoList, "IPO List");


connect(etfList, SIGNAL(customContextMenuRequested(const QPoint &)), this,SLOT(menuPopup(const QPoint &)));
connect(ipoList, SIGNAL(customContextMenuRequested(const QPoint &)), this,SLOT(menuPopup(const QPoint &)));


(this is the slot)


void MainWindow::menuPopup(const QPoint &point){

QDialog *dia = new QDialog();
qDebug()<<dia->parentWidget()->objectName(); <---crashes on this line
dia->show();
}
}


And in my header file:




class MainWindow : public QMainWindow
{
Q_OBJECT
QTabWidget *lists;
QListWidget *etfList;
QListWidget *ipoList;

public:
explicit MainWindow(QWidget *parent = 0);

~MainWindow();

signals:

private slots:
void menuPopup(const QPoint &point);

d_stranz
24th August 2016, 05:31
qDebug()<<dia->parentWidget()->objectName(); <---crashes on this line

Of course it does, because on the line before that you created your QDialog instance with no parent, so parentWidget() returns NULL. And by the way, your method of creating the QDialog on the heap (using "new") causes a memory leak. The more common method is to create temporary QDialog instances on the stack, which will automatically be destroyed when the slot exits and the QDialog instance goes out of scope.

Anyway, it isn't the QDialog's parent you are interested in - that has nothing to do with which QListWidget issued the signal that the slot is handling. Look at the QObject::sender() method. When you are in the slot, it tells you which QObject issued the signal that your slot is handling. If the only signals connected to that slot are those from the QListWidget instances, then you can qobject_cast() the pointer returned by the sender() method to QListWidget * and see which one of your two QListWidget pointers it matches.

anda_skoa
24th August 2016, 12:24
The more common method is to create temporary QDialog instances on the stack, which will automatically be destroyed when the slot exits and the QDialog instance goes out of scope.

Not for a non-modal dialog though, like in this case (QDialog::show() being called).
For those it is usually either explicit delete or using the DeleteOnClose widget attribute.

Cheers,
_

d_stranz
24th August 2016, 15:21
Not for a non-modal dialog though, like in this case (QDialog::show() being called).
For those it is usually either explicit delete or using the DeleteOnClose widget attribute.


True, but I don't think that was the intent in this case. The code pattern implies that the QDialog instance was intended to be temporary, since neither the DeleteOnClose attribute was set nor the destructor called.

bandito
25th August 2016, 00:32
Thank you d_stranz and anda_skoa. The QObject::sender() works perfect. As for the temporary instances, anda_skoa is correct. Creating a temporary instance
QDialog *dia; ends up crashed the program but using
dia->setAttribute(Qt::WA_DeleteOnClose, true); runs with our a flaw.

d_stranz
26th August 2016, 00:46
QDialog *dia;

This is not "creating a temporary instance". This is a declaration of a (uninitialized) local variable named "dia" of type "QDialog *". And of course, it crashes too, because it is uninitialized and points to garbage.

This is what I meant:



void MyClass::on_some_slot()
{
QDialog dlg;
if ( dlg.exec() == QDialog::Accepted )
{
// do something with the result
}

// dlg goes out of scope when method exits, and is automatically destroyed
}

bandito
26th August 2016, 02:23
This is what I meant:



void MyClass::on_some_slot()
{
QDialog dlg;
if ( dlg.exec() == QDialog::Accepted )
{
// do something with the result
}

// dlg goes out of scope when method exits, and is automatically destroyed
}


Sorry d_stranz for the confusion.

I tried your code but it does not enter the if condition. It does however run fine outside the if condition (Or appears to anyway).

Maybe there us something else that I am missing?

d_stranz
27th August 2016, 02:11
I tried your code but it does not enter the if condition.

Well, no, it won't as written. QDialog is like QWidget - it is a base class that contains nothing; you generally have to derive a class from it that you fill up with other GUI child widgets in a layout. In particular, classes derived from QDialog generally have an OK button or something like that which is connected to the QDialog::accept() slot. This causes the exec() function to exit with the QDialog::Accepted result code.

If you execute the code I wrote above, the only way to close the dialog is to click the "X" button on the dialog's frame. This is connected to the QDialog::reject() slot. That causes the exec() method to exit with the QDialog::Rejected result code, so the if() clause is not entered. Change my code to replace "Accepted" with "Rejected" and see what happens.