tycho: make the project view use icons

master
an 2019-07-01 01:25:54 -04:00
parent 14c0ef8f2a
commit e3c0b0dd7d
16 changed files with 219 additions and 76 deletions

View File

@ -9,6 +9,7 @@ set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror")
find_package(
Qt5 5.6.0
@ -22,11 +23,14 @@ 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
@ -60,6 +64,14 @@ target_link_libraries(
Qt5::Widgets
)
target_compile_definitions(
maraiah-tycho-hermes
PUBLIC
-DQT_DEPRECATED_WARNINGS
-DQT_STRICT_ITERATORS
-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT
)
install(TARGETS maraiah-tycho-hermes)
## EOF

View File

@ -6,8 +6,8 @@
"implementationModule": "gui"
},
"objects": {
"MapModel": {
"type": "Tree",
"AbstractMapModel": {
"type": "List",
"functions": {
"open": {
"return": "bool",
@ -32,18 +32,22 @@
"isDirty": {
"return": "bool",
"mut": false
},
"propIcon": {
"return": "QString",
"mut": false,
"arguments": [{
"name": "index",
"type": "quint16"
}]
}
},
"properties": {
},
"itemProperties": {
"rowName": {
"propIndex": {
"type": "quint64",
"roles": [["display"]]
},
"someNumber": {
"type": "quint64",
"roles": [[], ["display"]]
}
}
}

View File

@ -0,0 +1,17 @@
#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

@ -19,6 +19,7 @@ public slots:
void mapNew();
void mapOpen();
void openAbout();
void openAboutQt();
void openMapProperties();
void updateActions();

View File

@ -4,6 +4,8 @@
#include "../ui/ui_project.h"
class MapModel;
class ProjectModel
{
public:

10
tycho/cc_source/cc.cc Normal file
View File

@ -0,0 +1,10 @@
#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

@ -0,0 +1,28 @@
#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

@ -2,12 +2,14 @@
#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) :
@ -44,12 +46,17 @@ void Menu::mapOpen()
this,
tr("Open Map File"),
QString(),
tr("Marathon Map files (*.scen *.sceA Map)"));
tr("Marathon Map files (*.scen *.sceA Map);;"
"Marathon Physics files (*.phys *.phyA Physics);;"
"Aleph One Image files (*.imgA);;"
"All files (*)"));
QScopedPointer proj{new Project(new MapModel)};
if(!fname.isEmpty()) {
QScopedPointer proj{new Project(new MapModel)};
if(proj->model.open(fname)) {
addProject(proj.take());
if(proj->model.open(fname)) {
addProject(proj.take());
}
}
}
@ -77,6 +84,11 @@ void Menu::openAbout()
dlg.exec();
}
void Menu::openAboutQt()
{
QMessageBox::aboutQt(this);
}
void Menu::openLicense(QWidget *parent)
{
QDialog dlg{parent};

View File

@ -1,5 +1,6 @@
#include "tycho.h"
#include "project.h"
#include "mapmodel.h"
#include <QCloseEvent>
#include <QMessageBox>
@ -22,6 +23,7 @@ ProjectModel::~ProjectModel()
{
switch(modelType) {
case Map: delete modelMap; break;
case Invalid: break;
}
}
@ -34,8 +36,8 @@ QAbstractItemModel *ProjectModel::getAbstract() const
{
switch(modelType) {
case Map: return modelMap;
case Invalid: Q_UNREACHABLE();
}
Q_UNREACHABLE();
}
MapModel *ProjectModel::getMap() const
@ -47,6 +49,7 @@ bool ProjectModel::isDirty() const
{
switch(modelType) {
case Map: return modelMap->isDirty();
case Invalid: Q_UNREACHABLE();
}
Q_UNREACHABLE();
}
@ -55,6 +58,7 @@ bool ProjectModel::open(QString const &path)
{
switch(modelType) {
case Map: return modelMap->open(path);
case Invalid: Q_UNREACHABLE();
}
Q_UNREACHABLE();
}
@ -63,6 +67,7 @@ bool ProjectModel::saveAs(QString const &path) const
{
switch(modelType) {
case Map: return modelMap->saveAs(path);
case Invalid: Q_UNREACHABLE();
}
Q_UNREACHABLE();
}
@ -71,6 +76,7 @@ bool ProjectModel::save() const
{
switch(modelType) {
case Map: return modelMap->save();
case Invalid: Q_UNREACHABLE();
}
Q_UNREACHABLE();
}
@ -86,7 +92,7 @@ Project::Project(ProjectModel &&_model, QWidget *parent) :
setWidget(widget);
setAttribute(Qt::WA_DeleteOnClose);
treeView->setModel(model.getAbstract());
listView->setModel(model.getAbstract());
dbgPrintFunc();
}
@ -117,8 +123,7 @@ void Project::closeEvent(QCloseEvent *event)
event->ignore();
return;
default:
assert(true);
break;
Q_UNREACHABLE();
}
}

21
tycho/source/cc.rs Normal file
View File

@ -0,0 +1,21 @@
//! C++ functions.
mod ffi {
extern "C" {
pub fn critical_msg(title: maraiah::ffi::NT, msg: maraiah::ffi::NT);
}
}
pub fn critical_msg<T, U>(title: T, msg: U)
where T: ToString,
U: ToString
{
let title = std::ffi::CString::new(title.to_string()).unwrap();
let msg = std::ffi::CString::new(msg.to_string()).unwrap();
unsafe {
ffi::critical_msg(title.as_ptr(), msg.as_ptr());
}
}
// EOF

