node_model.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * node_model.cpp - node tree model wrapper
  3. * Copyright (C) 2017 caryoscelus
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <core/node_info.h>
  19. #include "node_model.h"
  20. namespace studio {
  21. NodeModel::NodeModel(core::AbstractReference root_, QObject* parent) :
  22. QAbstractItemModel(parent),
  23. root(root_)
  24. {
  25. }
  26. NodeModel::~NodeModel() {
  27. }
  28. QVariant NodeModel::data(QModelIndex const& index, int role) const {
  29. if (!index.isValid())
  30. return QVariant();
  31. if (role != Qt::DisplayRole)
  32. return QVariant();
  33. if (auto node = get_node(index))
  34. return QString::fromStdString(core::node_name(*node));
  35. return "<Bad node!>";
  36. }
  37. Qt::ItemFlags NodeModel::flags(QModelIndex const&) const {
  38. return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
  39. }
  40. QVariant NodeModel::headerData(int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const {
  41. return "header";
  42. }
  43. QModelIndex NodeModel::index(int row, int column, QModelIndex const& parent) const {
  44. if (parent == QModelIndex()) {
  45. if (row == 0 && column == 0)
  46. return createIndex(0, 0, get_id({}, 0));
  47. return QModelIndex();
  48. }
  49. if (auto parent_node = get_list_node(parent)) {
  50. if (row >= parent_node->link_count())
  51. return QModelIndex();
  52. return createIndex(row, column, get_id(parent, row));
  53. }
  54. return QModelIndex();
  55. }
  56. bool NodeModel::can_add_element(QModelIndex const& parent) const {
  57. if (auto node = get_list_node(parent))
  58. return node->is_editable_list();
  59. return false;
  60. }
  61. void NodeModel::add_empty_element(QModelIndex const& parent) {
  62. if (auto node = get_list_node(parent)) {
  63. auto last = node->link_count();
  64. beginInsertRows(parent, last-1, last-1);
  65. node->push_new();
  66. endInsertRows();
  67. }
  68. }
  69. void NodeModel::convert_node(QModelIndex const& index, core::NodeInfo const* node_info, core::Time time) {
  70. if (auto parent_node = get_list_node(index.parent())) {
  71. boost::any value;
  72. if (auto node = get_node(index))
  73. value = node->get_any(time);
  74. auto new_node = core::make_node_with_name<core::AbstractValue>(node_info->name(), value);
  75. // now tell Qt about our intentions
  76. size_t old_rows = 0;
  77. if (auto node = get_list_node(index))
  78. old_rows = node->link_count();
  79. size_t new_rows = 0;
  80. if (auto new_list = dynamic_cast<core::AbstractListLinked*>(new_node.get()))
  81. new_rows = new_list->link_count();
  82. if (new_rows > old_rows)
  83. beginInsertRows(index, old_rows, new_rows-1);
  84. else
  85. beginRemoveRows(index, new_rows, old_rows-1);
  86. // perform action
  87. parent_node->set_link(index.row(), new_node);
  88. if (new_rows > old_rows)
  89. endInsertRows();
  90. else
  91. endRemoveRows();
  92. }
  93. }
  94. bool NodeModel::node_is_connected(QModelIndex const& index) const {
  95. if (auto node = get_node(index)) {
  96. size_t count = 0;
  97. return find_nodes<bool>(
  98. node,
  99. [&count]() -> boost::optional<bool> {
  100. if (count > 0)
  101. return boost::make_optional(true);
  102. ++count;
  103. return boost::none;
  104. }
  105. );
  106. }
  107. return false;
  108. }
  109. void NodeModel::disconnect_node(QModelIndex const& index) {
  110. replace_node(index, core::shallow_copy(*get_node(index)));
  111. }
  112. void NodeModel::connect_nodes(QList<QModelIndex> const& selection, QModelIndex const& source_index) {
  113. if (auto source = get_node(source_index)) {
  114. auto type = source->get_type();
  115. // TODO: check type of required by parent instead
  116. for (auto const& index : selection) {
  117. if (index != source_index && get_node(index)->get_type() == type) {
  118. replace_node(index, source);
  119. }
  120. }
  121. }
  122. }
  123. void NodeModel::replace_node(QModelIndex const& index, core::AbstractReference node) {
  124. if (auto parent = get_list_node(index.parent())) {
  125. parent->set_link(index.row(), node);
  126. }
  127. }
  128. bool NodeModel::removeRows(int row, int count, QModelIndex const& parent) {
  129. if (auto parent_node = get_list_node(parent)) {
  130. beginRemoveRows(parent, row, row+count-1);
  131. for (int i = 0; i < count; ++i)
  132. parent_node->remove(row+i);
  133. endRemoveRows();
  134. return true;
  135. }
  136. return false;
  137. }
  138. quintptr NodeModel::get_id(QModelIndex const& parent, size_t i) const {
  139. std::pair<QModelIndex,size_t> pair = {parent, i};
  140. auto found = indexes.find(pair);
  141. if (found != indexes.end())
  142. return found->second;
  143. auto interal_id = index_count++;
  144. indexes.emplace(pair, interal_id);
  145. parents.emplace(interal_id, parent);
  146. return interal_id;
  147. }
  148. core::AbstractReference NodeModel::get_node(QModelIndex const& index) const {
  149. if (index == QModelIndex())
  150. return nullptr;
  151. if (index.parent() == QModelIndex())
  152. return root;
  153. if (auto pnode = get_node(index.parent())) {
  154. if (auto parent_node = std::dynamic_pointer_cast<core::AbstractListLinked>(pnode))
  155. return parent_node->get_links()[index.row()];
  156. }
  157. return nullptr;
  158. }
  159. size_t NodeModel::get_node_index(QModelIndex const& index) const {
  160. return index.row();
  161. }
  162. QModelIndex NodeModel::parent(QModelIndex const& index) const {
  163. if (index == QModelIndex())
  164. return QModelIndex();
  165. auto id = index.internalId();
  166. return parents.at(id);
  167. }
  168. int NodeModel::rowCount(QModelIndex const& parent) const {
  169. if (auto value = get_node(parent)) {
  170. if (auto node = std::dynamic_pointer_cast<core::AbstractListLinked>(value))
  171. return node->link_count();
  172. return 0;
  173. }
  174. if (root)
  175. return 1;
  176. return 0;
  177. }
  178. int NodeModel::columnCount(QModelIndex const& /*parent*/) const {
  179. return 1;
  180. }
  181. } // namespace studio