tycho: see? I told you it was magic

master
an 2019-06-17 06:32:22 -04:00
parent 1ac6b2df9d
commit c2339138a8
14 changed files with 353 additions and 193 deletions

View File

@ -29,7 +29,7 @@ add_library(
cc_source/main.cc
cc_source/mapprops.cc
cc_source/menu.cc
cc_source/projectview.cc
cc_source/project.cc
resources/resources.qrc
ui/about.ui
ui/license.ui
@ -37,7 +37,7 @@ add_library(
ui/mapview.ui
ui/menu.ui
ui/points.ui
ui/projectview.ui
ui/project.ui
)
set_target_properties(

View File

@ -6,21 +6,29 @@
"implementationModule": "qimpl"
},
"objects": {
"ProjectModel": {
"type": "List",
"MapModel": {
"type": "Tree",
"functions": {
"open": {
"return": "bool",
"mut": true,
"arguments": [{
"name": "fname",
"name": "path",
"type": "QString"
}]
},
"save": {
"return": "void",
"return": "bool",
"mut": false
},
"saveAs": {
"return": "bool",
"mut": false,
"arguments": [{
"name": "path",
"type": "QString"
}]
},
"isDirty": {
"return": "bool",
"mut": false

View File

@ -4,19 +4,18 @@
#include "../ui/ui_mapprops.h"
class ProjectModel;
class MapModel;
class MapProps : public QDialog, private Ui::MapProps
{
Q_OBJECT
public:
explicit MapProps(QSharedPointer<ProjectModel> proj,
QWidget *parent = nullptr);
explicit MapProps(MapModel *mapModel, QWidget *parent = nullptr);
~MapProps();
private:
QSharedPointer<ProjectModel> proj;
MapModel *mapModel;
};
// EOF

View File

@ -5,7 +5,7 @@
#include "../ui/ui_menu.h"
class ProjectView;
class Project;
class Menu : public QMainWindow, private Ui::Menu
{
@ -27,9 +27,9 @@ protected:
void openLicense(QWidget *parent);
private:
ProjectView *activeProject() const;
Project *activeProject() const;
QMdiSubWindow *activeSubWindow() const;
void addProject(ProjectView *view);
void addProject(Project *proj);
};
// EOF

View File

@ -2,24 +2,50 @@
#include <QMdiSubWindow>
#include "bindings.h"
#include "../ui/ui_projectview.h"
#include "../ui/ui_project.h"
class ProjectView : public QMdiSubWindow, private Ui::ProjectView
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 ProjectView(QWidget *parent = nullptr);
~ProjectView();
explicit Project(ProjectModel &&model, QWidget *parent = nullptr);
~Project();
QSharedPointer<ProjectModel> model();
ProjectModel model;
protected:
void closeEvent(QCloseEvent *event) override;
private:
QSharedPointer<ProjectModel> proj;
};
// EOF

View File

@ -4,6 +4,8 @@
#include <cstdint>
#include <cstddef>
#include "bindings.h"
#ifdef TYCHO_DEBUG_PRINT
#define dbgPrint(...) qDebug(__VA_ARGS__)
#else

View File

@ -3,9 +3,9 @@
#include <QDialogButtonBox>
MapProps::MapProps(QSharedPointer<ProjectModel> _proj, QWidget *parent) :
MapProps::MapProps(MapModel *_mapModel, QWidget *parent) :
QDialog(parent),
proj(_proj)
mapModel(_mapModel)
{
setupUi(this);

View File

@ -32,9 +32,9 @@ Menu::~Menu()
void Menu::mapNew()
{
QScopedPointer view{new ProjectView};
QScopedPointer proj{new Project(new MapModel)};
addProject(view.take());
addProject(proj.take());
}
void Menu::mapOpen()
@ -46,10 +46,10 @@ void Menu::mapOpen()
QString(),
tr("Marathon Map files (*.scen *.sceA Map)"));
QScopedPointer view{new ProjectView};
QScopedPointer proj{new Project(new MapModel)};
if(view->model()->open(fname)) {
addProject(view.take());
if(proj->model.open(fname)) {
addProject(proj.take());
}
}
@ -96,18 +96,18 @@ void Menu::openLicense(QWidget *parent)
void Menu::openMapProperties()
{
auto view = activeProject();
auto proj = activeProject();
if(view) {
MapProps props{view->model(), view};
if(proj && proj->model.type() == ProjectModel::Map) {
MapProps props{proj->model.getMap(), proj};
props.exec();
}
}
void Menu::updateActions()
{
auto view = activeProject();
bool active = view != nullptr;
auto proj = activeProject();
bool active = proj != nullptr;
actionClose->setEnabled(active);
actionMapProps->setEnabled(active);
@ -127,9 +127,9 @@ void Menu::closeEvent(QCloseEvent *event)
event->accept();
}
ProjectView *Menu::activeProject() const
Project *Menu::activeProject() const
{
return qobject_cast<ProjectView *>(activeSubWindow());
return qobject_cast<Project *>(activeSubWindow());
}
QMdiSubWindow *Menu::activeSubWindow() const
@ -137,9 +137,9 @@ QMdiSubWindow *Menu::activeSubWindow() const
return mdiArea->activeSubWindow();
}
void Menu::addProject(ProjectView *view)
void Menu::addProject(Project *proj)
{
auto win = mdiArea->addSubWindow(view);
auto win = mdiArea->addSubWindow(proj);
win->showMaximized();
}

View File

@ -0,0 +1,128 @@
#include "tycho.h"
#include "project.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;
}
}
ProjectModel::Type ProjectModel::type() const
{
return modelType;
}
QAbstractItemModel *ProjectModel::getAbstract() const
{
switch(modelType) {
case Map: return modelMap;
}
Q_UNREACHABLE();
}
MapModel *ProjectModel::getMap() const
{
return modelType == Map ? modelMap : nullptr;
}
bool ProjectModel::isDirty() const
{
switch(modelType) {
case Map: return modelMap->isDirty();
}
Q_UNREACHABLE();
}
bool ProjectModel::open(QString const &path)
{
switch(modelType) {
case Map: return modelMap->open(path);
}
Q_UNREACHABLE();
}
bool ProjectModel::saveAs(QString const &path) const
{
switch(modelType) {
case Map: return modelMap->saveAs(path);
}
Q_UNREACHABLE();
}
bool ProjectModel::save() const
{
switch(modelType) {
case Map: return modelMap->save();
}
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);
treeView->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:
assert(true);
break;
}
}
event->accept();
}
// EOF

