tycho: rewrite things to simplify

master
an 2019-07-02 17:57:10 -04:00
parent e3c0b0dd7d
commit 11cfc909f8
18 changed files with 332 additions and 364 deletions

View File

@ -23,17 +23,13 @@ add_library(
SHARED
$ENV{OUT_DIR}/bindings.cc
$ENV{OUT_DIR}/bindings.h
cc_headers/mapmodel.h
cc_headers/mapprops.h
cc_headers/menu.h
cc_headers/project.h
cc_headers/tycho.h
cc_source/cc.cc
cc_source/main.cc
cc_source/mapmodel.cc
cc_source/mapprops.cc
cc_source/menu.cc
cc_source/project.cc
cc/main.cc
cc/mapmodel.cc
cc/mapprops.cc
cc/mapview.cc
cc/menu.cc
cc/project.cc
cc/tycho.h
resources/resources.qrc
ui/about.ui
ui/license.ui
@ -54,7 +50,6 @@ set_target_properties(
target_include_directories(
maraiah-tycho-hermes
PUBLIC
cc_headers
$ENV{OUT_DIR}
)

View File

@ -16,7 +16,7 @@ fn main()
let mut config = cmake::Config::new(".");
if cfg!(debug_assertions) {
config.cxxflag("-DTYCHO_DEBUG_PRINT");
config.cxxflag("-DTYCHO_DEBUG_ASSERTIONS");
}
let destination = config.build();

View File

@ -1,8 +1,11 @@
#include "tycho.h"
#include "menu.h"
#include <QApplication>
extern "C" {
void critical_msg(char const *title, char const *msg)
{
QMessageBox::critical(nullptr, QObject::tr(title), QObject::tr(msg));
}
int main_cc(char *app_path)
{
dbgPrint("cc entry");

73
tycho/cc/mapmodel.cc Normal file
View File

@ -0,0 +1,73 @@
#include "tycho.h"
MapModel::MapModel(QObject *parent) :
AbstractMapModel(parent),
ProjectModel()
{
dbgPrintFunc();
}
MapModel::~MapModel()
{
dbgPrintFunc();
}
ProjectModel::Type MapModel::type() const
{
return ProjectModel::Map;
}
QAbstractItemModel const *MapModel::getAbstract() const
{
return this;
}
QAbstractItemModel *MapModel::getAbstract()
{
return this;
}
MapModel const *MapModel::getMap() const
{
return this;
}
MapModel *MapModel::getMap()
{
return this;
}
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);
}
QVariant MapModel::data(const QModelIndex &index, int role) const
{
switch(role) {
case Qt::DecorationRole: {
auto name = propIcon(index.row());
auto icon = name.front() == ':' ? QIcon(name) : QIcon::fromTheme(name);
return QVariant::fromValue(icon);
}
default:
return AbstractMapModel::data(index, role);
}
}
// EOF

View File

@ -1,7 +1,4 @@
#include "tycho.h"
#include "mapprops.h"
#include <QDialogButtonBox>
MapProps::MapProps(MapModel *_mapModel, QWidget *parent) :
QDialog(parent),

16
tycho/cc/mapview.cc Normal file
View File

@ -0,0 +1,16 @@
#include "tycho.h"
MapView::MapView(MapModel *mapModel, QWidget *parent) :
QWidget(parent)
{
setupUi(this);
dbgPrintFunc();
}
MapView::~MapView()
{
dbgPrintFunc();
}
// EOF

View File

@ -1,16 +1,4 @@
#include "tycho.h"
#include "mapprops.h"
#include "menu.h"
#include "project.h"
#include "mapmodel.h"
#include "../ui/ui_about.h"
#include "../ui/ui_license.h"
#include <QCloseEvent>
#include <QFileDialog>
#include <QMdiSubWindow>
#include <QMessageBox>
#include <iostream>
Menu::Menu(QWidget *parent) :
QMainWindow(parent)
@ -54,7 +42,7 @@ void Menu::mapOpen()
if(!fname.isEmpty()) {
QScopedPointer proj{new Project(new MapModel)};
if(proj->model.open(fname)) {
if(proj->model->open(fname)) {
addProject(proj.take());
}
}
@ -110,8 +98,8 @@ void Menu::openMapProperties()
{
auto proj = activeProject();
if(proj && proj->model.type() == ProjectModel::Map) {
MapProps props{proj->model.getMap(), proj};
if(proj && proj->model->type() == ProjectModel::Map) {
MapProps props{proj->model->getMap(), proj};
props.exec();
}
}

52
tycho/cc/project.cc Normal file
View File

@ -0,0 +1,52 @@
#include "tycho.h"
Project::Project(ProjectModel *_model, QWidget *parent) :
QMdiSubWindow(parent),
model(_model)
{
auto widget = new QWidget(this);
setupUi(widget);
setWidget(widget);
setAttribute(Qt::WA_DeleteOnClose);
listView->setModel(model->getAbstract());
dbgPrintFunc();
}
Project::~Project()
{
dbgPrintFunc();
}
void Project::closeEvent(QCloseEvent *event)
{
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."));
msg.setStandardButtons(QMessageBox::Save |
QMessageBox::Discard |
QMessageBox::Cancel);
msg.setDefaultButton(QMessageBox::Save);
switch(msg.exec()) {
case QMessageBox::Save:
model->save();
break;
case QMessageBox::Discard:
break;
case QMessageBox::Cancel:
event->ignore();
return;
default:
Q_UNREACHABLE();
}
}
event->accept();
}
// EOF

172
tycho/cc/tycho.h Normal file
View File

@ -0,0 +1,172 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <vector>
#include <QApplication>
#include <QCloseEvent>
#include <QDialog>
#include <QDialogButtonBox>
#include <QFileDialog>
#include <QIcon>
#include <QMainWindow>
#include <QMdiSubWindow>
#include <QMessageBox>
#include "../ui/ui_about.h"
#include "../ui/ui_license.h"
#include "../ui/ui_mapprops.h"
#include "../ui/ui_mapview.h"
#include "../ui/ui_menu.h"
#include "../ui/ui_project.h"
#include "bindings.h"
#ifdef TYCHO_DEBUG_ASSERTIONS
#define dbgPrint(...) qDebug(__VA_ARGS__)
#else
#define dbgPrint(...)
#endif
#define dbgPrintFunc() dbgPrint("%s", __func__)
// TODO: namespace Tycho {
class MapModel;
class MapProps;
class MapView;
class Menu;
class Project;
class ProjectModel;
class MapProps : public QDialog, private Ui::MapProps
{
Q_OBJECT
public:
explicit MapProps(MapModel *mapModel, QWidget *parent = nullptr);
~MapProps();
private:
MapModel *mapModel;
};
class MapView : public QWidget, private Ui::MapView
{
Q_OBJECT
public:
explicit MapView(MapModel *mapModel, QWidget *parent = nullptr);
~MapView();
};
class Project : public QMdiSubWindow, private Ui::Project
{
Q_OBJECT
public:
explicit Project(ProjectModel *model, QWidget *parent = nullptr);
~Project();
QSharedPointer<ProjectModel> model;
protected:
void closeEvent(QCloseEvent *event) override;
};
class ProjectModel
{
public:
enum Type
{
Invalid,
Map,
};
virtual ~ProjectModel() {}
virtual Type type() const = 0;
virtual QAbstractItemModel const *getAbstract() const = 0;
virtual QAbstractItemModel *getAbstract() = 0;
virtual MapModel const *getMap() const = 0;
virtual MapModel *getMap() = 0;
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 MapModel final : private AbstractMapModel, public ProjectModel
{
Q_OBJECT
public:
explicit MapModel(QObject *parent = nullptr);
~MapModel() override;
ProjectModel::Type type() const override;
QAbstractItemModel const *getAbstract() const override;
QAbstractItemModel *getAbstract() override;
MapModel const *getMap() const override;
MapModel *getMap() override;
bool isDirty() const override;
bool open(QString const &path) override;
bool save() const override;
bool saveAs(QString const &path) const override;
private:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole)
const override;
};
class Menu : public QMainWindow, private Ui::Menu
{
Q_OBJECT
public:
explicit Menu(QWidget *parent = nullptr);
~Menu();
public slots:
void mapNew();
void mapOpen();
void openAbout();
void openAboutQt();
void openMapProperties();
void updateActions();
protected:
void closeEvent(QCloseEvent *event) override;
void openLicense(QWidget *parent);
private:
Project *activeProject() const;
QMdiSubWindow *activeSubWindow() const;
void addProject(Project *proj);
};
constexpr std::uint32_t fourCC(std::uint8_t a,
std::uint8_t b,
std::uint8_t c,
std::uint8_t d)
{
return (a << 24) | (b << 16) | (c << 8) | d;
}
extern "C" {
char const *tychoAuthors();
char const *tychoHomepage();
char const *tychoLicenseText();
char const *tychoRepository();
char const *tychoVersion();
}
// }
// EOF

View File

@ -1,17 +0,0 @@
#pragma once
#include "bindings.h"
class MapModel : public AbstractMapModel
{
Q_OBJECT
public:
explicit MapModel(QObject *parent = nullptr);
~MapModel();
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole)
const override;
};
// EOF

View File

@ -1,21 +0,0 @@
#pragma once
#include <QDialog>
#include "../ui/ui_mapprops.h"
class MapModel;
class MapProps : public QDialog, private Ui::MapProps
{
Q_OBJECT
public:
explicit MapProps(MapModel *mapModel, QWidget *parent = nullptr);
~MapProps();
private:
MapModel *mapModel;
};
// EOF

View File

@ -1,36 +0,0 @@
#pragma once
#include <QMainWindow>
#include <vector>
#include "../ui/ui_menu.h"
class Project;
class Menu : public QMainWindow, private Ui::Menu
{
Q_OBJECT
public:
explicit Menu(QWidget *parent = nullptr);
~Menu();
public slots:
void mapNew();
void mapOpen();
void openAbout();
void openAboutQt();
void openMapProperties();
void updateActions();
protected:
void closeEvent(QCloseEvent *event) override;
void openLicense(QWidget *parent);
private:
Project *activeProject() const;
QMdiSubWindow *activeSubWindow() const;
void addProject(Project *proj);
};
// EOF

View File

@ -1,53 +0,0 @@
#pragma once
#include <QMdiSubWindow>
#include "../ui/ui_project.h"
class MapModel;
class ProjectModel
{
public:
enum Type
{
Invalid,
Map,
};
ProjectModel(MapModel *ptr);
ProjectModel(ProjectModel &&o);
ProjectModel() = delete;
ProjectModel(ProjectModel &) = delete;
~ProjectModel();
Type type() const;
QAbstractItemModel *getAbstract() const;
MapModel *getMap() const;
bool isDirty() const;
bool open(QString const &path);
bool saveAs(QString const &path) const;
bool save() const;
private:
Type modelType;
MapModel *modelMap;
};
class Project : public QMdiSubWindow, private Ui::Project
{
Q_OBJECT
public:
explicit Project(ProjectModel &&model, QWidget *parent = nullptr);
~Project();
ProjectModel model;
protected:
void closeEvent(QCloseEvent *event) override;
};
// EOF

View File

@ -1,33 +0,0 @@
#pragma once
#include <QtGlobal>
#include <cstdint>
#include <cstddef>
#include "bindings.h"
#ifdef TYCHO_DEBUG_PRINT
#define dbgPrint(...) qDebug(__VA_ARGS__)
#else
#define dbgPrint(...)
#endif
#define dbgPrintFunc() dbgPrint("%s", __func__)
constexpr std::uint32_t fourCC(std::uint8_t a,
std::uint8_t b,
std::uint8_t c,
std::uint8_t d)
{
return (a << 24) | (b << 16) | (c << 8) | d;
}
extern "C" {
char const *tychoAuthors();
char const *tychoHomepage();
char const *tychoLicenseText();
char const *tychoRepository();
char const *tychoVersion();
}
// EOF

View File

@ -1,10 +0,0 @@
#include "tycho.h"
#include <QMessageBox>
extern "C" {
void critical_msg(char const *title, char const *msg) {
QMessageBox::critical(nullptr, QObject::tr(title), QObject::tr(msg));
}
}
// EOF

View File

@ -1,28 +0,0 @@
#include "tycho.h"
#include "mapmodel.h"
#include <QIcon>
MapModel::MapModel(QObject *parent) :
AbstractMapModel(parent)
{
}
MapModel::~MapModel()
{
}
QVariant MapModel::data(const QModelIndex &index, int role) const
{
switch(role) {
case Qt::DecorationRole: {
auto name = propIcon(index.row());
auto icon = name.front() == ':' ? QIcon(name) : QIcon::fromTheme(name);
return QVariant::fromValue(icon);
}
default:
return AbstractMapModel::data(index, role);
}
}
// EOF

View File

@ -1,133 +0,0 @@
#include "tycho.h"
#include "project.h"
#include "mapmodel.h"
#include <QCloseEvent>
#include <QMessageBox>
ProjectModel::ProjectModel(MapModel *ptr) :
modelType(Map),
modelMap(ptr)
{
Q_ASSERT(modelMap != nullptr);
}
ProjectModel::ProjectModel(ProjectModel &&o) :
modelType(o.modelType),
modelMap(o.modelMap)
{
o.modelType = Invalid;
}
ProjectModel::~ProjectModel()
{
switch(modelType) {
case Map: delete modelMap; break;
case Invalid: break;
}
}
ProjectModel::Type ProjectModel::type() const
{
return modelType;
}
QAbstractItemModel *ProjectModel::getAbstract() const
{
switch(modelType) {
case Map: return modelMap;
case Invalid: Q_UNREACHABLE();
}
}
MapModel *ProjectModel::getMap() const
{
return modelType == Map ? modelMap : nullptr;
}
bool ProjectModel::isDirty() const
{
switch(modelType) {
case Map: return modelMap->isDirty();
case Invalid: Q_UNREACHABLE();
}
Q_UNREACHABLE();
}
bool ProjectModel::open(QString const &path)
{
switch(modelType) {
case Map: return modelMap->open(path);
case Invalid: Q_UNREACHABLE();
}
Q_UNREACHABLE();
}
bool ProjectModel::saveAs(QString const &path) const
{
switch(modelType) {
case Map: return modelMap->saveAs(path);
case Invalid: Q_UNREACHABLE();
}
Q_UNREACHABLE();
}
bool ProjectModel::save() const
{
switch(modelType) {
case Map: return modelMap->save();
case Invalid: Q_UNREACHABLE();
}
Q_UNREACHABLE();
}
Project::Project(ProjectModel &&_model, QWidget *parent) :
QMdiSubWindow(parent),
model(std::move(_model))
{
auto widget = new QWidget(this);
setupUi(widget);
setWidget(widget);
setAttribute(Qt::WA_DeleteOnClose);
listView->setModel(model.getAbstract());
dbgPrintFunc();
}
Project::~Project()
{
dbgPrintFunc();
}
void Project::closeEvent(QCloseEvent *event)
{
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."));
msg.setStandardButtons(QMessageBox::Save |
QMessageBox::Discard |
QMessageBox::Cancel);
msg.setDefaultButton(QMessageBox::Save);
switch(msg.exec()) {
case QMessageBox::Save:
model.save();
break;
case QMessageBox::Discard:
break;
case QMessageBox::Cancel:
event->ignore();
return;
default:
Q_UNREACHABLE();
}
}
event->accept();
}
// EOF

View File

@ -14,6 +14,9 @@
<string>Project</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget" native="true"/>
</item>
<item>
<widget class="QListView" name="listView">
<property name="frameShape">