View File

@ -1,8 +1,8 @@
//! GUI implementation.
mod ffi;
mod map;
mod qobj;
pub use self::map::MapModel;
pub use self::map::AbstractMapModel;
// EOF

View File

@ -1,69 +1,63 @@
//! Map model.
use super::ffi::*;
use maraiah::map;
use memmap::Mmap;
use super::qobj::*;
use maraiah::{backtrace, err::*, map::{self, data::*}};
use crate::cc;
fn open_f(path: String) -> ResultS<map::Map>
impl AbstractMapModel
{
let fp = std::fs::File::open(path)?;
let mm = unsafe { Mmap::map(&fp) }?;
pub fn open_map(path: String) -> ResultS<EntryDataMap>
{
let mut fp = maraiah::file::open_mac(path)?;
map::read(&mm)
let map = map::head::read(&mut fp)?;
let ent = map::entr::read_all(&map)?;
map::data::read_all(map.head(), &ent)
}
pub fn get(&self, index: usize) -> (&u16, &EntryData)
{
self.map.iter().nth(index).unwrap()
}
/*
pub fn get_mut(&mut self, index: usize) -> (&u16, &mut EntryData)
{
self.map.iter_mut().nth(index).unwrap()
}
*/
}
impl MapModelTrait for MapModel
impl AbstractMapModelTrait for AbstractMapModel
{
/// Returns a new `MapModel` instance.
fn new(emit: MapModelEmitter, model: MapModelTree) -> Self
/// Returns a new `AbstractMapModel` instance.
fn new(emit: AbstractMapModelEmitter, _: AbstractMapModelList) -> Self
{
if cfg!(debug_assertions) {
eprintln!("new MapModel");
eprintln!("new AbstractMapModel");
}
Self { emit,
model,
map: map::Map::default() }
Self{emit, map: EntryDataMap::default()}
}
/// Returns the emitter of `self`.
fn emit(&mut self) -> &mut MapModelEmitter { &mut self.emit }
fn emit(&mut self) -> &mut AbstractMapModelEmitter {&mut self.emit}
/// Checks if `row` exists in the leaf `index`.
fn check_row(&self, index: usize, _row: usize) -> Option<usize> { None }
fn row_count(&self) -> usize {self.map.len()}
/// Returns the row `index` is in.
fn row(&self, index: usize) -> usize { index }
fn prop_index(&self, index: usize) -> u64 {(*self.get(index).0).into()}
/// Returns the number of rows in `index`.
fn row_count(&self, index: Option<usize>) -> usize
fn prop_icon(&self, index: u16) -> String
{
match index {
Some(_) => 0,
None => 7,
match self.get(index.into()).1.get_type() {
EntryType::Image => "image-x-generic".to_string(),
EntryType::Map => ":/tycho/color/map.png".to_string(),
EntryType::Other => "image-missing".to_string(),
EntryType::Physics => "applications-system".to_string(),
}
}
/// 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
{
@ -71,11 +65,16 @@ impl MapModelTrait for MapModel
eprintln!("opening project: {}", &path);
}
if let Ok(map) = open_f(&mm) {
self.map = map;
true
} else {
false
match Self::open_map(path) {
Ok(map) => {
self.map = map;
true
}
Err(e) => {
backtrace!(e);
cc::critical_msg("Error opening map", e);
false
}
}
}
@ -100,24 +99,22 @@ impl MapModelTrait for MapModel
}
/// Returns `true` if the file has been modified from its original state.
fn is_dirty(&self) -> bool { false }
fn is_dirty(&self) -> bool {false}
}
impl Drop for MapModel
impl Drop for AbstractMapModel
{
fn drop(&mut self)
{
if cfg!(debug_assertions) {
eprintln!("drop MapModel");
eprintln!("drop AbstractMapModel");
}
}
}
pub struct MapModel
{
emit: MapModelEmitter,
model: MapModelTree,
map: map::Map,
pub struct AbstractMapModel {
emit: AbstractMapModelEmitter,
map: EntryDataMap,
}
// EOF

View File

@ -1,5 +1,6 @@
use maraiah::{err::*, ffi};
mod cc;
mod gui;
mod meta;

View File

@ -76,6 +76,7 @@
<string>&amp;Help</string>
</property>
<addaction name="actionAbout"/>
<addaction name="actionAboutQt"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
@ -135,12 +136,21 @@
<bool>false</bool>
</property>
<property name="icon">
<iconset theme="window-close"/>
<iconset theme="window-close">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Close</string>
</property>
</action>
<action name="actionAboutQt">
<property name="icon">
<iconset theme="help-about"/>
</property>
<property name="text">
<string>About Qt</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
@ -259,6 +269,22 @@
</hint>
</hints>
</connection>
<connection>
<sender>actionAboutQt</sender>
<signal>triggered()</signal>
<receiver>Menu</receiver>
<slot>openAboutQt()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>399</x>
<y>299</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>openMapProperties()</slot>
@ -266,5 +292,6 @@
<slot>mapOpen()</slot>
<slot>openAbout()</slot>
<slot>updateActions()</slot>
<slot>openAboutQt()</slot>
</slots>
</ui>

View File

@ -15,7 +15,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeView" name="treeView">
<widget class="QListView" name="listView">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
@ -31,6 +31,12 @@
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="viewMode">
<enum>QListView::IconMode</enum>
</property>
<property name="uniformItemSizes">
<bool>true</bool>
</property>
</widget>
</item>
</layout>