From 28c9fe25b3d37d7919ffa6154b82b3c166540c33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4berich?= Date: Sat, 10 Apr 2021 12:04:07 +0200 Subject: [PATCH] Experimental json tree view --- .../CustomWidgets/jsonpickerdialog.cpp | 183 ++++++++++++++++++ .../CustomWidgets/jsonpickerdialog.h | 55 ++++++ .../CustomWidgets/jsonpickerdialog.ui | 67 +++++++ 3 files changed, 305 insertions(+) create mode 100644 Software/PC_Application/CustomWidgets/jsonpickerdialog.cpp create mode 100644 Software/PC_Application/CustomWidgets/jsonpickerdialog.h create mode 100644 Software/PC_Application/CustomWidgets/jsonpickerdialog.ui diff --git a/Software/PC_Application/CustomWidgets/jsonpickerdialog.cpp b/Software/PC_Application/CustomWidgets/jsonpickerdialog.cpp new file mode 100644 index 0000000..627a73b --- /dev/null +++ b/Software/PC_Application/CustomWidgets/jsonpickerdialog.cpp @@ -0,0 +1,183 @@ +#include "jsonpickerdialog.h" +#include "ui_jsonpickerdialog.h" + + + + +JSONPickerDialog::JSONPickerDialog(const nlohmann::json &json, QWidget *parent) : + QDialog(parent), + ui(new Ui::JSONPickerDialog), + model(new JSONModel(json)) +{ + ui->setupUi(this); + ui->treeView->setModel(model); +} + +JSONPickerDialog::~JSONPickerDialog() +{ + delete ui; + delete model; +} + +JSONModel::JSONModel(const nlohmann::json &json, QObject *parent) : + json(json) +{ + setupJsonInfo(json); +} + +JSONModel::~JSONModel() +{ + +} + +QModelIndex JSONModel::index(int row, int column, const QModelIndex &parent) const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + nlohmann::json const *parentItem; + + if (!parent.isValid()) + parentItem = &json; + else + parentItem = static_cast(parent.internalPointer()); + + auto it = parentItem->begin(); + int rb = row; + while(rb) { + it++; + rb--; + } + nlohmann::json *childItem = const_cast(&*it); + if (childItem) + return createIndex(row, column, childItem); + return QModelIndex(); +} + +QModelIndex JSONModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) + return QModelIndex(); + + nlohmann::json *childItem = static_cast(index.internalPointer()); + if (childItem == &json) { + return QModelIndex(); + } + + // find the parent of this entry and its position in the list + nlohmann::json *parentItem = const_cast(jsonInfo.at(childItem).parent); + auto it = parentItem->begin(); + int row = 0; + while(&*it != childItem) { + it++; + row++; + } + return createIndex(row, 0, parentItem); +} + +int JSONModel::rowCount(const QModelIndex &parent) const +{ + const nlohmann::json *parentItem; + if (parent.column() > 0) { + return 0; + } + + if (!parent.isValid()) { + parentItem = &json; + } else { + parentItem = static_cast(parent.internalPointer()); + } + + if (parentItem->is_object() || parentItem->is_array()) { + return parentItem->size(); + } else { + return 0; + } +} + +int JSONModel::columnCount(const QModelIndex &parent) const +{ + return 2; +} + +QVariant JSONModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + nlohmann::json *item = static_cast(index.internalPointer()); + auto info = jsonInfo.at(item); + switch(role) { + case Qt::DisplayRole: + switch(index.column()) { + case 0: + return info.name; + case 1: + if(item->is_object() || item->is_array()) { + return QVariant(); + } else { + return info.data; + } + } + case Qt::CheckStateRole: { + if(index.column() == 0) { + return info.enabled ? Qt::Checked : Qt::Unchecked; + } else { + return QVariant(); + } + } + default: + return QVariant(); + } +} + +QVariant JSONModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + return QVariant(); +} + +bool JSONModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + nlohmann::json *item = static_cast(index.internalPointer()); + auto info = jsonInfo.at(item); + if(role == Qt::CheckStateRole) + { + info.enabled = !info.enabled; + jsonInfo[item] = info; + emit dataChanged(index, index); + return true; + } + + if (role != Qt::EditRole) + return false; + return true; +} + +Qt::ItemFlags JSONModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) { + return Qt::NoItemFlags; + } + + return Qt::ItemIsEditable | QAbstractItemModel::flags(index)|Qt::ItemIsUserCheckable; +} + +void JSONModel::setupJsonInfo(const nlohmann::json &j) +{ + for(auto it = j.begin();it != j.end(); it++) { + JSONInfo i; + i.parent = &j; + i.enabled = true; + if(j.is_object()) { + i.name = it.key().c_str(); + } else if(j.is_array()) { + i.name = QString::number(it - j.begin() + 1); + } + if(it->is_object() || it->is_array()) { + setupJsonInfo(*it); + } else { + i.data = QString::fromStdString(it->dump()); + } + jsonInfo[&*it] = i; + } +} diff --git a/Software/PC_Application/CustomWidgets/jsonpickerdialog.h b/Software/PC_Application/CustomWidgets/jsonpickerdialog.h new file mode 100644 index 0000000..bb30019 --- /dev/null +++ b/Software/PC_Application/CustomWidgets/jsonpickerdialog.h @@ -0,0 +1,55 @@ +#ifndef JSONPICKERDIALOG_H +#define JSONPICKERDIALOG_H + +#include +#include +#include "json.hpp" + +namespace Ui { +class JSONPickerDialog; +} + +class JSONModel : public QAbstractItemModel +{ + Q_OBJECT +public: + JSONModel(const nlohmann::json &json, QObject *parent = 0); + ~JSONModel(); + + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex &index) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + Qt::ItemFlags flags(const QModelIndex &index) const override; + +private: + void setupJsonInfo(const nlohmann::json &j); + const nlohmann::json &json; + class JSONInfo { + public: + const nlohmann::json *parent; + QString name; + QString data; + bool enabled; + }; + + std::map jsonInfo; +}; + +class JSONPickerDialog : public QDialog +{ + Q_OBJECT + +public: + explicit JSONPickerDialog(const nlohmann::json &json, QWidget *parent = nullptr); + ~JSONPickerDialog(); + +private: + Ui::JSONPickerDialog *ui; + JSONModel *model; +}; + +#endif // JSONPICKERDIALOG_H diff --git a/Software/PC_Application/CustomWidgets/jsonpickerdialog.ui b/Software/PC_Application/CustomWidgets/jsonpickerdialog.ui new file mode 100644 index 0000000..d73f3ba --- /dev/null +++ b/Software/PC_Application/CustomWidgets/jsonpickerdialog.ui @@ -0,0 +1,67 @@ + + + JSONPickerDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + JSONPickerDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + JSONPickerDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +