Compare commits

..

No commits in common. "c01756886b7921f88390c10b30895235bfcc9b10" and "004989ab588a314c6c065ce11c72023884b57e65" have entirely different histories.

15 changed files with 161 additions and 192 deletions

3
.gitmodules vendored
View File

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

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

View File

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

View File

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

View File

@ -1,5 +1,4 @@
{
"beforeHeader": "interface.h",
"cppFile": "",
"rust": {
"dir": "",
@ -7,16 +6,16 @@
"implementationModule": "gui"
},
"objects": {
"IMapModel": {
"AbstractMapModel": {
"type": "List",
"baseClass": "IProjectModel",
"functions": {
"open": {
"return": "bool",
"mut": true,
"arguments": [
{"name": "path", "type": "QString"}
]
"arguments": [{
"name": "path",
"type": "QString"
}]
},
"save": {
"return": "bool",
@ -25,16 +24,22 @@
"saveAs": {
"return": "bool",
"mut": false,
"arguments": [
{"name": "path", "type": "QString"}
]
"arguments": [{
"name": "path",
"type": "QString"
}]
},
"isDirty": {
"return": "bool",
"mut": false
},
"propIcon": {
"return": "QString",
"mut": false,
"arguments": [
{"name": "index", "type": "quint16"}
]
"arguments": [{
"name": "index",
"type": "quint16"
}]
},
"deselect": {
"return": "void",
@ -43,25 +48,19 @@
"select": {
"return": "void",
"mut": true,
"arguments": [
{"name": "index", "type": "quint16"}
]
"arguments": [{
"name": "index",
"type": "quint16"
}]
}
},
"properties": {
"dirty": {"type": "bool", "write": true}
},
"itemProperties": {
"propIndex": {"type": "quint64", "roles": [["display"]]}
}
},
"IMapView": {
"type": "Object",
"functions": {
},
"properties": {
},
"itemProperties": {
"propIndex": {
"type": "quint64",
"roles": [["display"]]
}
}
}
}

View File

@ -1,40 +0,0 @@
#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,7 +1,8 @@
#include "tycho.h"
MapModel::MapModel(Project *parent) :
IMapModel(parent)
AbstractMapModel(static_cast<QWidget *>(parent)),
ProjectModel()
{
dbgPrintFunc();
}
@ -11,9 +12,29 @@ MapModel::~MapModel()
dbgPrintFunc();
}
bool MapModel::isDirty() const
{
return AbstractMapModel::isDirty();
}
bool MapModel::open(QString const &path)
{
return AbstractMapModel::open(path);
}
bool MapModel::save() const
{
return AbstractMapModel::save();
}
bool MapModel::saveAs(QString const &path) const
{
return AbstractMapModel::saveAs(path);
}
void MapModel::deselect()
{
IMapModel::deselect();
AbstractMapModel::deselect();
emit deselected();
}
@ -22,7 +43,7 @@ void MapModel::select(QModelIndex const &index)
{
auto idx = index.internalId();
IMapModel::select(idx);
AbstractMapModel::select(idx);
emit selected(idx);
}
@ -37,7 +58,7 @@ QVariant MapModel::data(const QModelIndex &index, int role) const
return QVariant::fromValue(icon);
}
default:
return IMapModel::data(index, role);
return AbstractMapModel::data(index, role);
}
}

View File

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

View File

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

View File

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

View File

