#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) { Q_UNUSED(parent) 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 { Q_UNUSED(parent) 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 info.data; } } return QVariant(); 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 { Q_UNUSED(section) Q_UNUSED(orientation) Q_UNUSED(role) return QVariant(); } bool JSONModel::setData(const QModelIndex &index, const QVariant &value, int role) { Q_UNUSED(value) 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; } }