tycho: make the project view use icons
parent
14c0ef8f2a
commit
e3c0b0dd7d
|
@ -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
|
||||
|
|
|
@ -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"]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -19,6 +19,7 @@ public slots:
|
|||
void mapNew();
|
||||
void mapOpen();
|
||||
void openAbout();
|
||||
void openAboutQt();
|
||||
void openMapProperties();
|
||||
void updateActions();
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include "../ui/ui_project.h"
|
||||
|
||||
class MapModel;
|
||||
|
||||
class ProjectModel
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -1,8 +1,8 @@
|
|||
//! GUI implementation.
|
||||
|
||||
mod ffi;
|
||||
mod map;
|
||||
mod qobj;
|
||||
|
||||
pub use self::map::MapModel;
|
||||
pub use self::map::AbstractMapModel;
|
||||
|
||||
// EOF
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use maraiah::{err::*, ffi};
|
||||
|
||||
mod cc;
|
||||
mod gui;
|
||||
mod meta;
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
<string>&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>&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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue