app: add object-focused tab

This commit is contained in:
itsmattkc 2022-07-03 22:45:57 -05:00
parent 9ce113f1f0
commit 0fb49a780b
10 changed files with 233 additions and 40 deletions

View file

@ -17,11 +17,15 @@ set(PROJECT_SOURCES
panels/riff.cpp panels/riff.cpp
panels/riff.h panels/riff.h
abstractsiitemmodel.cpp
abstractsiitemmodel.h
chunkmodel.cpp chunkmodel.cpp
chunkmodel.h chunkmodel.h
main.cpp main.cpp
mainwindow.cpp mainwindow.cpp
mainwindow.h mainwindow.h
objectmodel.cpp
objectmodel.h
) )
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)

View file

@ -0,0 +1,26 @@
#include "abstractsiitemmodel.h"
using namespace si;
AbstractSIItemModel::AbstractSIItemModel(QObject *parent) :
QAbstractItemModel{parent},
chunk_(nullptr)
{
}
void AbstractSIItemModel::SetChunk(si::Chunk *c)
{
beginResetModel();
chunk_ = c;
endResetModel();
}
si::Chunk *AbstractSIItemModel::GetChunkFromIndex(const QModelIndex &index) const
{
if (!index.isValid()) {
return chunk_;
} else {
return static_cast<Chunk*>(index.internalPointer());
}
}

25
app/abstractsiitemmodel.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef ABSTRACTSIITEMMODEL_H
#define ABSTRACTSIITEMMODEL_H
#include <chunk.h>
#include <QAbstractItemModel>
class AbstractSIItemModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit AbstractSIItemModel(QObject *parent = nullptr);
void SetChunk(si::Chunk *c);
protected:
si::Chunk *GetChunkFromIndex(const QModelIndex &index) const;
si::Chunk *root() const { return chunk_; }
private:
si::Chunk *chunk_;
};
#endif // ABSTRACTSIITEMMODEL_H

View file

@ -2,13 +2,12 @@
#include <iostream> #include <iostream>
#define super QAbstractItemModel #define super AbstractSIItemModel
using namespace si; using namespace si;
ChunkModel::ChunkModel(QObject *parent) : ChunkModel::ChunkModel(QObject *parent) :
super{parent}, super{parent}
chunk_(nullptr)
{ {
} }
@ -45,7 +44,7 @@ QModelIndex ChunkModel::parent(const QModelIndex &index) const
} }
size_t row = grandparent->IndexOfChild(parent); size_t row = grandparent->IndexOfChild(parent);
return createIndex(row, 0, parent); return createIndex(int(row), 0, parent);
} }
int ChunkModel::rowCount(const QModelIndex &parent) const int ChunkModel::rowCount(const QModelIndex &parent) const
@ -55,7 +54,7 @@ int ChunkModel::rowCount(const QModelIndex &parent) const
return 0; return 0;
} }
return c->GetChildCount(); return int(c->GetChildCount());
} }
QVariant ChunkModel::data(const QModelIndex &index, int role) const QVariant ChunkModel::data(const QModelIndex &index, int role) const
@ -99,19 +98,3 @@ QVariant ChunkModel::headerData(int section, Qt::Orientation orientation, int ro
return super::headerData(section, orientation, role); return super::headerData(section, orientation, role);
} }
void ChunkModel::SetChunk(si::Chunk *c)
{
beginResetModel();
chunk_ = c;
endResetModel();
}
si::Chunk *ChunkModel::GetChunkFromIndex(const QModelIndex &index) const
{
if (!index.isValid()) {
return chunk_;
} else {
return static_cast<Chunk*>(index.internalPointer());
}
}

View file

