diff --git a/DRAMSys/traceAnalyzer/businessObjects/configmodels.cpp b/DRAMSys/traceAnalyzer/businessObjects/configmodels.cpp index 3748d438..b3d4400f 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/configmodels.cpp +++ b/DRAMSys/traceAnalyzer/businessObjects/configmodels.cpp @@ -49,14 +49,12 @@ McConfigModel::McConfigModel(const TraceDB &traceFile, QObject *parent) : QAbstr QString mcConfigJson = sqlQuery.value(0).toString(); parseJson(mcConfigJson); - - qDebug() << roleNames(); } void McConfigModel::parseJson(const QString &jsonString) { QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonString.toUtf8()); - QJsonObject mcConfigJson = jsonDocument["mcconfig"].toObject(); + QJsonObject mcConfigJson = jsonDocument.object()["mcconfig"].toObject(); for (auto key : mcConfigJson.keys()) { @@ -124,3 +122,152 @@ QVariant McConfigModel::headerData(int section, Qt::Orientation orientation, int return QVariant(); } + +MemSpecModel::MemSpecModel(const TraceDB &traceFile, QObject *parent) : QAbstractItemModel(parent) +{ + QSqlDatabase db = traceFile.getDatabase(); + QString query = "SELECT Memspec FROM GeneralInfo"; + QSqlQuery sqlQuery = db.exec(query); + + // The whole configuration is stored in a single cell. + sqlQuery.next(); + QString memSpecJson = sqlQuery.value(0).toString(); + + parseJson(memSpecJson); +} + +int MemSpecModel::Node::getRow() const +{ + if (!parent) + return 0; + + const auto &siblings = parent->children; + const auto siblingsIt = std::find_if(siblings.begin(), siblings.end(), [this](const std::unique_ptr &node){ + return node.get() == this; + }); + + Q_ASSERT(siblingsIt != siblings.end()); + + return std::distance(siblings.begin(), siblingsIt); +} + +void MemSpecModel::parseJson(const QString &jsonString) +{ + QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonString.toUtf8()); + QJsonObject memSpecJson = jsonDocument.object()["memspec"].toObject(); + + std::function &)> addNodes; + addNodes = [&addNodes](const QJsonObject &obj, std::unique_ptr &parentNode) + { + for (auto key : obj.keys()) + { + QJsonValue currentValue = obj.value(key); + + QString value; + if (currentValue.isDouble()) + { + value = QString::number(currentValue.toDouble()); + } + else if (currentValue.isString()) + { + value = currentValue.toString(); + } + + std::unique_ptr node = std::unique_ptr(new Node(std::make_pair(key, value), parentNode.get())); + addNodes(obj[key].toObject(), node); + + parentNode->children.push_back(std::move(node)); + } + }; + + addNodes(memSpecJson, rootNode); +} + +int MemSpecModel::rowCount(const QModelIndex &parent) const +{ + if (parent.column() > 0) + return 0; + + const Node *parentNode; + + if (!parent.isValid()) + parentNode = rootNode.get(); + else + parentNode = static_cast(parent.internalPointer()); + + return parentNode->childCount(); +} + +int MemSpecModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + + return 2; +} + +QVariant MemSpecModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (role != Qt::DisplayRole && role != Qt::ToolTipRole) + return QVariant(); + + auto *node = static_cast(index.internalPointer()); + + if (index.column() == 0) + return QVariant(node->data.first); + else + return QVariant(node->data.second); +} + +QVariant MemSpecModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + if (orientation == Qt::Horizontal) + { + switch (section) { + case 0: + return "Field"; + case 1: + return "Value"; + default: + break; + } + } + + return QVariant(); +} + +QModelIndex MemSpecModel::index(int row, int column, const QModelIndex &parent) const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + const Node *parentNode; + + if (!parent.isValid()) + parentNode = rootNode.get(); + else + parentNode = static_cast(parent.internalPointer()); + + const Node *node = parentNode->children[row].get(); + + return createIndex(row, column, const_cast(node)); +} + +QModelIndex MemSpecModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) + return QModelIndex(); + + const Node *childNode = static_cast(index.internalPointer()); + const Node *parentNode = childNode->parent; + + if (!parentNode) + return QModelIndex(); + + return createIndex(parentNode->getRow(), 0, const_cast(parentNode)); +} diff --git a/DRAMSys/traceAnalyzer/businessObjects/configmodels.h b/DRAMSys/traceAnalyzer/businessObjects/configmodels.h index 327b20cb..2548ab39 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/configmodels.h +++ b/DRAMSys/traceAnalyzer/businessObjects/configmodels.h @@ -44,13 +44,16 @@ class McConfigModel : public QAbstractTableModel { + Q_OBJECT + public: - McConfigModel(const TraceDB &traceFile, QObject *parent = nullptr); + explicit McConfigModel(const TraceDB &traceFile, QObject *parent = nullptr); ~McConfigModel() {} protected: int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; @@ -65,9 +68,52 @@ private: std::vector> entries; }; -class MemSpecsModel : public QAbstractItemModel +class MemSpecModel : public QAbstractItemModel { + Q_OBJECT +public: + explicit MemSpecModel(const TraceDB &traceFile, QObject *parent = nullptr); + ~MemSpecModel() {} + +protected: + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + + QModelIndex index(int row, int column, const QModelIndex &parent) const override; + QModelIndex parent(const QModelIndex &index) const override; + +private: + /** + * Parses the json file and adds json entries to the entries vector. + * In case of failure, nothing is added and therefore the model + * will stay empty. + */ + void parseJson(const QString &jsonString); + + struct Node + { + using NodeData = std::pair; + + Node() {} + Node(NodeData data, const Node *parent) : data(data), parent(parent) {} + + /** + * Gets the row relative to its parent. + */ + int getRow() const; + int childCount() const { return children.size(); } + + NodeData data; + + const Node *parent = nullptr; + std::vector> children; + }; + + std::unique_ptr rootNode = std::unique_ptr(new Node); }; #endif // CONFIGMODELS_H diff --git a/DRAMSys/traceAnalyzer/tracefiletab.cpp b/DRAMSys/traceAnalyzer/tracefiletab.cpp index 93c60ae4..36c95509 100644 --- a/DRAMSys/traceAnalyzer/tracefiletab.cpp +++ b/DRAMSys/traceAnalyzer/tracefiletab.cpp @@ -65,7 +65,9 @@ TraceFileTab::TraceFileTab(QWidget *parent, const QString &path) : QWidget(parent), ui(new Ui::TraceFileTab), navigator(new TraceNavigator(path, this)), - mcConfigModel(new McConfigModel(navigator->TraceFile(), this)), savingChangesToDB(false) + mcConfigModel(new McConfigModel(navigator->TraceFile(), this)), + memSpecModel(new MemSpecModel(navigator->TraceFile(), this)), + savingChangesToDB(false) { ui->setupUi(this); this->path = path; @@ -84,6 +86,9 @@ TraceFileTab::TraceFileTab(QWidget *parent, const QString &path) : ui->mcConfigView->setModel(mcConfigModel); ui->mcConfigView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + ui->memSpecView->setModel(memSpecModel); + ui->memSpecView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + tracefileChanged(); } diff --git a/DRAMSys/traceAnalyzer/tracefiletab.h b/DRAMSys/traceAnalyzer/tracefiletab.h index 9fd7b3a3..966d5784 100644 --- a/DRAMSys/traceAnalyzer/tracefiletab.h +++ b/DRAMSys/traceAnalyzer/tracefiletab.h @@ -77,7 +77,7 @@ private: QFileSystemWatcher *fileWatcher; QAbstractItemModel *mcConfigModel; - //QAbstractItemModel *memSpecModel; + QAbstractItemModel *memSpecModel; void setUpQueryEditor(QString path); bool savingChangesToDB; diff --git a/DRAMSys/traceAnalyzer/tracefiletab.ui b/DRAMSys/traceAnalyzer/tracefiletab.ui index c6555e26..64693bdb 100644 --- a/DRAMSys/traceAnalyzer/tracefiletab.ui +++ b/DRAMSys/traceAnalyzer/tracefiletab.ui @@ -350,7 +350,7 @@ - Simulation Configuration + Configuration @@ -373,7 +373,11 @@ - + + + true + +