Compare commits
No commits in common. "69fe7cf9caa27c4cd4ace5de40bd3e91cf0be27d" and "89414dd5ecec5936fcf0afb3d926ca0519b322f7" have entirely different histories.
69fe7cf9ca
...
89414dd5ec
|
@ -46,10 +46,7 @@ add_executable(
|
||||||
source/quam/main_window.h
|
source/quam/main_window.h
|
||||||
source/quam/main_window.ui
|
source/quam/main_window.ui
|
||||||
source/quam/pak.cc
|
source/quam/pak.cc
|
||||||
source/quam/pak.h
|
source/quam/pak.h)
|
||||||
source/quam/project.cc
|
|
||||||
source/quam/project.h
|
|
||||||
source/quam/project.ui)
|
|
||||||
|
|
||||||
make_qt_project(quam)
|
make_qt_project(quam)
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include <ios>
|
#include <ios>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <optional>
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
|
@ -1,23 +1,18 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "quam/main_window.h"
|
#include "quam/main_window.h"
|
||||||
#include "quam/project.h"
|
#include "quam/pak.h"
|
||||||
|
|
||||||
#include <QErrorMessage>
|
|
||||||
#include <QFileDialog>
|
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent) :
|
MainWindow::MainWindow(QWidget *parent) :
|
||||||
QMainWindow{parent},
|
QMainWindow{parent},
|
||||||
Ui::MainWindow{},
|
Ui::MainWindow{},
|
||||||
m_errors{new QErrorMessage{this}}
|
m_errors{}
|
||||||
{
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
actionClose->setShortcut(QKeySequence{QKeySequence::Close});
|
|
||||||
actionOpen->setShortcut(QKeySequence{QKeySequence::Open});
|
actionOpen->setShortcut(QKeySequence{QKeySequence::Open});
|
||||||
actionQuit->setShortcut(QKeySequence{QKeySequence::Quit});
|
actionQuit->setShortcut(QKeySequence{QKeySequence::Quit});
|
||||||
}
|
|
||||||
|
|
||||||
MainWindow::~MainWindow() {
|
tableWidget->sortByColumn(Pak::ColumnId, Qt::AscendingOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::fileOpen() {
|
void MainWindow::fileOpen() {
|
||||||
|
@ -34,17 +29,11 @@ void MainWindow::fileOpen() {
|
||||||
try {
|
try {
|
||||||
auto st = openReadBin(fileName.toStdString());
|
auto st = openReadBin(fileName.toStdString());
|
||||||
auto pak = readPak(st);
|
auto pak = readPak(st);
|
||||||
new Project{std::move(pak), m_errors, mdiArea};
|
setTableToPakDir(*tableWidget, pak);
|
||||||
} catch(std::exception const &exc) {
|
} catch(std::exception const &exc) {
|
||||||
m_errors->showMessage(tr(exc.what()));
|
m_errors.showMessage(tr(exc.what()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::fileClose() {
|
|
||||||
if(auto win = mdiArea->activeSubWindow()) {
|
|
||||||
mdiArea->removeSubWindow(win);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -1,26 +1,23 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "quam/pak.h"
|
|
||||||
#include "quam/ui_main_window.h"
|
#include "quam/ui_main_window.h"
|
||||||
|
|
||||||
|
#include <QErrorMessage>
|
||||||
|
#include <QFileDialog>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
class QErrorMessage;
|
|
||||||
|
|
||||||
class MainWindow : public QMainWindow, private Ui::MainWindow {
|
class MainWindow : public QMainWindow, private Ui::MainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MainWindow(QWidget *parent = nullptr);
|
explicit MainWindow(QWidget *parent = nullptr);
|
||||||
virtual ~MainWindow();
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void fileOpen();
|
void fileOpen();
|
||||||
void fileClose();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QErrorMessage *m_errors;
|
QErrorMessage m_errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -11,26 +11,80 @@
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>QuAM!</string>
|
<string>Quam!</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralwidget">
|
<widget class="QWidget" name="centralwidget">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QMdiArea" name="mdiArea">
|
<widget class="QTableWidget" name="tableWidget">
|
||||||
<property name="viewMode">
|
<property name="verticalScrollBarPolicy">
|
||||||
<enum>QMdiArea::TabbedView</enum>
|
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="documentMode">
|
<property name="horizontalScrollBarPolicy">
|
||||||
|
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||||
|
</property>
|
||||||
|
<property name="autoScroll">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="tabKeyNavigation">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="tabsClosable">
|
<property name="alternatingRowColors">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="tabsMovable">
|
<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>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<attribute name="horizontalHeaderVisible">
|
||||||
|
<bool>true</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
|
||||||
|
<bool>true</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="horizontalHeaderStretchLastSection">
|
||||||
|
<bool>true</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="verticalHeaderVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>ID</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>The ID of the file. This is the N-th file in the archive.</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Size</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>The size of the file in bytes.</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Name</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>The name of the file.</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPlainTextEdit" name="textEdit"/>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenuBar" name="menubar">
|
<widget class="QMenuBar" name="menubar">
|
||||||
|
@ -47,7 +101,6 @@
|
||||||
<string>&File</string>
|
<string>&File</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionOpen"/>
|
<addaction name="actionOpen"/>
|
||||||
<addaction name="actionClose"/>
|
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionQuit"/>
|
<addaction name="actionQuit"/>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -56,8 +109,7 @@
|
||||||
<widget class="QStatusBar" name="statusbar"/>
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
<action name="actionOpen">
|
<action name="actionOpen">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="document-open">
|
<iconset theme="document-open"/>
|
||||||
<normaloff>.</normaloff>.</iconset>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Open</string>
|
<string>&Open</string>
|
||||||
|
@ -65,22 +117,12 @@
|
||||||
</action>
|
</action>
|
||||||
<action name="actionQuit">
|
<action name="actionQuit">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="application-exit">
|
<iconset theme="application-exit"/>
|
||||||
<normaloff>.</normaloff>.</iconset>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Quit</string>
|
<string>&Quit</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionClose">
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="document-close">
|
|
||||||
<normaloff>.</normaloff>.</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>&Close</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
|
@ -116,26 +158,8 @@
|
||||||
</hint>
|
</hint>
|
||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
<connection>
|
|
||||||
<sender>actionClose</sender>
|
|
||||||
<signal>triggered()</signal>
|
|
||||||
<receiver>MainWindow</receiver>
|
|
||||||
<slot>fileClose()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>-1</x>
|
|
||||||
<y>-1</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>319</x>
|
|
||||||
<y>239</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
</connections>
|
||||||
<slots>
|
<slots>
|
||||||
<slot>fileOpen()</slot>
|
<slot>fileOpen()</slot>
|
||||||
<slot>selectCell(int,int)</slot>
|
|
||||||
<slot>fileClose()</slot>
|
|
||||||
</slots>
|
</slots>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "quam/pak.h"
|
#include "quam/pak.h"
|
||||||
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QMetaEnum>
|
|
||||||
|
|
||||||
struct PakHeader {
|
struct PakHeader {
|
||||||
quint32 dirOffset;
|
quint32 dirOffset;
|
||||||
quint32 dirNum;
|
quint32 dirNum;
|
||||||
|
@ -36,7 +33,7 @@ static PakHeader readPakHeader(std::istream &st) {
|
||||||
return hdr;
|
return hdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PakEntry readPakEntry(std::istream &st) {
|
static PakEntry readPakEntry(std::istream &st, quint32 id) {
|
||||||
auto entName = readBytes<56>(st);
|
auto entName = readBytes<56>(st);
|
||||||
auto entOffset = readLE<quint32>(st);
|
auto entOffset = readLE<quint32>(st);
|
||||||
auto entSize = readLE<quint32>(st);
|
auto entSize = readLE<quint32>(st);
|
||||||
|
@ -46,6 +43,7 @@ static PakEntry readPakEntry(std::istream &st) {
|
||||||
st.seekg(entOffset);
|
st.seekg(entOffset);
|
||||||
|
|
||||||
PakFile file;
|
PakFile file;
|
||||||
|
file.id = id;
|
||||||
file.resize(entSize);
|
file.resize(entSize);
|
||||||
st.read(file.data(), entSize);
|
st.read(file.data(), entSize);
|
||||||
|
|
||||||
|
@ -67,29 +65,15 @@ static PakEntry readPakEntry(std::istream &st) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertFile(PakDir &dir, std::string name, PakFile file) {
|
void insertFile(PakDir &dir, std::string name, PakFile file) {
|
||||||
std::optional<std::string> next;
|
|
||||||
|
|
||||||
if(auto slash = name.find('/'); slash != std::string::npos) {
|
if(auto slash = name.find('/'); slash != std::string::npos) {
|
||||||
next = name.substr(slash + 1);
|
auto folder = name.substr(0, slash);
|
||||||
name = name.substr(0, slash);
|
auto next = name.substr(slash + 1);
|
||||||
}
|
dir[folder] = PakNode{PakDir{}};
|
||||||
|
insertFile(std::get<PakDir>(dir[folder]),
|
||||||
auto existingNode = std::find_if(dir.begin(), dir.end(),
|
std::move(next),
|
||||||
[&name](PakNode const &node) {
|
std::move(file));
|
||||||
return node.name == name;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(next) {
|
|
||||||
auto ref =
|
|
||||||
existingNode != dir.end()
|
|
||||||
? *existingNode
|
|
||||||
: dir.emplace_back(PakDir{}, std::move(name));
|
|
||||||
insertFile(std::get<PakDir>(ref), *std::move(next), std::move(file));
|
|
||||||
} else {
|
} else {
|
||||||
if(existingNode != dir.end()) {
|
dir[name] = PakNode{std::move(file)};
|
||||||
throw std::runtime_error("duplicate file");
|
|
||||||
}
|
|
||||||
dir.emplace_back(std::move(file), std::move(name));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,113 +83,57 @@ PakDir readPak(std::istream &st) {
|
||||||
|
|
||||||
PakDir root;
|
PakDir root;
|
||||||
|
|
||||||
for(quint32 i = 0; i < hdr.dirNum; i++) {
|
for(quint32 id = 0; id < hdr.dirNum; id++) {
|
||||||
auto ent = readPakEntry(st);
|
auto ent = readPakEntry(st, id);
|
||||||
insertFile(root, std::move(ent.name), std::move(ent.file));
|
insertFile(root, std::move(ent.name), std::move(ent.file));
|
||||||
}
|
}
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
PakDirRoot::PakDirRoot(PakDir &&root, QObject *parent) :
|
void setTableToPakDir(QTableWidget &table, PakDir const &dir) {
|
||||||
QObject{parent},
|
constexpr auto Flags = Qt::ItemIsSelectable |
|
||||||
PakDir{std::move(root)}
|
Qt::ItemIsDragEnabled |
|
||||||
{
|
Qt::ItemIsEnabled |
|
||||||
}
|
Qt::ItemNeverHasChildren;
|
||||||
|
|
||||||
PakDirRoot::~PakDirRoot() {
|
auto sorted = table.isSortingEnabled();
|
||||||
}
|
table.clearContents();
|
||||||
|
table.setSortingEnabled(false);
|
||||||
PakDirModel::PakDirModel(PakDir const *root, QObject *parent) :
|
quint32 row{0};
|
||||||
QAbstractItemModel{parent},
|
for(auto const &kv : dir) {
|
||||||
m_root{root}
|
auto const &name = kv.first;
|
||||||
{
|
auto const &node = kv.second;
|
||||||
}
|
table.setRowCount(row + 1);
|
||||||
|
{
|
||||||
PakDirModel::~PakDirModel() {
|
auto item = new QTableWidgetItem;
|
||||||
}
|
item->setFlags(Flags);
|
||||||
|
if(auto file = std::get_if<PakFile>(&node)) {
|
||||||
QVariant PakDirModel::data(QModelIndex const &index, int role) const {
|
item->setText(QString::number(file->id));
|
||||||
if(!index.isValid()) {
|
|
||||||
return QVariant{};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto node = static_cast<PakNode *>(index.internalPointer());
|
|
||||||
auto col = Pak::Column(index.column());
|
|
||||||
|
|
||||||
switch(role) {
|
|
||||||
case Qt::DecorationRole:
|
|
||||||
if(col == Pak::Column::Name) {
|
|
||||||
auto icon =
|
|
||||||
std::holds_alternative<PakDir>(*node) ? "folder"
|
|
||||||
: "text-x-generic";
|
|
||||||
return QVariant{QIcon::fromTheme(icon)};
|
|
||||||
}
|
}
|
||||||
break;
|
table.setItem(row, Pak::ColumnId, item);
|
||||||
case Qt::DisplayRole:
|
|
||||||
switch(col) {
|
|
||||||
case Pak::Column::Size:
|
|
||||||
if(auto file = std::get_if<PakFile>(node)) {
|
|
||||||
return QVariant{QString::number(file->size())};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Pak::Column::Name:
|
|
||||||
return QVariant{tr(node->name.data())};
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return QVariant{};
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::ItemFlags PakDirModel::flags(QModelIndex const &index) const {
|
|
||||||
if(!index.isValid()) {
|
|
||||||
return Qt::NoItemFlags;
|
|
||||||
} else {
|
|
||||||
return Qt::ItemIsSelectable |
|
|
||||||
Qt::ItemIsDragEnabled |
|
|
||||||
Qt::ItemIsEnabled |
|
|
||||||
Qt::ItemNeverHasChildren;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant PakDirModel::headerData(int section,
|
|
||||||
Qt::Orientation orientation,
|
|
||||||
int role) const {
|
|
||||||
if(orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
|
||||||
switch(Pak::Column(section)) {
|
|
||||||
case Pak::Column::Size: return QVariant{tr("Size")};
|
|
||||||
case Pak::Column::Name: return QVariant{tr("Name")};
|
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
auto item = new QTableWidgetItem;
|
||||||
|
item->setFlags(Flags);
|
||||||
|
if(auto file = std::get_if<PakFile>(&node)) {
|
||||||
|
item->setText(QString::number(file->size()));
|
||||||
|
}
|
||||||
|
table.setItem(row, Pak::ColumnSize, item);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto item = new QTableWidgetItem;
|
||||||
|
auto icon = std::holds_alternative<PakDir>(node) ? "folder" :
|
||||||
|
"text-x-generic";
|
||||||
|
item->setFlags(Flags);
|
||||||
|
item->setText(QString::fromStdString(name));
|
||||||
|
item->setIcon(QIcon::fromTheme(icon));
|
||||||
|
table.setItem(row, Pak::ColumnName, item);
|
||||||
|
}
|
||||||
|
++row;
|
||||||
}
|
}
|
||||||
return QVariant{};
|
table.setSortingEnabled(sorted);
|
||||||
}
|
table.resizeColumnsToContents();
|
||||||
|
|
||||||
QModelIndex PakDirModel::index(int row,
|
|
||||||
int col,
|
|
||||||
QModelIndex const &parent) const {
|
|
||||||
if(!hasIndex(row, col, parent) || row > m_root->size()) {
|
|
||||||
return QModelIndex{};
|
|
||||||
} else {
|
|
||||||
// despite index data being const, this function does not take a const
|
|
||||||
// pointer, which is very annoying!
|
|
||||||
return createIndex(row, col, const_cast<PakNode *>(&m_root->at(row)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex PakDirModel::parent(QModelIndex const &) const {
|
|
||||||
return QModelIndex{};
|
|
||||||
}
|
|
||||||
|
|
||||||
int PakDirModel::rowCount(QModelIndex const &) const {
|
|
||||||
return m_root->size();
|
|
||||||
}
|
|
||||||
|
|
||||||
int PakDirModel::columnCount(QModelIndex const &) const {
|
|
||||||
return QMetaEnum::fromType<Pak::Column>().keyCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
PakDirModelSorter::~PakDirModelSorter() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -1,83 +1,35 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QAbstractItemModel>
|
#include <QTableWidget>
|
||||||
#include <QSortFilterProxyModel>
|
|
||||||
|
|
||||||
namespace Pak {
|
namespace Pak {
|
||||||
Q_NAMESPACE
|
enum PakColumn {
|
||||||
|
ColumnId,
|
||||||
enum class Column {
|
ColumnSize,
|
||||||
Size,
|
ColumnName,
|
||||||
Name,
|
|
||||||
};
|
};
|
||||||
Q_ENUM_NS(Column)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PakNode;
|
struct PakNode;
|
||||||
|
|
||||||
struct PakDir : public std::vector<PakNode> {
|
struct PakDir : public std::map<std::string, PakNode> {
|
||||||
using std::vector<PakNode>::vector;
|
using std::map<std::string, PakNode>::map;
|
||||||
};
|
};
|
||||||
Q_DECLARE_METATYPE(PakDir)
|
Q_DECLARE_METATYPE(PakDir)
|
||||||
|
|
||||||
struct PakFile : public QByteArray {
|
struct PakFile : public QByteArray {
|
||||||
using QByteArray::QByteArray;
|
using QByteArray::QByteArray;
|
||||||
|
|
||||||
|
quint32 id{0};
|
||||||
};
|
};
|
||||||
Q_DECLARE_METATYPE(PakFile)
|
Q_DECLARE_METATYPE(PakFile)
|
||||||
|
|
||||||
struct PakNode : public std::variant<PakDir, PakFile> {
|
struct PakNode : public std::variant<PakDir, PakFile> {
|
||||||
PakNode() = default;
|
using std::variant<PakDir, PakFile>::variant;
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr PakNode(T &&t, std::string &&n) :
|
|
||||||
variant(std::move(t)),
|
|
||||||
name(std::move(n)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
PakNode(PakNode const &) = default;
|
|
||||||
PakNode(PakNode &&) = default;
|
|
||||||
|
|
||||||
std::string name;
|
|
||||||
};
|
};
|
||||||
Q_DECLARE_METATYPE(PakNode)
|
Q_DECLARE_METATYPE(PakNode)
|
||||||
|
|
||||||
class PakDirRoot : public QObject, public PakDir {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit PakDirRoot(PakDir &&root, QObject *parent);
|
|
||||||
virtual ~PakDirRoot();
|
|
||||||
};
|
|
||||||
|
|
||||||
class PakDirModel : public QAbstractItemModel {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit PakDirModel(PakDir const *root, QObject *parent);
|
|
||||||
virtual ~PakDirModel();
|
|
||||||
|
|
||||||
QVariant data(QModelIndex const &index, int role) const override;
|
|
||||||
Qt::ItemFlags flags(QModelIndex const &index) const override;
|
|
||||||
QVariant headerData(int section, Qt::Orientation orientation, int role)
|
|
||||||
const override;
|
|
||||||
QModelIndex index(int row, int col, QModelIndex const &parent)
|
|
||||||
const override;
|
|
||||||
QModelIndex parent(QModelIndex const &index) const override;
|
|
||||||
int rowCount(QModelIndex const &parent) const override;
|
|
||||||
int columnCount(QModelIndex const &parent) const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
PakDir const *const m_root;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PakDirModelSorter : public QSortFilterProxyModel {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
using QSortFilterProxyModel::QSortFilterProxyModel;
|
|
||||||
virtual ~PakDirModelSorter();
|
|
||||||
};
|
|
||||||
|
|
||||||
PakDir readPak(std::istream &st);
|
PakDir readPak(std::istream &st);
|
||||||
|
void setTableToPakDir(QTableWidget &table, PakDir const &dir);
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
#include "common.h"
|
|
||||||
#include "quam/project.h"
|
|
||||||
|
|
||||||
#include <QAbstractItemModel>
|
|
||||||
#include <QErrorMessage>
|
|
||||||
#include <QMdiArea>
|
|
||||||
#include <QSortFilterProxyModel>
|
|
||||||
|
|
||||||
Project::Project(QErrorMessage *errors, QMdiArea *parent) :
|
|
||||||
QMdiSubWindow{parent},
|
|
||||||
Ui::Project{},
|
|
||||||
m_errors{errors}
|
|
||||||
{
|
|
||||||
auto widget = new QWidget(this);
|
|
||||||
setupUi(widget);
|
|
||||||
setWidget(widget);
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
showMaximized();
|
|
||||||
}
|
|
||||||
|
|
||||||
Project::Project(PakDir &&dir, QErrorMessage *errors, QMdiArea *parent) :
|
|
||||||
Project{errors, parent}
|
|
||||||
{
|
|
||||||
auto root = new PakDirRoot{std::move(dir), this};
|
|
||||||
auto model = new PakDirModel{root, this};
|
|
||||||
setupModel(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
Project::~Project() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Project::setupModel(QAbstractItemModel *model) {
|
|
||||||
m_model = model;
|
|
||||||
m_sorter = new QSortFilterProxyModel{this};
|
|
||||||
m_sorter->setSourceModel(m_model);
|
|
||||||
tableView->setModel(m_sorter);
|
|
||||||
tableView->sortByColumn(int(Pak::Column::Name), Qt::AscendingOrder);
|
|
||||||
tableView->resizeColumnsToContents();
|
|
||||||
}
|
|
||||||
|
|
||||||
// EOF
|
|
|
@ -1,31 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "quam/pak.h"
|
|
||||||
#include "quam/ui_project.h"
|
|
||||||
|
|
||||||
#include <QMainWindow>
|
|
||||||
#include <QMdiSubWindow>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class QAbstractItemModel;
|
|
||||||
class QErrorMessage;
|
|
||||||
class QSortFilterProxyModel;
|
|
||||||
|
|
||||||
class Project : public QMdiSubWindow, private Ui::Project {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Project(PakDir &&dir, QErrorMessage *errors, QMdiArea *parent);
|
|
||||||
virtual ~Project();
|
|
||||||
|
|
||||||
private:
|
|
||||||
explicit Project(QErrorMessage *errors, QMdiArea *parent);
|
|
||||||
|
|
||||||
void setupModel(QAbstractItemModel *model);
|
|
||||||
|
|
||||||
QErrorMessage *m_errors;
|
|
||||||
QAbstractItemModel *m_model;
|
|
||||||
QSortFilterProxyModel *m_sorter;
|
|
||||||
};
|
|
||||||
|
|
||||||
// EOF
|
|
|
@ -1,67 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>Project</class>
|
|
||||||
<widget class="QWidget" name="Project">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>640</width>
|
|
||||||
<height>480</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Project View</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QSplitter" name="splitter">
|
|
||||||
<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>
|
|
||||||
<widget class="QPlainTextEdit" name="textEdit"/>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
Loading…
Reference in New Issue
Block a user