tycho: fix broken inheritance chain by submoduling rust-qt-binding-generator

master
an 2019-07-03 23:17:04 -04:00
parent fa7d785212
commit c01756886b
15 changed files with 168 additions and 120 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "rust-qt-binding-generator"]
path = rust-qt-binding-generator
url = https://git.greyserv.net/marrub/rust-qt-binding-generator

@ -0,0 +1 @@
Subproject commit 598336e657cb4bf5ef5070dfa35b999b7dfd341b

View File

@ -23,6 +23,7 @@ add_library(
SHARED SHARED
$ENV{OUT_DIR}/bindings.cc $ENV{OUT_DIR}/bindings.cc
$ENV{OUT_DIR}/bindings.h $ENV{OUT_DIR}/bindings.h
cc/interface.h
cc/main.cc cc/main.cc
cc/mapmodel.cc cc/mapmodel.cc
cc/mapprops.cc cc/mapprops.cc
@ -51,6 +52,7 @@ target_include_directories(
maraiah-tycho-hermes maraiah-tycho-hermes
PUBLIC PUBLIC
$ENV{OUT_DIR} $ENV{OUT_DIR}
cc
) )
target_link_libraries( target_link_libraries(

View File

@ -10,7 +10,7 @@ maraiah = {path = ".."}
[build-dependencies] [build-dependencies]
cmake = "0.1" cmake = "0.1"
maraiah = {path = ".."} maraiah = {path = ".."}
rust_qt_binding_generator = "0.3" rust_qt_binding_generator = {path = "../rust-qt-binding-generator"}
[[bin]] [[bin]]
name = "tycho" name = "tycho"

View File

@ -1,4 +1,5 @@
{ {
"beforeHeader": "interface.h",
"cppFile": "", "cppFile": "",
"rust": { "rust": {
"dir": "", "dir": "",
@ -8,6 +9,7 @@
"objects": { "objects": {
"IMapModel": { "IMapModel": {
"type": "List", "type": "List",
"baseClass": "IProjectModel",
"functions": { "functions": {
"open": { "open": {
"return": "bool", "return": "bool",
@ -27,10 +29,6 @@
{"name": "path", "type": "QString"} {"name": "path", "type": "QString"}
] ]
}, },
"isDirty": {
"return": "bool",
"mut": false
},
"propIcon": { "propIcon": {
"return": "QString", "return": "QString",
"mut": false, "mut": false,
@ -51,10 +49,20 @@
} }
}, },
"properties": { "properties": {
"dirty": {"type": "bool", "write": true}
}, },
"itemProperties": { "itemProperties": {
"propIndex": {"type": "quint64", "roles": [["display"]]} "propIndex": {"type": "quint64", "roles": [["display"]]}
} }
},
"IMapView": {
"type": "Object",
"functions": {
},
"properties": {
},
"itemProperties": {
}
} }
} }
} }

40
tycho/cc/interface.h Normal file
View File

@ -0,0 +1,40 @@
#pragma once
#pragma clang diagnostic ignored "-Winconsistent-missing-override"
#include <QAbstractItemModel>
class IProjectModel : public QAbstractItemModel
{
Q_OBJECT
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged)
public:
using QAbstractItemModel::QAbstractItemModel;
virtual ~IProjectModel() {}
virtual bool dirty() const = 0;
virtual void setDirty(bool dirty) = 0;
virtual bool open(QString const &path) = 0;
virtual bool save() const = 0;
virtual bool saveAs(QString const &path) const = 0;
public slots:
virtual void deselect() = 0;
virtual void select(QModelIndex const &index) = 0;
signals:
void dirtyChanged(bool dirty);
void deselected();
void selected(std::uint16_t index);
};
class IProjectView
{
public:
virtual ~IProjectView() {}
};
// EOF

View File

@ -1,45 +1,24 @@
#include "tycho.h" #include "tycho.h"
CMapModel::CMapModel(Project *parent) : MapModel::MapModel(Project *parent) :
IMapModel(static_cast<QWidget *>(parent)), IMapModel(parent)
IProjectModel()
{ {
dbgPrintFunc(); dbgPrintFunc();
} }
CMapModel::~CMapModel() MapModel::~MapModel()
{ {
dbgPrintFunc(); dbgPrintFunc();
} }
bool CMapModel::isDirty() const void MapModel::deselect()
{
return IMapModel::isDirty();
}
bool CMapModel::open(QString const &path)
{
return IMapModel::open(path);
}
bool CMapModel::save() const
{
return IMapModel::save();
}
bool CMapModel::saveAs(QString const &path) const
{
return IMapModel::saveAs(path);
}
void CMapModel::deselect()
{ {
IMapModel::deselect(); IMapModel::deselect();
emit deselected(); emit deselected();
} }
void CMapModel::select(QModelIndex const &index) void MapModel::select(QModelIndex const &index)
{ {
auto idx = index.internalId(); auto idx = index.internalId();
@ -48,7 +27,7 @@ void CMapModel::select(QModelIndex const &index)
emit selected(idx); emit selected(idx);
} }
QVariant CMapModel::data(const QModelIndex &index, int role) const QVariant MapModel::data(const QModelIndex &index, int role) const
{ {
switch(role) { switch(role) {
case Qt::DecorationRole: { case Qt::DecorationRole: {

View File

@ -2,7 +2,7 @@
MapProps::MapProps(Project *parent) : MapProps::MapProps(Project *parent) :
QDialog(static_cast<QWidget *>(parent)), QDialog(static_cast<QWidget *>(parent)),
mapModel(parent->getMapModel()) m_mapModel(parent->mapModel())
{ {
setupUi(this); setupUi(this);

View File

@ -1,15 +1,15 @@
#include "tycho.h" #include "tycho.h"
CMapView::CMapView(Project *parent) : MapView::MapView(Project *parent) :
QWidget(static_cast<QWidget *>(parent)), QWidget(static_cast<QWidget *>(parent)),
mapModel(parent->getMapModel()) m_mapModel(parent->mapModel())
{ {
setupUi(this); setupUi(this);
dbgPrintFunc(); dbgPrintFunc();
} }
CMapView::~CMapView() MapView::~MapView()
{ {
dbgPrintFunc(); dbgPrintFunc();
} }

View File

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

View File

@ -3,24 +3,24 @@
static static
IProjectModel *makeModel(Project *proj) IProjectModel *makeModel(Project *proj)
{ {
switch(proj->getType()) { switch(proj->type()) {
case ProjectType::Map: return new MapModel(proj); case Project::Map: return new MapModel(proj);
} }
} }
static static
IProjectView *makeView(Project *proj) IProjectView *makeView(Project *proj)
{ {
switch(proj->getType()) { switch(proj->type()) {
case ProjectType::Map: return new MapView(proj); case Project::Map: return new MapView(proj);
} }
} }
Project::Project(ProjectType _type) : Project::Project(Type type) :
QMdiSubWindow(), QMdiSubWindow(),
type(_type), m_type(type),
model(makeModel(this)), m_model(makeModel(this)),
view(makeView(this)) m_view(makeView(this))
{ {
auto widget = new QWidget(this); auto widget = new QWidget(this);
@ -29,12 +29,12 @@ Project::Project(ProjectType _type) :
setWidget(widget); setWidget(widget);
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
listView->setModel(dynamic_cast<QAbstractItemModel *>(model)); listView->setModel(m_model);
verticalLayout->insertWidget(0, dynamic_cast<QWidget *>(view)); verticalLayout->insertWidget(0, dynamic_cast<QWidget *>(m_view));
connect(listView, connect(listView,
SIGNAL(doubleClicked(QModelIndex const &)), SIGNAL(doubleClicked(QModelIndex const &)),
dynamic_cast<QObject *>(model), m_model,
SLOT(select(QModelIndex const &))); SLOT(select(QModelIndex const &)));
dbgPrintFunc(); dbgPrintFunc();
@ -45,24 +45,24 @@ Project::~Project()
dbgPrintFunc(); dbgPrintFunc();
} }
ProjectType Project::getType() const Project::Type Project::type() const
{ {
return type; return m_type;
} }
ProjectModel *Project::getModel() const IProjectModel *Project::model() const
{ {
return model; return m_model;
} }
MapModel *Project::getMapModel() const MapModel *Project::mapModel() const
{ {
return dynamic_cast<MapModel *>(model); return dynamic_cast<MapModel *>(m_model);
} }
void Project::closeEvent(QCloseEvent *event) void Project::closeEvent(QCloseEvent *event)
{ {
if(model->isDirty()) { if(m_model->dirty()) {
QMessageBox msg; QMessageBox msg;
msg.setText(tr("Do you want to save your changes to this project before closing it?")); msg.setText(tr("Do you want to save your changes to this project before closing it?"));
msg.setInformativeText(tr("Unsaved changes will be lost unless you save.")); msg.setInformativeText(tr("Unsaved changes will be lost unless you save."));
@ -73,7 +73,7 @@ void Project::closeEvent(QCloseEvent *event)
switch(msg.exec()) { switch(msg.exec()) {
case QMessageBox::Save: case QMessageBox::Save:
model->save(); m_model->save();
break; break;
case QMessageBox::Discard: case QMessageBox::Discard:
break; break;

View File

@ -16,8 +16,6 @@
#include <QMdiSubWindow> #include <QMdiSubWindow>
#include <QMessageBox> #include <QMessageBox>
#include "bindings.h"
#include "../ui/ui_about.h" #include "../ui/ui_about.h"
#include "../ui/ui_license.h" #include "../ui/ui_license.h"
#include "../ui/ui_mapprops.h" #include "../ui/ui_mapprops.h"
@ -25,69 +23,42 @@
#include "../ui/ui_menu.h" #include "../ui/ui_menu.h"
#include "../ui/ui_project.h" #include "../ui/ui_project.h"
enum class ProjectType #include "bindings.h"
{
Map, #pragma clang diagnostic warning "-Winconsistent-missing-override"
};
class Project;
using byte = std::uint8_t; using byte = std::uint8_t;
class IProjectModel class MapModel final : public IMapModel
{
public:
virtual ~IProjectModel() {}
virtual bool isDirty() const = 0;
virtual bool open(QString const &path) = 0;
virtual bool save() const = 0;
virtual bool saveAs(QString const &path) const = 0;
};
class IProjectView
{
public:
virtual ~IProjectView() {}
};
class CMapModel final : public IMapModel,
public IProjectModel
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CMapModel(Project *parent); explicit MapModel(Project *parent);
~CMapModel() override; ~MapModel() override;
bool isDirty() const override;
bool open(QString const &path) override;
bool save() const override;
bool saveAs(QString const &path) const override;
public slots: public slots:
void deselect(); void deselect() override;
void select(QModelIndex const &index); void select(QModelIndex const &index) override;
signals:
void deselected();
void selected(std::uint16_t index);
private: private:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) QVariant data(const QModelIndex &index, int role) const override;
const override;
}; };
class CMapView final : public QWidget, class MapView final : public QWidget,
public IProjectView, public IProjectView,
private Ui::CMapView private Ui::MapView
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CMapView(Project *parent); explicit MapView(Project *parent);
~CMapView(); ~MapView();
private: private:
CMapModel *const m_mapModel; MapModel *const m_mapModel;
}; };
class MapProps final : public QDialog, class MapProps final : public QDialog,
@ -102,7 +73,7 @@ public:
void accept() override; void accept() override;
private: private:
CMapModel *const m_mapModel; MapModel *const m_mapModel;
}; };
class Menu final : public QMainWindow, class Menu final : public QMainWindow,
@ -137,24 +108,28 @@ class Project final : public QMdiSubWindow,
private Ui::Project private Ui::Project
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(Type type READ type CONSTANT)
Q_PROPERTY(IProjectModel *model READ model CONSTANT)
Q_PROPERTY(MapModel *mapModel READ mapModel CONSTANT)
public: public:
explicit Project(ProjectType type); enum Type {Map};
Q_ENUM(Type)
explicit Project(Type type);
~Project(); ~Project();
ProjectType getType() const; Type type() const;
IProjectModel *model() const;
ProjectModel *getModel() const; MapModel *mapModel() const;
MapModel *getMapModel() const;
protected: protected:
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;
private: private:
ProjectType const type; Type const m_type;
IProjectModel *const m_model;
ProjectModel *const model; IProjectView *const m_view;
ProjectView *const view;
}; };
#pragma clang diagnostic push #pragma clang diagnostic push

View File

@ -1,8 +1,10 @@
//! GUI implementation. //! GUI implementation.
mod mapmodel; mod mapmodel;
mod mapview;
mod qobj; mod qobj;
pub use self::mapmodel::IMapModel; pub use self::mapmodel::IMapModel;
pub use self::mapview::IMapView;
// EOF // EOF

View File

@ -38,7 +38,7 @@ impl IMapModelTrait for IMapModel
eprintln!("new IMapModel"); eprintln!("new IMapModel");
} }
Self{emit, map: EntryDataMap::default(), selected: None} Self{emit, map: EntryDataMap::default(), selected: None, dirty: false}
} }
/// Returns the emitter of `self`. /// Returns the emitter of `self`.
@ -99,7 +99,9 @@ impl IMapModelTrait for IMapModel
} }
/// Returns `true` if the file has been modified from its original state. /// Returns `true` if the file has been modified from its original state.
fn is_dirty(&self) -> bool {false} fn dirty(&self) -> bool {self.dirty}
fn set_dirty(&mut self, dirty: bool) {self.dirty = dirty;}
fn deselect(&mut self) {self.selected = None;} fn deselect(&mut self) {self.selected = None;}
@ -127,6 +129,7 @@ pub struct IMapModel {
emit: IMapModelEmitter, emit: IMapModelEmitter,
map: EntryDataMap, map: EntryDataMap,
selected: Option<u16>, selected: Option<u16>,
dirty: bool,
} }
// EOF // EOF

View File

@ -0,0 +1,35 @@
//! Map view.
use super::qobj::*;
impl IMapViewTrait for IMapView
{
/// Returns a new `IMapView` instance.
fn new(emit: IMapViewEmitter) -> Self
{
if cfg!(debug_assertions) {
eprintln!("new IMapView");
}
Self{emit}
}
/// Returns the emitter of `self`.
fn emit(&mut self) -> &mut IMapViewEmitter {&mut self.emit}
}
impl Drop for IMapView
{
fn drop(&mut self)
{
if cfg!(debug_assertions) {
eprintln!("drop IMapView");
}
}
}
pub struct IMapView {
emit: IMapViewEmitter,
}
// EOF