tycho: let Qt handle object lifetimes for us

master
an 2019-07-03 19:23:04 -04:00
parent cd854ef8ea
commit 3e9ca71dc8
6 changed files with 101 additions and 65 deletions

View File

@ -1,7 +1,7 @@
#include "tycho.h" #include "tycho.h"
MapModel::MapModel(QObject *parent) : MapModel::MapModel(Project *parent) :
AbstractMapModel(parent), AbstractMapModel(static_cast<QWidget *>(parent)),
ProjectModel() ProjectModel()
{ {
dbgPrintFunc(); dbgPrintFunc();
@ -12,11 +12,6 @@ MapModel::~MapModel()
dbgPrintFunc(); dbgPrintFunc();
} }
ProjectModelType MapModel::type() const
{
return ProjectModelType::Map;
}
bool MapModel::isDirty() const bool MapModel::isDirty() const
{ {
return AbstractMapModel::isDirty(); return AbstractMapModel::isDirty();

View File

@ -1,8 +1,8 @@
#include "tycho.h" #include "tycho.h"
MapProps::MapProps(std::weak_ptr<MapModel> _mapModel, QWidget *parent) : MapProps::MapProps(Project *parent) :
QDialog(parent), QDialog(static_cast<QWidget *>(parent)),
mapModel(_mapModel) mapModel(parent->getMapModel())
{ {
setupUi(this); setupUi(this);
@ -12,8 +12,8 @@ MapProps::MapProps(std::weak_ptr<MapModel> _mapModel, QWidget *parent) :
bbox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); bbox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
verticalLayout->addWidget(bbox); verticalLayout->addWidget(bbox);
connect(bbox, SIGNAL(accepted()), this, SLOT(accept())); connect(bbox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(bbox, SIGNAL(rejected()), this, SLOT(reject())); connect(bbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
dbgPrintFunc(); dbgPrintFunc();
} }
@ -23,4 +23,9 @@ MapProps::~MapProps()
dbgPrintFunc(); dbgPrintFunc();
} }
void MapProps::accept()
{
done(QDialog::Accepted);
}
// EOF // EOF

View File

@ -1,8 +1,8 @@
#include "tycho.h" #include "tycho.h"
MapView::MapView(std::weak_ptr<MapModel> _mapModel, QWidget *parent) : MapView::MapView(Project *parent) :
QWidget(parent), QWidget(static_cast<QWidget *>(parent)),
mapModel(_mapModel) mapModel(parent->getMapModel())
{ {
setupUi(this); setupUi(this);

View File

@ -22,7 +22,7 @@ Menu::~Menu()
void Menu::mapNew() void Menu::mapNew()
{ {
QScopedPointer proj{new Project(ProjectModelType::Map)}; QScopedPointer proj{new Project(ProjectType::Map)};
addProject(proj.take()); addProject(proj.take());
} }
@ -40,7 +40,7 @@ void Menu::mapOpen()
"All files (*)")); "All files (*)"));
if(!fname.isEmpty()) { if(!fname.isEmpty()) {
QScopedPointer proj{new Project(ProjectModelType::Map)}; QScopedPointer proj{new Project(ProjectType::Map)};
if(proj->getModel()->open(fname)) { if(proj->getModel()->open(fname)) {
addProject(proj.take()); addProject(proj.take());
@ -98,19 +98,22 @@ void Menu::openMapProperties()
{ {
auto proj = activeProject(); auto proj = activeProject();
if(proj && proj->getModel()->type() == ProjectModelType::Map) { if(proj && proj->getType() == ProjectType::Map) {
MapProps props{proj->getMapModel(), proj}; MapProps props{proj};
props.exec(); props.exec();
} }
} }
void Menu::updateActions() void Menu::updateActions()
{ {
auto proj = activeProject(); std::optional<ProjectType> active;
bool active = proj != nullptr;
actionClose->setEnabled(active); if(auto proj = activeProject()) {
actionMapProps->setEnabled(active); active = proj->getType();
}
actionClose->setEnabled(!!active);
actionMapProps->setEnabled(active == ProjectType::Map);
} }
void Menu::closeEvent(QCloseEvent *event) void Menu::closeEvent(QCloseEvent *event)

View File

@ -1,9 +1,24 @@
#include "tycho.h" #include "tycho.h"
Project::Project(ProjectModelType type) : static ProjectModel *makeModel(Project *proj)
{
switch(proj->getType()) {
case ProjectType::Map: return new MapModel(proj);
}
}
static ProjectView *makeView(Project *proj)
{
switch(proj->getType()) {
case ProjectType::Map: return new MapView(proj);
}
}
Project::Project(ProjectType _type) :
QMdiSubWindow(), QMdiSubWindow(),
model(nullptr), type(_type),
view(nullptr) model(makeModel(this)),
view(makeView(this))
{ {
auto widget = new QWidget(this); auto widget = new QWidget(this);
@ -12,15 +27,13 @@ Project::Project(ProjectModelType type) :
setWidget(widget); setWidget(widget);
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
switch(type) { listView->setModel(dynamic_cast<QAbstractItemModel *>(model));
case ProjectModelType::Map: verticalLayout->insertWidget(0, dynamic_cast<QWidget *>(view));
model.reset(new MapModel(this));
view = new MapView(getMapModel(), this);
break;
}
listView->setModel(dynamic_cast<QAbstractItemModel *>(model.get())); connect(listView,
verticalLayout->insertWidget(0, view); SIGNAL(doubleClicked(QModelIndex const &)),
dynamic_cast<QObject *>(model),
SLOT(select(QModelIndex const &)));
dbgPrintFunc(); dbgPrintFunc();
} }
@ -30,14 +43,19 @@ Project::~Project()
dbgPrintFunc(); dbgPrintFunc();
} }
std::shared_ptr<ProjectModel> Project::getModel() ProjectType Project::getType() const
{
return type;
}
ProjectModel *Project::getModel() const
{ {
return model; return model;
} }
std::shared_ptr<MapModel> Project::getMapModel() MapModel *Project::getMapModel() const
{ {
return std::dynamic_pointer_cast<MapModel>(model); return dynamic_cast<MapModel *>(model);
} }
void Project::closeEvent(QCloseEvent *event) void Project::closeEvent(QCloseEvent *event)

View File

@ -3,7 +3,7 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <iostream> #include <iostream>
#include <memory> #include <optional>
#include <vector> #include <vector>
#include <QApplication> #include <QApplication>
@ -25,40 +25,48 @@
#include "../ui/ui_menu.h" #include "../ui/ui_menu.h"
#include "../ui/ui_project.h" #include "../ui/ui_project.h"
// Types ---------------------------------------------------------------------|
class MapModel; class MapModel;
class MapProps; class MapProps;
class MapView; class MapView;
class Menu; class Menu;
class Project; class Project;
enum class ProjectModelType enum class ProjectType
{ {
Map, Map,
}; };
// Interfaces ----------------------------------------------------------------|
class ProjectModel class ProjectModel
{ {
public: public:
virtual ~ProjectModel() {} virtual ~ProjectModel() {}
virtual ProjectModelType type() const = 0;
virtual bool isDirty() const = 0; virtual bool isDirty() const = 0;
virtual bool open(QString const &path) = 0; virtual bool open(QString const &path) = 0;
virtual bool save() const = 0; virtual bool save() const = 0;
virtual bool saveAs(QString const &path) const = 0; virtual bool saveAs(QString const &path) const = 0;
}; };
class ProjectView
{
public:
virtual ~ProjectView() {}
};
// Implementations -----------------------------------------------------------|
class MapModel final : public AbstractMapModel, public ProjectModel class MapModel final : public AbstractMapModel, public ProjectModel
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit MapModel(QObject *parent = nullptr); explicit MapModel(Project *parent);
~MapModel() override; ~MapModel() override;
ProjectModelType type() const override;
bool isDirty() const override; bool isDirty() const override;
bool open(QString const &path) override; bool open(QString const &path) override;
bool save() const override; bool save() const override;
@ -69,30 +77,32 @@ private:
const override; const override;
}; };
class MapView final : public QWidget, public ProjectView, private Ui::MapView
{
Q_OBJECT
public:
explicit MapView(Project *parent);
~MapView();
private:
MapModel *const mapModel;
};
// UI ------------------------------------------------------------------------|
class MapProps final : public QDialog, private Ui::MapProps class MapProps final : public QDialog, private Ui::MapProps
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit MapProps(std::weak_ptr<MapModel> mapModel, explicit MapProps(Project *parent);
QWidget *parent = nullptr);
~MapProps(); ~MapProps();
private: void accept() override;
std::weak_ptr<MapModel> mapModel;
};
class MapView final : public QWidget, private Ui::MapView
{
Q_OBJECT
public:
explicit MapView(std::weak_ptr<MapModel> mapModel,
QWidget *parent = nullptr);
~MapView();
private: private:
std::weak_ptr<MapModel> mapModel; MapModel *const mapModel;
}; };
class Menu final : public QMainWindow, private Ui::Menu class Menu final : public QMainWindow, private Ui::Menu
@ -116,8 +126,9 @@ protected:
void openLicense(QWidget *parent); void openLicense(QWidget *parent);
private: private:
Project *activeProject() const; Project *activeProject() const;
QMdiSubWindow *activeSubWindow() const; QMdiSubWindow *activeSubWindow() const;
void addProject(Project *proj); void addProject(Project *proj);
}; };
@ -126,18 +137,22 @@ class Project final : public QMdiSubWindow, private Ui::Project
Q_OBJECT Q_OBJECT
public: public:
explicit Project(ProjectModelType type); explicit Project(ProjectType type);
~Project(); ~Project();
std::shared_ptr<ProjectModel> getModel(); ProjectType getType() const;
std::shared_ptr<MapModel> getMapModel();
ProjectModel *getModel() const;
MapModel *getMapModel() const;
protected: protected:
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;
private: private:
std::shared_ptr<ProjectModel> model; ProjectType const type;
QWidget *view;
ProjectModel *const model;
ProjectView *const view;
}; };
template<typename... VA> template<typename... VA>