123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- /*
- * node_model.cpp - node tree model wrapper
- * Copyright (C) 2017 caryoscelus
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <core/node_info.h>
- #include "node_model.h"
- namespace studio {
- NodeModel::NodeModel(core::AbstractReference root_, QObject* parent) :
- QAbstractItemModel(parent),
- root(root_)
- {
- }
- NodeModel::~NodeModel() {
- }
- QVariant NodeModel::data(QModelIndex const& index, int role) const {
- if (!index.isValid())
- return QVariant();
- if (role != Qt::DisplayRole)
- return QVariant();
- if (auto node = get_node(index))
- return QString::fromStdString(core::node_name(*node));
- return "<Bad node!>";
- }
- Qt::ItemFlags NodeModel::flags(QModelIndex const&) const {
- return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
- }
- QVariant NodeModel::headerData(int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const {
- return "header";
- }
- QModelIndex NodeModel::index(int row, int column, QModelIndex const& parent) const {
- if (parent == QModelIndex()) {
- if (row == 0 && column == 0)
- return createIndex(0, 0, get_id({}, 0));
- return QModelIndex();
- }
- if (auto parent_node = get_list_node(parent)) {
- if (row >= parent_node->link_count())
- return QModelIndex();
- return createIndex(row, column, get_id(parent, row));
- }
- return QModelIndex();
- }
- bool NodeModel::can_add_element(QModelIndex const& parent) const {
- if (auto node = get_list_node(parent))
- return node->is_editable_list();
- return false;
- }
- void NodeModel::add_empty_element(QModelIndex const& parent) {
- if (auto node = get_list_node(parent)) {
- auto last = node->link_count();
- beginInsertRows(parent, last-1, last-1);
- node->push_new();
- endInsertRows();
- }
- }
- void NodeModel::convert_node(QModelIndex const& index, core::NodeInfo const* node_info, core::Time time) {
- if (auto parent_node = get_list_node(index.parent())) {
- boost::any value;
- if (auto node = get_node(index))
- value = node->get_any(time);
- auto new_node = core::make_node_with_name<core::AbstractValue>(node_info->name(), value);
- // now tell Qt about our intentions
- size_t old_rows = 0;
- if (auto node = get_list_node(index))
- old_rows = node->link_count();
- size_t new_rows = 0;
- if (auto new_list = dynamic_cast<core::AbstractListLinked*>(new_node.get()))
- new_rows = new_list->link_count();
- if (new_rows > old_rows)
- beginInsertRows(index, old_rows, new_rows-1);
- else
- beginRemoveRows(index, new_rows, old_rows-1);
- // perform action
- parent_node->set_link(index.row(), new_node);
- if (new_rows > old_rows)
- endInsertRows();
- else
- endRemoveRows();
- }
- }
- bool NodeModel::node_is_connected(QModelIndex const& index) const {
- if (auto node = get_node(index)) {
- size_t count = 0;
- return find_nodes<bool>(
- node,
- [&count]() -> boost::optional<bool> {
- if (count > 0)
- return boost::make_optional(true);
- ++count;
- return boost::none;
- }
- );
- }
- return false;
- }
- void NodeModel::disconnect_node(QModelIndex const& index) {
- replace_node(index, core::shallow_copy(*get_node(index)));
- }
- void NodeModel::connect_nodes(QList<QModelIndex> const& selection, QModelIndex const& source_index) {
- if (auto source = get_node(source_index)) {
- auto type = source->get_type();
- // TODO: check type of required by parent instead
- for (auto const& index : selection) {
- if (index != source_index && get_node(index)->get_type() == type) {
- replace_node(index, source);
- }
- }
- }
- }
- void NodeModel::replace_node(QModelIndex const& index, core::AbstractReference node) {
- if (auto parent = get_list_node(index.parent())) {
- parent->set_link(index.row(), node);
- }
- }
- bool NodeModel::removeRows(int row, int count, QModelIndex const& parent) {
- if (auto parent_node = get_list_node(parent)) {
- beginRemoveRows(parent, row, row+count-1);
- for (int i = 0; i < count; ++i)
- parent_node->remove(row+i);
- endRemoveRows();
- return true;
- }
- return false;
- }
- quintptr NodeModel::get_id(QModelIndex const& parent, size_t i) const {
- std::pair<QModelIndex,size_t> pair = {parent, i};
- auto found = indexes.find(pair);
- if (found != indexes.end())
- return found->second;
- auto interal_id = index_count++;
- indexes.emplace(pair, interal_id);
- parents.emplace(interal_id, parent);
- return interal_id;
- }
- core::AbstractReference NodeModel::get_node(QModelIndex const& index) const {
- if (index == QModelIndex())
- return nullptr;
- if (index.parent() == QModelIndex())
- return root;
- if (auto pnode = get_node(index.parent())) {
- if (auto parent_node = std::dynamic_pointer_cast<core::AbstractListLinked>(pnode))
- return parent_node->get_links()[index.row()];
- }
- return nullptr;
- }
- size_t NodeModel::get_node_index(QModelIndex const& index) const {
- return index.row();
- }
- QModelIndex NodeModel::parent(QModelIndex const& index) const {
- if (index == QModelIndex())
- return QModelIndex();
- auto id = index.internalId();
- return parents.at(id);
- }
- int NodeModel::rowCount(QModelIndex const& parent) const {
- if (auto value = get_node(parent)) {
- if (auto node = std::dynamic_pointer_cast<core::AbstractListLinked>(value))
- return node->link_count();
- return 0;
- }
- if (root)
- return 1;
- return 0;
- }
- int NodeModel::columnCount(QModelIndex const& /*parent*/) const {
- return 1;
- }
- } // namespace studio
|