Safe way of creating new QDialog object

Viewed 184

I am writing a Qt application where I have QListWidget filled with QListWidgetItems and I want to create a new dialog on double click on QListWidgetItem. So I created a new dialog class as in this qt tutorial. Now, I added on_listWidget_itemDoubleClicked(QListWidgetItem* item) slot where I should create an instance of dialog class. But I want my main app to still operate and continue and just have dialog window show some info. So I cant just create an instance of dialog class and show it with exec() function.

So what i came up with is to have std::unique_ptr on my dialog class as class member of my main class, and invoke dialog with show() method. Everytime on_listWidget_itemDoubleClicked(QListWidgetItem* item) is called I will create new instance of dialog class with std::make_unique which should destroy old dialog and create a new one.

Is this generally a safe approach ? Or is there other standard way of solving such situation ?

EDIT

Here is example how I was thinking it might look:

The main class:

class USB_Packet_Analyzer : public QWidget
{
    Q_OBJECT

public:
    USB_Packet_Analyzer(QWidget *parent = Q_NULLPTR);    
private:
    Ui::USB_Packet_AnalyzerClass ui;
    std::unique_ptr<DataViewer> dataViewer;
private slots:
    void on_listWidget_itemDoubleClicked(QListWidgetItem* item);
};


void USB_Packet_Analyzer::on_listWidget_itemDoubleClicked(QListWidgetItem* item)
{
    dataViewer = std::make_unique<DataViewer>(item, this);
    dataViewer->show();
}

Dialog class :

class DataViewer : public QDialog
{
    Q_OBJECT

public:
    DataViewer(QListWidgetItem* item, QWidget *parent = Q_NULLPTR);
    ~DataViewer();

private:
    Ui::DataViewer ui;
};
2 Answers

Yes what you are doing is fine. There are some minor issues you may want to address:

  1. Closing the dialog does not free the memory. The memory will be consumed until the unique_ptr is destroyed.

  2. The unique_ptr is not cleared when the dialog is closed. This may be fine now, but if you try to use that unique_ptr later it may be a problem.

These may not cause problems now, but they may in the future. This is why I could suggest the following edits:

void USB_Packet_Analyzer::on_listWidget_itemDoubleClicked(QListWidgetItem* item)
{
    if (!dataViewer.isNull()) dataViewer->deleteLater();
    dataViewer = QPointer(new DataViewer(item, this));
    dataViewer ->setAttribute(Qt::WidgetAttribute::WA_DeleteOnClose);
    dataViewer->show();
}

QPointer allows you to easily detect if the widget has been deleted.

While technically your usage of unique_ptr is safe, it is dangerous to use QObject classes in smart pointers. QObject lifetimes are usually managed through parent-child relationships. Because the smart pointers don't know about this, it is VERY easy to get double frees when doing this. I would recommend you go with the QPointer version because of this.

you dont need a special custom made dialog for just showing a couple lines of info use instead the MessageBox...

 QMessageBox::information(this, "some title", "my text");
Related