@ -1,26 +1,26 @@
#include "tycho.h"
static
IProjectModel *makeModel(Project *proj)
ProjectModel *makeModel(Project *proj)
{
switch(proj->type()) {
case Project::Map: return new MapModel(proj);
switch(proj->getType()) {
case ProjectType::Map: return new MapModel(proj);
}
}
static
IProjectView *makeView(Project *proj)
ProjectView *makeView(Project *proj)
{
switch(proj->type()) {
case Project::Map: return new MapView(proj);
switch(proj->getType()) {
case ProjectType::Map: return new MapView(proj);
}
}
Project::Project(Type type) :
Project::Project(ProjectType _type) :
QMdiSubWindow(),
m_type(type),
m_model(makeModel(this)),
m_view(makeView(this))
type(_type),
model(makeModel(this)),
view(makeView(this))
{
auto widget = new QWidget(this);
@ -29,12 +29,12 @@ Project::Project(Type type) :
setWidget(widget);
setAttribute(Qt::WA_DeleteOnClose);
listView->setModel(m_model);
verticalLayout->insertWidget(0, dynamic_cast<QWidget *>(m_view));
listView->setModel(dynamic_cast<QAbstractItemModel *>(model));
verticalLayout->insertWidget(0, dynamic_cast<QWidget *>(view));
connect(listView,
SIGNAL(doubleClicked(QModelIndex const &)),
m_model,
dynamic_cast<QObject *>(model),
SLOT(select(QModelIndex const &)));
dbgPrintFunc();
@ -45,24 +45,24 @@ Project::~Project()
dbgPrintFunc();
}
Project::Type Project::type() const
ProjectType Project::getType() const
{
return m_type;
return type;
}
IProjectModel *Project::model() const
ProjectModel *Project::getModel() const
{
return m_model;
return model;
}
MapModel *Project::mapModel() const
MapModel *Project::getMapModel() const
{
return dynamic_cast<MapModel *>(m_model);
return dynamic_cast<MapModel *>(model);
}
void Project::closeEvent(QCloseEvent *event)
{
if(m_model->dirty()) {
if(model->isDirty()) {
QMessageBox msg;
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."));
@ -73,7 +73,7 @@ void Project::closeEvent(QCloseEvent *event)
switch(msg.exec()) {
case QMessageBox::Save:
m_model->save();
model->save();
break;
case QMessageBox::Discard:
break;

View File

@ -16,6 +16,8 @@
#include <QMdiSubWindow>
#include <QMessageBox>
#include "bindings.h"
#include "../ui/ui_about.h"
#include "../ui/ui_license.h"
#include "../ui/ui_mapprops.h"
@ -23,15 +25,43 @@
#include "../ui/ui_menu.h"
#include "../ui/ui_project.h"
#include "bindings.h"
#pragma clang diagnostic warning "-Winconsistent-missing-override"
// Types ---------------------------------------------------------------------|
class MapModel;
class MapProps;
class MapView;
class Menu;
class Project;
enum class ProjectType
{
Map,
};
using byte = std::uint8_t;
class MapModel final : public IMapModel
// Interfaces ----------------------------------------------------------------|
class ProjectModel
{
public:
virtual ~ProjectModel() {}
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 ProjectView
{
public:
virtual ~ProjectView() {}
};
// Implementations -----------------------------------------------------------|
class MapModel final : public AbstractMapModel, public ProjectModel
{
Q_OBJECT
@ -39,17 +69,25 @@ public:
explicit MapModel(Project *parent);
~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:
void deselect() override;
void select(QModelIndex const &index) override;
void deselect();
void select(QModelIndex const &index);
signals:
void deselected();
void selected(std::uint16_t index);
private:
QVariant data(const QModelIndex &index, int role) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole)
const override;
};
class MapView final : public QWidget,
public IProjectView,
private Ui::MapView
class MapView final : public QWidget, public ProjectView, private Ui::MapView
{
Q_OBJECT
@ -58,11 +96,12 @@ public:
~MapView();
private:
MapModel *const m_mapModel;
MapModel *const mapModel;
};
class MapProps final : public QDialog,
private Ui::MapProps
// UI ------------------------------------------------------------------------|
class MapProps final : public QDialog, private Ui::MapProps
{
Q_OBJECT
@ -73,11 +112,10 @@ public:
void accept() override;
private:
MapModel *const m_mapModel;
MapModel *const mapModel;
};
class Menu final : public QMainWindow,
private Ui::Menu
class Menu final : public QMainWindow, private Ui::Menu
{
Q_OBJECT
@ -104,34 +142,31 @@ private:
void addProject(Project *proj);
};
class Project final : public QMdiSubWindow,
private Ui::Project
class Project final : public QMdiSubWindow, private Ui::Project
{
Q_OBJECT
Q_PROPERTY(Type type READ type CONSTANT)
Q_PROPERTY(IProjectModel *model READ model CONSTANT)
Q_PROPERTY(MapModel *mapModel READ mapModel CONSTANT)
public:
enum Type {Map};
Q_ENUM(Type)
explicit Project(Type type);
explicit Project(ProjectType type);
~Project();
Type type() const;
IProjectModel *model() const;
MapModel *mapModel() const;
ProjectType getType() const;
ProjectModel *getModel() const;
MapModel *getMapModel() const;
protected:
void closeEvent(QCloseEvent *event) override;
private:
Type const m_type;
IProjectModel *const m_model;
IProjectView *const m_view;
ProjectType const type;
ProjectModel *const model;
ProjectView *const view;
};
// Functions -----------------------------------------------------------------|
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat-security"

View File

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

View File

@ -4,7 +4,7 @@ use super::qobj::*;
use maraiah::{backtrace, err::*, map::{self, data::*}};
use crate::cc;
impl IMapModel
impl AbstractMapModel
{
pub fn open_map(path: String) -> ResultS<EntryDataMap>
{
@ -29,20 +29,20 @@ impl IMapModel
*/
}
impl IMapModelTrait for IMapModel
impl AbstractMapModelTrait for AbstractMapModel
{
/// Returns a new `IMapModel` instance.
fn new(emit: IMapModelEmitter, _: IMapModelList) -> Self
/// Returns a new `AbstractMapModel` instance.
fn new(emit: AbstractMapModelEmitter, _: AbstractMapModelList) -> Self
{
if cfg!(debug_assertions) {
eprintln!("new IMapModel");
eprintln!("new AbstractMapModel");
}
Self{emit, map: EntryDataMap::default(), selected: None, dirty: false}
Self{emit, map: EntryDataMap::default(), selected: None}
}
/// Returns the emitter of `self`.
fn emit(&mut self) -> &mut IMapModelEmitter {&mut self.emit}
fn emit(&mut self) -> &mut AbstractMapModelEmitter {&mut self.emit}
fn row_count(&self) -> usize {self.map.len()}
@ -99,9 +99,7 @@ impl IMapModelTrait for IMapModel
}
/// Returns `true` if the file has been modified from its original state.
fn dirty(&self) -> bool {self.dirty}
fn set_dirty(&mut self, dirty: bool) {self.dirty = dirty;}
fn is_dirty(&self) -> bool {false}
fn deselect(&mut self) {self.selected = None;}
@ -115,21 +113,20 @@ impl IMapModelTrait for IMapModel
}
}
impl Drop for IMapModel
impl Drop for AbstractMapModel
{
fn drop(&mut self)
{
if cfg!(debug_assertions) {
eprintln!("drop IMapModel");
eprintln!("drop AbstractMapModel");
}
}
}
pub struct IMapModel {
emit: IMapModelEmitter,
pub struct AbstractMapModel {
emit: AbstractMapModelEmitter,
map: EntryDataMap,
selected: Option<u16>,
dirty: bool,
}
// EOF

View File

@ -1,35 +0,0 @@
//! 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