View File

@ -1,62 +0,0 @@
#include "tycho.h"
#include "project.h"
#include <QCloseEvent>
#include <QMessageBox>
ProjectView::ProjectView(QWidget *parent) :
QMdiSubWindow(parent),
proj(new ProjectModel)
{
auto widget = new QWidget(this);
setupUi(widget);
setWidget(widget);
setAttribute(Qt::WA_DeleteOnClose);
listView->setModel(proj.data());
dbgPrintFunc();
}
ProjectView::~ProjectView()
{
dbgPrintFunc();
}
QSharedPointer<ProjectModel> ProjectView::model()
{
return proj;
}
void ProjectView::closeEvent(QCloseEvent *event)
{
if(proj->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:
proj->save();
break;
case QMessageBox::Discard:
break;
case QMessageBox::Cancel:
event->ignore();
return;
default:
assert(true);
break;
}
}
event->accept();
}
// EOF

View File

@ -1,7 +1,7 @@
//! Qt implementation.
mod project;
mod map;
pub use self::project::*;
pub use self::map::*;
// EOF

View File

@ -0,0 +1,138 @@
//! Map model.
use crate::qintr::*;
//use memmap::Mmap;
use maraiah::map;
pub struct MapModel
{
emit: MapModelEmitter,
model: MapModelTree,
}
impl Drop for MapModel
{
fn drop(&mut self)
{
if cfg!(debug_assertions) {
eprintln!("drop MapModel");
}
}
}
impl MapModelTrait for MapModel
{
/// Returns a new `MapModel` instance.
fn new(emit: MapModelEmitter, model: MapModelTree) -> MapModel
{
if cfg!(debug_assertions) {
eprintln!("new MapModel");
}
MapModel{emit, model}
}
/// Returns the emitter of `self`.
fn emit(&mut self) -> &mut MapModelEmitter
{
&mut self.emit
}
/// Checks if `row` exists in the leaf `index`.
fn check_row(&self, index: usize, _row: usize) -> Option<usize>
{
None
}
/// Returns the row `index` is in.
fn row(&self, index: usize) -> usize
{
index
}
/// Returns the number of rows in `index`.
fn row_count(&self, index: Option<usize>) -> usize
{
match index {
Some(_) => 0,
None => 7,
}
}
/// Returns the leaf index of `row` in the leaf `index`.
fn index(&self, index: Option<usize>, row: usize) -> usize
{
match index {
Some(_) => unreachable!(),
None => row,
}
}
/// Returns the parent index of the leaf `index`, if any.
fn parent(&self, _index: usize) -> Option<usize>
{
// no parents!
None
}
fn row_name(&self, row: usize) -> u64
{
row as u64 + 1
}
fn some_number(&self, row: usize) -> u64
{
69420
}
/// Opens the map file at `path`.
fn open(&mut self, path: String) -> bool
{
if cfg!(debug_assertions) {
eprintln!("opening project: {}", &path);
}
/*
let fp = std::fs::File::open(path);
let fp = if let Ok(fp) = fp {fp} else {return false;};
let mm = unsafe {Mmap::map(&fp)};
let mm = if let Ok(mm) = mm {mm} else {return false;};
if let Ok(wad) = map::read(&mm) {
self.wad.replace(Some(wad));
return true;
}
*/
false
}
/// Saves the project into the original file.
fn save(&self) -> bool
{
if cfg!(debug_assertions) {
eprintln!("saving project");
}
false
}
/// Saves the project into `path`.
fn save_as(&self, path: String) -> bool
{
if cfg!(debug_assertions) {
eprintln!("saving project as {}", path);
}
false
}
/// Returns `true` if the file has been modified from its original state.
fn is_dirty(&self) -> bool
{
false
}
}
// EOF