@ -1,11 +1,11 @@
#ifndef CHUNKMODEL_H #ifndef CHUNKMODEL_H
#define CHUNKMODEL_H #define CHUNKMODEL_H
#include <chunk.h> #include "abstractsiitemmodel.h"
#include <QAbstractItemModel>
class ChunkModel : public QAbstractItemModel class ChunkModel : public AbstractSIItemModel
{ {
Q_OBJECT
public: public:
enum Columns enum Columns
{ {
@ -25,13 +25,6 @@ public:
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
void SetChunk(si::Chunk *c);
private:
si::Chunk *GetChunkFromIndex(const QModelIndex &index) const;
si::Chunk *chunk_;
}; };
#endif // CHUNKMODEL_H #endif // CHUNKMODEL_H

View file

@ -16,12 +16,18 @@ MainWindow::MainWindow(QWidget *parent) :
splitter->setChildrenCollapsible(false); splitter->setChildrenCollapsible(false);
this->setCentralWidget(splitter); this->setCentralWidget(splitter);
model_.SetChunk(&chunk_); auto tree_tab = new QTabWidget();
splitter->addWidget(tree_tab);
auto tree = new QTreeView(); auto simple_tree = new QTreeView();
tree->setModel(&model_); simple_tree->setModel(&object_model_);
splitter->addWidget(tree); tree_tab->addTab(simple_tree, tr("Simple"));
connect(tree->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &MainWindow::SelectionChanged); connect(simple_tree->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &MainWindow::SelectionChanged);
auto lowlevel_tree = new QTreeView();
lowlevel_tree->setModel(&chunk_model_);
tree_tab->addTab(lowlevel_tree, tr("Advanced"));
connect(lowlevel_tree->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &MainWindow::SelectionChanged);
config_stack_ = new QStackedWidget(); config_stack_ = new QStackedWidget();
splitter->addWidget(config_stack_); splitter->addWidget(config_stack_);
@ -51,10 +57,12 @@ MainWindow::MainWindow(QWidget *parent) :
void MainWindow::OpenFilename(const QString &s) void MainWindow::OpenFilename(const QString &s)
{ {
model_.SetChunk(nullptr); object_model_.SetChunk(nullptr);
chunk_model_.SetChunk(nullptr);
SetPanel(panel_blank_, nullptr); SetPanel(panel_blank_, nullptr);
chunk_.Read(s.toStdString()); chunk_.Read(s.toStdString());
model_.SetChunk(&chunk_); object_model_.SetChunk(&chunk_);
chunk_model_.SetChunk(&chunk_);
} }
void MainWindow::InitializeMenuBar() void MainWindow::InitializeMenuBar()

View file

@ -6,6 +6,7 @@
#include <QStackedWidget> #include <QStackedWidget>
#include "chunkmodel.h" #include "chunkmodel.h"
#include "objectmodel.h"
#include "panels/mxch.h" #include "panels/mxch.h"
#include "panels/mxhd.h" #include "panels/mxhd.h"
#include "panels/mxob.h" #include "panels/mxob.h"
@ -30,7 +31,8 @@ private:
void SetPanel(Panel *panel, si::Chunk *chunk); void SetPanel(Panel *panel, si::Chunk *chunk);
ChunkModel model_; ObjectModel object_model_;
ChunkModel chunk_model_;
si::Chunk chunk_; si::Chunk chunk_;
QStackedWidget *config_stack_; QStackedWidget *config_stack_;

119
app/objectmodel.cpp Normal file
View file

@ -0,0 +1,119 @@
#include "objectmodel.h"
#define super AbstractSIItemModel
using namespace si;
ObjectModel::ObjectModel(QObject *parent) :
super{parent}
{
}
int ObjectModel::columnCount(const QModelIndex &parent) const
{
return kColCount;
}
QModelIndex ObjectModel::index(int row, int column, const QModelIndex &parent) const
{
return createIndex(row, column, GetItem(row));
}
QModelIndex ObjectModel::parent(const QModelIndex &index) const
{
return QModelIndex();
}
int ObjectModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid()) {
return 0;
} else {
Chunk *mxof = GetMxOf();
if (!mxof) {
return 0;
}
return mxof->data("Offsets").size() / sizeof(u32);
}
}
QVariant ObjectModel::data(const QModelIndex &index, int role) const
{
u32 offset;
Chunk *c = GetItem(index.row(), &offset);
switch (role) {
case Qt::DisplayRole:
switch (index.column()) {
case kColIndex:
return index.row();
case kColOffset:
return QStringLiteral("0x%1").arg(QString::number(offset, 16).toUpper());
case kColName:
if (c) {
Chunk *mxob = c->FindChildWithType(Chunk::TYPE_MxOb);
if (mxob) {
return QString(mxob->data("Name"));
}
}
break;
}
break;
}
return QVariant();
}
QVariant ObjectModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch (section) {
case kColIndex:
return tr("Index");
case kColOffset:
return tr("Offset");
case kColName:
return tr("Name");
}
}
return super::headerData(section, orientation, role);
}
Chunk *ObjectModel::GetMxOf() const
{
Chunk *root = this->root();
if (!root) {
return NULL;
}
return root->FindChildWithType(Chunk::TYPE_MxOf);
}
Chunk *ObjectModel::GetItem(size_t index, si::u32 *offset_out) const
{
Chunk *mxof = GetMxOf();
if (!mxof) {
return NULL;
}
const Data &offset_bytes = mxof->data("Offsets");
if (index >= offset_bytes.size()/sizeof(u32)) {
return NULL;
}
const u32 *offsets = reinterpret_cast<const u32*>(offset_bytes.data());
u32 offset = offsets[index];
if (offset_out) {
*offset_out = offset;
}
if (offset == 0) {
return NULL;
} else {
return root()->FindChildWithOffset(offset);
}
}

33
app/objectmodel.h Normal file
View file

@ -0,0 +1,33 @@
#ifndef OBJECTMODEL_H
#define OBJECTMODEL_H
#include "abstractsiitemmodel.h"
class ObjectModel : public AbstractSIItemModel
{
Q_OBJECT
public:
enum Columns {
kColIndex,
kColOffset,
kColName,
kColCount
};
explicit ObjectModel(QObject *parent = nullptr);
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override;
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
virtual QModelIndex parent(const QModelIndex &index) const override;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
private:
si::Chunk *GetMxOf() const;
si::Chunk *GetItem(size_t index, si::u32 *offset_out = NULL) const;
};
#endif // OBJECTMODEL_H

View file

@ -92,7 +92,7 @@ void MxChPanel::OnOpeningData(Chunk *chunk)
} }
const Data &data = chunk->data("Data"); const Data &data = chunk->data("Data");
QByteArray ba(data.data(), data.size()); QByteArray ba(data.data(), int(data.size()));
data_edit_->setPlainText(ba.toHex()); data_edit_->setPlainText(ba.toHex());
} }