Fix peripheral deletion order issue when exiting application
MODIFY
src/io/periphparammodel.cpp
src/io/periphparammodel.cpp
@@ -35,7 +35,7 @@ void PeriphParamDelegate::setModelData(QWidget* e, QAbstractItemModel* model, co
}
}
-PeriphParamModel::PeriphParamModel(IOBase* peripheral, QObject* parent)
+PeriphParamModel::PeriphParamModel(QPointer<IOBase> peripheral, QObject* parent)
: QAbstractTableModel(parent), m_peripheral(peripheral) {}
int PeriphParamModel::columnCount(const QModelIndex&) const {
@@ -43,7 +43,11 @@ int PeriphParamModel::columnCount(const QModelIndex&) const {
}
int PeriphParamModel::rowCount(const QModelIndex&) const {
+ if (!m_peripheral.isNull()) {
return m_peripheral->parameters().size();
+ } else {
+ return 0;
+ }
}
QVariant PeriphParamModel::headerData(int section, Qt::Orientation orientation, int role) const {
@@ -61,12 +65,20 @@ QVariant PeriphParamModel::headerData(int section, Qt::Orientation orientation,
}
bool PeriphParamModel::setData(const QModelIndex& index, const QVariant& value, int) {
+ if (!m_peripheral.isNull()) {
const unsigned idx = index.row();
auto ret = m_peripheral->setParameter(idx, value);
return ret == value;
+ } else {
+ return false;
+ }
}
QVariant PeriphParamModel::data(const QModelIndex& index, int role) const {
+ if (m_peripheral.isNull()) {
+ return QVariant();
+ }
+
if (!index.isValid()) {
return QVariant();
}

MODIFY
src/io/periphparammodel.h
src/io/periphparammodel.h
#include "radix.h"
#include <QAbstractTableModel>
+#include <QPointer>
#include <QStyledItemDelegate>
namespace Ripes {
@@ -31,7 +32,7 @@ class PeriphParamModel : public QAbstractTableModel {
Q_OBJECT
public:
enum Column { Name, Value, NColumns };
- PeriphParamModel(IOBase* peripheral, QObject* parent = nullptr);
+ PeriphParamModel(QPointer<IOBase> peripheral, QObject* parent = nullptr);
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
@@ -43,6 +44,6 @@ public:
Qt::ItemFlags flags(const QModelIndex& index) const override;
private:
- IOBase* m_peripheral = nullptr;
+ QPointer<IOBase> m_peripheral = nullptr;
};
} // namespace Ripes

MODIFY
src/io/registermapmodel.cpp
src/io/registermapmodel.cpp
namespace Ripes {
-RegisterMapModel::RegisterMapModel(IOBase* peripheral, QObject* parent)
+RegisterMapModel::RegisterMapModel(QPointer<IOBase> peripheral, QObject* parent)
: QAbstractTableModel(parent), m_peripheral(peripheral) {
connect(m_peripheral, &IOBase::regMapChanged, this, &RegisterMapModel::regMapChanged);
}
@@ -23,7 +23,11 @@ int RegisterMapModel::columnCount(const QModelIndex&) const {
}
int RegisterMapModel::rowCount(const QModelIndex&) const {
+ if (!m_peripheral.isNull()) {
return m_peripheral->registers().size();
+ } else {
+ return 0;
+ }
}
QVariant RegisterMapModel::headerData(int section, Qt::Orientation orientation, int role) const {
@@ -45,6 +49,10 @@ QVariant RegisterMapModel::headerData(int section, Qt::Orientation orientation,
}
QVariant RegisterMapModel::data(const QModelIndex& index, int role) const {
+ if (m_peripheral.isNull()) {
+ return QVariant();
+ }
+
if (!index.isValid()) {
return QVariant();
}

MODIFY
src/io/registermapmodel.h
src/io/registermapmodel.h
#include "radix.h"
#include <QAbstractTableModel>
+#include <QPointer>
namespace Ripes {
class IOBase;
@@ -22,7 +23,7 @@ class RegisterMapModel : public QAbstractTableModel {
Q_OBJECT
public:
enum Column { Name, Address, RW, BitWidth, NColumns };
- RegisterMapModel(IOBase* peripheral, QObject* parent = nullptr);
+ RegisterMapModel(QPointer<IOBase> peripheral, QObject* parent = nullptr);
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
@@ -36,6 +37,6 @@ public slots:
void regMapChanged();
private:
- IOBase* m_peripheral = nullptr;
+ QPointer<IOBase> m_peripheral = nullptr;
};
} // namespace Ripes

MODIFY
src/iotab.cpp
src/iotab.cpp
@@ -66,7 +66,7 @@ IOTab::IOTab(QToolBar* toolbar, QWidget* parent) : RipesTab(toolbar, parent), m_
}
});
- connect(&IOManager::get(), &IOManager::peripheralRemoved, this, &IOTab::removePeripheral);
+ connect(&IOManager::get(), &IOManager::peripheralRemoved, QPointer(this), &IOTab::removePeripheral);
connect(m_ui->peripheralsTab, &QTabWidget::currentChanged, this, &IOTab::setPeripheralMDIWindowActive);
@@ -199,6 +199,18 @@ void IOTab::tile() {
}
IOTab::~IOTab() {
+ /* Because of the way that IOBase objects signal to the IOTab that they have been removed, we need to delete all
+ * IOBase objects before deleting the IOTab itself. The default deletion mechanism is incorrect for this, given that
+ * IOTab is first deleted, and then the underlying QObject is deleted (which deletes its children, being the IOBase
+ * objects). We delete from the subwindows because they are the top-level parent of the IOBase objects.
+ */
+
+ // Copy subwindows collection, so we can safely iterate through it (m_subWindows is modified when deleting a
+ // subwindow).
+ auto subWindowsCopy = m_subWindows;
+ for (const auto& subwindow : subWindowsCopy) {
+ delete subwindow.second;
+ }
delete m_ui;
}
} // namespace Ripes

Fix peripheral deletion order issue when exiting application