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(); 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) { static inline QDebug operator<<(QDebug debug, std::string const &t) {
debug << QString::fromStdString(t); debug << QString::fromStdString(t);
return debug; return debug;

View File

@ -18,14 +18,42 @@ namespace Arc {
return None; return None;
} }
Dir readArchive(std::istream &st) { Dir Dir::readArchive(std::istream &st, ArcType type) {
switch(auto v = getArchiveType(st); switch(type) {
v.has_value() ? *v : throw FileFormatError("not an archive")) {
case ArcType::Pack: return readPack(st); case ArcType::Pack: return readPack(st);
case ArcType::Wad2: return readWad2(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) { Node *Dir::findNode(std::string const &name) {
auto it = std::find_if(begin(), end(), [&name](Node &node) { auto it = std::find_if(begin(), end(), [&name](Node &node) {
return node.name == name; return node.name == name;
@ -143,17 +171,25 @@ namespace Arc {
return m_dir; return m_dir;
} }
void Model::setDir(Dir *dir) { void Model::setDir(Dir *to) {
if(dir != m_dir) { auto from = m_dir;
if(to != from) {
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
for(int row = 0, rows = rowCount(); row < rows; row++) { for(int row = 0, rows = rowCount(); row < rows; row++) {
for(int col = 0, cols = columnCount(); col < cols; col++) { for(int col = 0, cols = columnCount(); col < cols; col++) {
changePersistentIndex(index(row, col), QModelIndex{}); changePersistentIndex(index(row, col), QModelIndex{});
} }
} }
m_dir = dir; m_dir = to;
emit layoutChanged(); 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 <QAbstractItemModel>
#include <QByteArray> #include <QByteArray>
#include <QMetaObject>
#include <QObject> #include <QObject>
#include <QValidator>
namespace Arc { namespace Arc {
Q_NAMESPACE Q_NAMESPACE
struct Node;
struct Dir;
enum class Column { enum class Column {
Size, Size,
Type, Type,
@ -36,14 +35,14 @@ namespace Arc {
}; };
Q_ENUM_NS(ArcType) Q_ENUM_NS(ArcType)
Option<ArcType> getArchiveType(std::istream &st) noexcept; struct Node;
Dir readArchive(std::istream &st);
struct Dir : public std::vector<Node> { struct Dir : public std::vector<Node> {
using std::vector<Node>::vector; using std::vector<Node>::vector;
Node *findNode(std::string const &name); Node *findNode(std::string const &name);
static Dir readArchive(std::istream &st, ArcType type);
}; };
struct File : public QByteArray { struct File : public QByteArray {
@ -89,13 +88,36 @@ namespace Arc {
public slots: public slots:
void setDir(Dir *dir); void setDir(Dir *dir);
void setDirToIndex(QModelIndex const &ind);
signals: signals:
void dirChanged(Dir *dir); void dirChanged(Dir *from, Dir *to);
private: private:
Dir *m_dir; 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::Dir)
Q_DECLARE_METATYPE(Arc::File) 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 fileName = par.value(fileNameOpt).toStdString();
auto st = openReadBin(fileName); auto st = openReadBin(fileName);
auto arc = Arc::readArchive(st); qDebug() << Arc::Arc(st).root;
qDebug() << arc;
return 0; return 0;
} }

View File

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

View File

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

View File

@ -4,6 +4,17 @@
#include "quam/archive.h" #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); Arc::Dir readPack(std::istream &st);
// EOF // EOF

View File

@ -5,15 +5,17 @@
#include <QMdiArea> #include <QMdiArea>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
Project::Project(Arc::Dir &&arc, QErrorMessage *errors, QMdiArea *parent) : Project::Project(std::istream &st, QErrorMessage *errors, QMdiArea *parent) :
QMdiSubWindow{parent}, QMdiSubWindow{parent},
Ui::Project{}, 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_errors{errors},
m_model{new Arc::Model{this}}, m_model{new Arc::Model{this}},
m_sorter{new QSortFilterProxyModel{this}} m_sorter{new QSortFilterProxyModel{this}}
{ {
auto widget = new QWidget(this); auto widget = new QWidget{this};
setupUi(widget); setupUi(widget);
setWidget(widget); setWidget(widget);
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
@ -22,26 +24,19 @@ Project::Project(Arc::Dir &&arc, QErrorMessage *errors, QMdiArea *parent) :
connect(m_model, &Arc::Model::dirChanged, connect(m_model, &Arc::Model::dirChanged,
this, &Project::dirChanged); this, &Project::dirChanged);
connect(tableView, &QAbstractItemView::doubleClicked, connect(tableView, &QAbstractItemView::doubleClicked,
this, &Project::viewDoubleClicked); m_model, &Arc::Model::setDirToIndex);
m_sorter->setSourceModel(m_model); m_sorter->setSourceModel(m_model);
tableView->setModel(m_sorter); tableView->setModel(m_sorter);
m_model->setDir(&m_arc); m_model->setDir(m_root);
} }
Project::~Project() { Project::~Project() {
} }
void Project::dirChanged(Arc::Dir *) { void Project::dirChanged(Arc::Dir *from, Arc::Dir *to) {
m_lastDir = from;
tableView->resizeColumnsToContents(); 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 // EOF

View File

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

View File

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

View File

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

View File

@ -4,6 +4,17 @@
#include "quam/archive.h" #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); Arc::Dir readWad2(std::istream &st);
// EOF // EOF