View File

@ -1,88 +0,0 @@
//! Project management.
use crate::qintr::*;
//use memmap::Mmap;
use maraiah::map;
pub struct ProjectModel
{
emit: ProjectModelEmitter,
}
impl Drop for ProjectModel
{
fn drop(&mut self)
{
if cfg!(debug_assertions) {
eprintln!("drop ProjectModel");
}
}
}
impl ProjectModelTrait for ProjectModel
{
fn new(emit: ProjectModelEmitter, _: ProjectModelList) -> ProjectModel
{
if cfg!(debug_assertions) {
eprintln!("new ProjectModel");
}
ProjectModel{emit}
}
fn emit(&mut self) -> &mut ProjectModelEmitter
{
&mut self.emit
}
fn row_count(&self) -> usize
{
7
}
fn row_name(&self, row: usize) -> u64
{
row as u64 + 1
}
fn some_number(&self, row: usize) -> u64
{
69420
}
fn open(&mut self, path: String) -> bool
{
if cfg!(debug_assertions) {
eprintln!("opening project: {}", &path);
}
/*
let fp = std::fs::File::open(path);
let fp = if let Ok(fp) = fp {fp} else {return false;};
let mm = unsafe {Mmap::map(&fp)};
let mm = if let Ok(mm) = mm {mm} else {return false;};
if let Ok(wad) = map::read(&mm) {
self.wad.replace(Some(wad));
return true;
}
*/
false
}
fn save(&self)
{
if cfg!(debug_assertions) {
eprintln!("saving project");
}
}
fn is_dirty(&self) -> bool
{
false
}
}
// EOF

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ProjectView</class>
<widget class="QWidget" name="ProjectView">
<class>Project</class>
<widget class="QWidget" name="Project">
<property name="geometry">
<rect>
<x>0</x>
@ -15,7 +15,16 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QListView" name="listView">
<widget class="QTreeView" name="treeView">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>