#include "gtl_data_model.h" namespace gtl { data_model::data_model(QObject *parent) : QAbstractItemModel(parent) { } QVariant data_model::headerData(int section, Qt::Orientation orientation, int role) const { // FIXME: Implement me! return QVariant(); } QModelIndex data_model::index(int row, int column, const QModelIndex &parent) const { // FIXME: Implement me! if(row >= rowCount(parent)) return QModelIndex(); if(parent.isValid()) { return createIndex(row, column, static_cast(parent.internalPointer())->child(row)); } return createIndex(row, column, _devices[row]); } QModelIndex data_model::parent(const QModelIndex &index) const { // FIXME: Implement me! if(!index.isValid()) return QModelIndex(); gtl::data_model_node* node = static_cast(index.internalPointer()); if(node->parent_node() == NULL) { return QModelIndex(); } else if(node->parent_node()->parent_node() == NULL) { int row = std::find(_devices.begin(), _devices.end(), node->parent_node()) - _devices.begin(); return createIndex(row, 0, node->parent_node()); } else { return createIndex(index_of(node->parent_node()), 0, node->parent_node()); } } QModelIndex data_model::index(data_model_node *node) { return index(index_of(node), 0, parent(node)); } QModelIndex gtl::data_model::parent(data_model_node* node) { QModelIndex parent; if(node->parent_node()) { int row_parent = node->parent_node()->index_of(); if(row_parent < 0) row_parent = index_of(node->parent_node()); parent = createIndex(row_parent, 0, node->parent_node()); } return parent; } int data_model::rowCount(const QModelIndex &parent) const { if (parent.isValid()) return static_cast(parent.internalPointer())->count(); // FIXME: Implement me! return (int)_devices.size(); } int data_model::columnCount(const QModelIndex &parent) const { // FIXME: Implement me! return 1; } QVariant data_model::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); // FIXME: Implement me! if(role == Qt::DisplayRole) { return static_cast(index.internalPointer())->name(); } return QVariant(); } bool data_model::setData(const QModelIndex &index, const QVariant &value, int role) { data_model_node* node = static_cast(index.internalPointer()); if(node) { if(role == Qt::EditRole && !value.toString().isEmpty()) { node->set_name(value.toString()); return true; } } return false; } Qt::ItemFlags data_model::flags(const QModelIndex &index) const { Qt::ItemFlags flags = QAbstractItemModel::flags(index); data_model_node* node = static_cast(index.internalPointer()); if(node->type() != data_model_node::device) flags |= Qt::ItemFlag::ItemIsEditable; while(node->type() == data_model_node::analog) { if(!node->is_enabled()) { flags &= ~Qt::ItemFlag::ItemIsEnabled; break; } node = node->parent_node(); if(node == nullptr) break; } return flags; } void data_model::clear() { beginResetModel(); _devices.clear(); endResetModel(); } void data_model::add_device(device *d) { if(std::find(_devices.begin(), _devices.end(), d) == _devices.end()) { beginInsertRows(QModelIndex(), (int)_devices.size(), (int)_devices.size()); _devices.push_back(d); endInsertRows(); connect(d, &data_model_node::create_node, this, &data_model::create_node); connect(d, &data_model_node::deleting, this, &data_model::deleting_device); connect(d, &data_model_node::node_name_changed, this, &data_model::node_name_changed); connect(d, &data_model_node::begin_insert_children, this, &data_model::begin_add_children); connect(d, &data_model_node::end_insert_children, this, &data_model::end_add_children); connect(d, &data_model_node::begin_remove_children, this, &data_model::begin_remove_children); connect(d, &data_model_node::end_remove_children, this, &data_model::end_remove_children); } } void data_model::remove(data_model_node *node) { if(node->parent_node()) node->parent_node()->remove(node); else { int row = index_of(node); beginRemoveRows(QModelIndex(), row, row); _devices.erase(_devices.begin() + row); endRemoveRows(); } } data_model_node *data_model::node(QString path) const { QStringList tokens = path.split("/"); if(tokens.empty()) return NULL; auto iter_device = std::find_if(_devices.cbegin(), _devices.cend(), [=](const gtl::device* d){return d->name() == tokens.first();}); if(iter_device == _devices.end()) return NULL; data_model_node* node = *iter_device; for(int i = 1; i < tokens.size(); i++) { node = node->child(tokens[i].toInt()); if(node == NULL) break; } return node; } int data_model::index_of(data_model_node *node) const { if(node->type() != data_model_node::device) return node->index_of(); auto iter = std::find(_devices.cbegin(), _devices.cend(), static_cast(node)); if(iter == _devices.cend()) return -1; return std::distance(_devices.cbegin(), iter); } data_model_node *data_model::node(const QModelIndex& index) const { return static_cast(index.internalPointer()); } void data_model::save(QDomElement &root_element) { for(auto device_iter: _devices) { QDomElement device_element = root_element.ownerDocument().createElement("device"); root_element.appendChild(device_element); device_iter->save(device_element); } } void data_model::load(const QDomElement &root_element) { QDomElement device_element = root_element.firstChildElement("device"); while(!device_element.isNull()) { gtl::data_model_node* device = NULL; device = emit create_node(NULL, device_element); if(device) { add_device(static_cast(device)); device->load(device_element); } device_element = device_element.nextSiblingElement("device"); } } void data_model::begin_add_children(data_model_node* parent, int begin, int end) { QModelIndex parent_index = data_model::index(parent); beginInsertRows(parent_index, begin, end); } void data_model::end_add_children() { endInsertRows(); } void data_model::begin_remove_children(data_model_node *parent, int begin, int end) { QModelIndex parent_index = data_model::index(parent); beginRemoveRows(parent_index, begin, end); } void data_model::end_remove_children() { endRemoveRows(); } void data_model::deleting_device() { remove(static_cast(sender())); } void data_model::node_name_changed(data_model_node *node) { QModelIndex node_index = index(node); emit dataChanged(node_index, node_index, QList() << Qt::DisplayRole); } }