From 62253abab0ee9a02fa5aba44e3519ef17e638744 Mon Sep 17 00:00:00 2001 From: Alison Watson Date: Sat, 28 Sep 2019 04:17:55 -0400 Subject: [PATCH] finish pak opening support --- source/common.h | 4 +++ source/quam/main.cc | 7 ++-- source/quam/main_window.cc | 51 ++++++++++++++++++++++++---- source/quam/main_window.h | 7 +++- source/quam/main_window.ui | 68 ++++++++++++++++++++++++++++---------- source/quam/pak.cc | 8 ++--- source/quam/pak.h | 7 ++-- 7 files changed, 120 insertions(+), 32 deletions(-) diff --git a/source/common.h b/source/common.h index 446c548..1b66136 100644 --- a/source/common.h +++ b/source/common.h @@ -64,4 +64,8 @@ static inline QDebug operator <<(QDebug debug, return debug; } +static inline std::ifstream openReadBin(std::filesystem::path path) { + return std::ifstream{path, std::ios_base::in | std::ios_base::binary}; +} + // EOF diff --git a/source/quam/main.cc b/source/quam/main.cc index 7feefc2..6300763 100644 --- a/source/quam/main.cc +++ b/source/quam/main.cc @@ -42,14 +42,17 @@ static int modeText(int argc, char *argv[]) { par.process(appl); auto fileName = par.value(fileNameOpt).toStdString(); - std::ifstream st{fileName, std::ios_base::in | std::ios_base::binary}; + + auto st = openReadBin(fileName); auto pak = readPak(st); + qDebug() << pak; + return 0; } int main(int argc, char *argv[]) { - if(argc == 0) { + if(argc <= 1) { return modeGui(argc, argv); } else { return modeText(argc, argv); diff --git a/source/quam/main_window.cc b/source/quam/main_window.cc index 189e054..5cc5c7a 100644 --- a/source/quam/main_window.cc +++ b/source/quam/main_window.cc @@ -2,14 +2,53 @@ #include "quam/main_window.h" #include "quam/pak.h" -MainWindow::MainWindow(QWidget *parent) : - QMainWindow{parent}, - Ui::MainWindow{} -{ - setupUi(this); +static void setListToDir(QListWidget &list, PakDir const &dir) { + list.clear(); + for(auto const &kv : dir) { + auto const &name = kv.first; + auto const &node = kv.second; + auto var = QVariant::fromValue(node); + auto item = new QListWidgetItem{&list}; + item->setText(QString::fromStdString(name)); + item->setData(Qt::UserRole, var); + if(std::holds_alternative(node)) { + item->setIcon(QIcon::fromTheme("folder")); + } else { + item->setIcon(QIcon::fromTheme("text-x-generic")); + } + list.addItem(item); + } } -void MainWindow::openTest() { +MainWindow::MainWindow(QWidget *parent) : + QMainWindow{parent}, + Ui::MainWindow{}, + m_errors{} +{ + setupUi(this); + + actionOpen->setShortcut(QKeySequence(QKeySequence::Open)); + actionQuit->setShortcut(QKeySequence(QKeySequence::Quit)); +} + +void MainWindow::fileOpen() { + auto fileName = + QFileDialog::getOpenFileName( + this, + tr("Open Archive"), + QString{}, + tr("Quake PACK file (*.pak);;" + "All files (*)")); + + if(!fileName.isEmpty()) { + try { + auto st = openReadBin(fileName.toStdString()); + auto pak = readPak(st); + setListToDir(*listWidget, pak); + } catch(std::exception const &exc) { + m_errors.showMessage(tr(exc.what())); + } + } } // EOF diff --git a/source/quam/main_window.h b/source/quam/main_window.h index 2652e5d..3f12e5a 100644 --- a/source/quam/main_window.h +++ b/source/quam/main_window.h @@ -2,6 +2,8 @@ #include "quam/ui_main_window.h" +#include +#include #include #include @@ -12,7 +14,10 @@ public: explicit MainWindow(QWidget *parent = nullptr); public slots: - void openTest(); + void fileOpen(); + +private: + QErrorMessage m_errors; }; // EOF diff --git a/source/quam/main_window.ui b/source/quam/main_window.ui index 3b73751..ef5b573 100644 --- a/source/quam/main_window.ui +++ b/source/quam/main_window.ui @@ -16,17 +16,10 @@ - - - - 0 - 0 - - - - PushButton - - + + + + @@ -39,20 +32,61 @@ 29 + + + &File + + + + + + + + + + + + &Open + + + + + + + + &Quit + + - pushButton - clicked() + actionOpen + triggered() MainWindow - openTest() + fileOpen() - 59 - 53 + -1 + -1 + + + 319 + 239 + + + + + actionQuit + triggered() + MainWindow + close() + + + -1 + -1 319 @@ -62,6 +96,6 @@ - openTest() + fileOpen() diff --git a/source/quam/pak.cc b/source/quam/pak.cc index 06a71cb..c392436 100644 --- a/source/quam/pak.cc +++ b/source/quam/pak.cc @@ -54,7 +54,7 @@ static PakEntry readPakEntry(std::istream &st) { std::copy(entName.cbegin(), zero, std::back_inserter(name)); if(name.front() == '/') { - name.erase(0, 1); + throw std::runtime_error("empty root directory name"); } PakEntry ent; @@ -67,12 +67,12 @@ void insertFile(PakDir &dir, std::string name, PakFile file) { if(auto slash = name.find('/'); slash != std::string::npos) { auto folder = name.substr(0, slash); auto next = name.substr(slash + 1); - dir[folder] = std::make_unique(PakDir{}); - insertFile(std::get(*dir[folder]), + dir[folder] = PakNode{PakDir{}}; + insertFile(std::get(dir[folder]), std::move(next), std::move(file)); } else { - dir[name] = std::make_unique(std::move(file)); + dir[name] = PakNode{std::move(file)}; } } diff --git a/source/quam/pak.h b/source/quam/pak.h index b6145aa..f52fdd7 100644 --- a/source/quam/pak.h +++ b/source/quam/pak.h @@ -2,17 +2,20 @@ struct PakNode; -struct PakDir : public std::map> { - using std::map>::map; +struct PakDir : public std::map { + using std::map::map; }; +Q_DECLARE_METATYPE(PakDir) struct PakFile : public QByteArray { using QByteArray::QByteArray; }; +Q_DECLARE_METATYPE(PakFile) struct PakNode : public std::variant { using std::variant::variant; }; +Q_DECLARE_METATYPE(PakNode) PakDir readPak(std::istream &st);