crime spaghetti

master
an 2019-10-09 19:06:14 -04:00
parent ed5f825b5a
commit 4c118e2b63
12 changed files with 197 additions and 75 deletions

View File

@ -120,6 +120,15 @@ static inline int enumMax() {
return QMetaEnum::fromType<T>().keyCount();
}
template<typename T>
static inline T orThrow(Option<T> opt, Error err) {
if(opt) {
return *opt;
} else {
throw err;
}
}
static inline QDebug operator<<(QDebug debug, std::string const &t) {
debug << QString::fromStdString(t);
return debug;

View File

@ -18,14 +18,42 @@ namespace Arc {
return None;
}
Dir readArchive(std::istream &st) {
switch(auto v = getArchiveType(st);
v.has_value() ? *v : throw FileFormatError("not an archive")) {
Dir Dir::readArchive(std::istream &st, ArcType type) {
switch(type) {
case ArcType::Pack: return readPack(st);
case ArcType::Wad2: return readWad2(st);
}
}
ArcInfo::ArcInfo(ArcType arcType) noexcept :
type{arcType}
{
switch(type) {
case ArcType::Pack:
pathMaxChars = 56;
validatorType = PackValidator::staticMetaObject;
break;
case ArcType::Wad2:
pathMaxChars = 16;
validatorType = Wad2Validator::staticMetaObject;
break;
}
}
Arc::Arc(std::istream &st, QObject *parent) :
QObject{parent},
info{ArcInfo(orThrow(getArchiveType(st),
FileFormatError("not an archive")))},
root{Dir::readArchive(st, info.type)},
validator{qobject_cast<QValidator *>(info.validatorType
.newInstance(Q_ARG(QObject *,
this)))}
{
}
Arc::~Arc() {
}
Node *Dir::findNode(std::string const &name) {
auto it = std::find_if(begin(), end(), [&name](Node &node) {
return node.name == name;
@ -143,17 +171,25 @@ namespace Arc {
return m_dir;
}
void Model::setDir(Dir *dir) {
if(dir != m_dir) {
void Model::setDir(Dir *to) {
auto from = m_dir;
if(to != from) {
emit layoutAboutToBeChanged();
for(int row = 0, rows = rowCount(); row < rows; row++) {
for(int col = 0, cols = columnCount(); col < cols; col++) {
changePersistentIndex(index(row, col), QModelIndex{});
}
}
m_dir = dir;
m_dir = to;
emit layoutChanged();
emit dirChanged(dir);
emit dirChanged(from, to);
}
}
void Model::setDirToIndex(QModelIndex const &ind) {
auto node = static_cast<Node *>(ind.data(Qt::UserRole).value<void *>());
if(auto dir = std::get_if<Dir>(node)) {
setDir(dir);
}
}
}

View File

@ -4,14 +4,13 @@
#include <QAbstractItemModel>
#include <QByteArray>
#include <QMetaObject>
#include <QObject>
#include <QValidator>
namespace Arc {
Q_NAMESPACE
struct Node;
struct Dir;
enum class Column {
Size,
Type,
@ -36,14 +35,14 @@ namespace Arc {
};
Q_ENUM_NS(ArcType)
Option<ArcType> getArchiveType(std::istream &st) noexcept;
Dir readArchive(std::istream &st);
struct Node;
struct Dir : public std::vector<Node> {
using std::vector<Node>::vector;
Node *findNode(std::string const &name);
static Dir readArchive(std::istream &st, ArcType type);
};
struct File : public QByteArray {
@ -89,13 +88,36 @@ namespace Arc {
public slots:
void setDir(Dir *dir);
void setDirToIndex(QModelIndex const &ind);
signals:
void dirChanged(Dir *dir);
void dirChanged(Dir *from, Dir *to);
private:
Dir *m_dir;
};
struct ArcInfo {
ArcInfo(ArcType arcType) noexcept;
ArcType type;
std::size_t pathMaxChars;
QMetaObject validatorType;
};
class Arc : QObject {
Q_OBJECT
public:
explicit Arc(std::istream &st, QObject *parent = nullptr);
~Arc();
ArcInfo info;
Dir root;
QValidator *validator;
};
Option<ArcType> getArchiveType(std::istream &st) noexcept;
}
Q_DECLARE_METATYPE(Arc::Dir)
Q_DECLARE_METATYPE(Arc::File)

View File

@ -43,9 +43,7 @@ static int modeText(int argc, char *argv[]) {
auto fileName = par.value(fileNameOpt).toStdString();
auto st = openReadBin(fileName);
auto arc = Arc::readArchive(st);
qDebug() << arc;
qDebug() << Arc::Arc(st).root;
return 0;
}

View File

@ -34,9 +34,8 @@ void MainWindow::fileOpen() {
if(!fileName.isEmpty()) {
try {
auto st = openReadBin(fileName.toStdString());
auto arc = Arc::readArchive(st);
new Project{std::move(arc), m_errors, mdiArea};
auto st = openReadBin(fileName.toStdString());
new Project{st, m_errors, mdiArea};
} catch(std::exception const &exc) {
m_errors->showMessage(tr(exc.what()));
}

View File

@ -93,4 +93,13 @@ Arc::Dir readPack(std::istream &st) {
return root;
}
PackValidator::PackValidator(QObject *parent) :
QValidator{parent}
{
}
QValidator::State PackValidator::validate(QString &input, int &pos) const {
return QValidator::Acceptable;
}
// EOF

View File

@ -4,6 +4,17 @@
#include "quam/archive.h"
#include <QValidator>
class PackValidator : public QValidator {
Q_OBJECT
public:
Q_INVOKABLE explicit PackValidator(QObject *parent);
QValidator::State validate(QString &input, int &pos) const override;
};
Arc::Dir readPack(std::istream &st);
// EOF

View File

@ -5,15 +5,17 @@
#include <QMdiArea>
#include <QSortFilterProxyModel>
Project::Project(Arc::Dir &&arc, QErrorMessage *errors, QMdiArea *parent) :
Project::Project(std::istream &st, QErrorMessage *errors, QMdiArea *parent) :
QMdiSubWindow{parent},
Ui::Project{},
m_arc{std::move(arc)},
m_arc{new Arc::Arc{st, this}},
m_root{&m_arc->root},
m_lastDir{nullptr},
m_errors{errors},
m_model{new Arc::Model{this}},
m_sorter{new QSortFilterProxyModel{this}}
{
auto widget = new QWidget(this);
auto widget = new QWidget{this};
setupUi(widget);
setWidget(widget);
setAttribute(Qt::WA_DeleteOnClose);
@ -22,26 +24,19 @@ Project::Project(Arc::Dir &&arc, QErrorMessage *errors, QMdiArea *parent) :
connect(m_model, &Arc::Model::dirChanged,
this, &Project::dirChanged);
connect(tableView, &QAbstractItemView::doubleClicked,
this, &Project::viewDoubleClicked);
m_model, &Arc::Model::setDirToIndex);
m_sorter->setSourceModel(m_model);
tableView->setModel(m_sorter);
m_model->setDir(&m_arc);
m_model->setDir(m_root);
}
Project::~Project() {
}
void Project::dirChanged(Arc::Dir *) {
void Project::dirChanged(Arc::Dir *from, Arc::Dir *to) {
m_lastDir = from;
tableView->resizeColumnsToContents();
}
void Project::viewDoubleClicked(QModelIndex const &index) {
auto node = static_cast<Arc::Node *>(index.data(Qt::UserRole)
.value<void *>());
if(auto dir = std::get_if<Arc::Dir>(node)) {
m_model->setDir(dir);
}
}
// EOF

View File

@ -17,15 +17,15 @@ class Project : public QMdiSubWindow, private Ui::Project {
Q_OBJECT
public:
explicit Project(Arc::Dir &&arc, QErrorMessage *errors, QMdiArea *parent);
explicit Project(std::istream &st, QErrorMessage *errors, QMdiArea *parent);
virtual ~Project();
private slots:
void dirChanged(Arc::Dir *dir);
void viewDoubleClicked(QModelIndex const &index);
void dirChanged(Arc::Dir *from, Arc::Dir *to);
private:
Arc::Dir m_arc;
Arc::Arc *m_arc;
Arc::Dir *m_root, *m_lastDir;
QErrorMessage *m_errors;
Arc::Model *m_model;
QSortFilterProxyModel *m_sorter;

View File

@ -19,43 +19,66 @@
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QTableView" name="tableView">
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="autoScroll">
<bool>false</bool>
</property>
<property name="tabKeyNavigation">
<bool>true</bool>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="horizontalHeaderVisible">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<widget class="QWidget" name="">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="dirName"/>
</item>
<item>
<widget class="QPushButton" name="buttonUp">
<property name="icon">
<iconset theme="go-up"/>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTableView" name="tableView">
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="autoScroll">
<bool>false</bool>
</property>
<property name="tabKeyNavigation">
<bool>true</bool>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="horizontalHeaderVisible">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
<widget class="QPlainTextEdit" name="textEdit"/>
</widget>

View File

@ -88,4 +88,13 @@ Arc::Dir readWad2(std::istream &st) {
return root;
}
Wad2Validator::Wad2Validator(QObject *parent) :
QValidator{parent}
{
}
QValidator::State Wad2Validator::validate(QString &input, int &pos) const {
return QValidator::Acceptable;
}
// EOF

View File

@ -4,6 +4,17 @@
#include "quam/archive.h"
#include <QValidator>
class Wad2Validator : public QValidator {
Q_OBJECT
public:
Q_INVOKABLE explicit Wad2Validator(QObject *parent);
QValidator::State validate(QString &input, int &pos) const override;
};
Arc::Dir readWad2(std::istream &st);
// EOF