Model.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <LibGUI/AbstractView.h>
  8. #include <LibGUI/Model.h>
  9. #include <LibGUI/PersistentModelIndex.h>
  10. namespace GUI {
  11. Model::Model()
  12. {
  13. }
  14. Model::~Model()
  15. {
  16. }
  17. void Model::register_view(Badge<AbstractView>, AbstractView& view)
  18. {
  19. m_views.set(&view);
  20. m_clients.set(&view);
  21. }
  22. void Model::unregister_view(Badge<AbstractView>, AbstractView& view)
  23. {
  24. m_views.remove(&view);
  25. m_clients.remove(&view);
  26. }
  27. void Model::invalidate()
  28. {
  29. m_persistent_handles.clear();
  30. did_update();
  31. }
  32. void Model::for_each_view(Function<void(AbstractView&)> callback)
  33. {
  34. for (auto* view : m_views)
  35. callback(*view);
  36. }
  37. void Model::for_each_client(Function<void(ModelClient&)> callback)
  38. {
  39. for (auto* client : m_clients)
  40. callback(*client);
  41. }
  42. void Model::did_update(unsigned flags)
  43. {
  44. for_each_client([flags](ModelClient& client) {
  45. client.model_did_update(flags);
  46. });
  47. }
  48. ModelIndex Model::create_index(int row, int column, void const* data) const
  49. {
  50. return ModelIndex(*this, row, column, const_cast<void*>(data));
  51. }
  52. ModelIndex Model::index(int row, int column, ModelIndex const&) const
  53. {
  54. return create_index(row, column);
  55. }
  56. bool Model::accepts_drag(ModelIndex const&, Vector<String> const&) const
  57. {
  58. return false;
  59. }
  60. void Model::register_client(ModelClient& client)
  61. {
  62. m_clients.set(&client);
  63. }
  64. void Model::unregister_client(ModelClient& client)
  65. {
  66. m_clients.remove(&client);
  67. }
  68. WeakPtr<PersistentHandle> Model::register_persistent_index(Badge<PersistentModelIndex>, ModelIndex const& index)
  69. {
  70. if (!index.is_valid())
  71. return {};
  72. auto it = m_persistent_handles.find(index);
  73. // Easy modo: we already have a handle for this model index.
  74. if (it != m_persistent_handles.end()) {
  75. return it->value->make_weak_ptr();
  76. }
  77. // Hard modo: create a new persistent handle.
  78. auto handle = adopt_own(*new PersistentHandle(index));
  79. auto weak_handle = handle->make_weak_ptr();
  80. m_persistent_handles.set(index, move(handle));
  81. return weak_handle;
  82. }
  83. RefPtr<Core::MimeData> Model::mime_data(ModelSelection const& selection) const
  84. {
  85. auto mime_data = Core::MimeData::construct();
  86. RefPtr<Gfx::Bitmap> bitmap;
  87. StringBuilder text_builder;
  88. StringBuilder data_builder;
  89. bool first = true;
  90. selection.for_each_index([&](auto& index) {
  91. auto text_data = index.data();
  92. if (!first)
  93. text_builder.append(", ");
  94. text_builder.append(text_data.to_string());
  95. if (!first)
  96. data_builder.append('\n');
  97. auto data = index.data(ModelRole::MimeData);
  98. data_builder.append(data.to_string());
  99. first = false;
  100. if (!bitmap) {
  101. Variant icon_data = index.data(ModelRole::Icon);
  102. if (icon_data.is_icon())
  103. bitmap = icon_data.as_icon().bitmap_for_size(32);
  104. }
  105. });
  106. mime_data->set_data(drag_data_type(), data_builder.to_byte_buffer());
  107. mime_data->set_text(text_builder.to_string());
  108. if (bitmap)
  109. mime_data->set_data("image/x-raw-bitmap", bitmap->serialize_to_byte_buffer());
  110. return mime_data;
  111. }
  112. void Model::begin_insert_rows(ModelIndex const& parent, int first, int last)
  113. {
  114. VERIFY(first >= 0);
  115. VERIFY(first <= last);
  116. m_operation_stack.empend(OperationType::Insert, Direction::Row, parent, first, last);
  117. }
  118. void Model::begin_insert_columns(ModelIndex const& parent, int first, int last)
  119. {
  120. VERIFY(first >= 0);
  121. VERIFY(first <= last);
  122. m_operation_stack.empend(OperationType::Insert, Direction::Column, parent, first, last);
  123. }
  124. void Model::begin_move_rows(ModelIndex const& source_parent, int first, int last, ModelIndex const& target_parent, int target_index)
  125. {
  126. VERIFY(first >= 0);
  127. VERIFY(first <= last);
  128. VERIFY(target_index >= 0);
  129. m_operation_stack.empend(OperationType::Move, Direction::Row, source_parent, first, last, target_parent, target_index);
  130. }
  131. void Model::begin_move_columns(ModelIndex const& source_parent, int first, int last, ModelIndex const& target_parent, int target_index)
  132. {
  133. VERIFY(first >= 0);
  134. VERIFY(first <= last);
  135. VERIFY(target_index >= 0);
  136. m_operation_stack.empend(OperationType::Move, Direction::Column, source_parent, first, last, target_parent, target_index);
  137. }
  138. void Model::begin_delete_rows(ModelIndex const& parent, int first, int last)
  139. {
  140. VERIFY(first >= 0);
  141. VERIFY(first <= last);
  142. VERIFY(last < row_count(parent));
  143. save_deleted_indices<true>(parent, first, last);
  144. m_operation_stack.empend(OperationType::Delete, Direction::Row, parent, first, last);
  145. }
  146. void Model::begin_delete_columns(ModelIndex const& parent, int first, int last)
  147. {
  148. VERIFY(first >= 0);
  149. VERIFY(first <= last);
  150. VERIFY(last < column_count(parent));
  151. save_deleted_indices<false>(parent, first, last);
  152. m_operation_stack.empend(OperationType::Delete, Direction::Column, parent, first, last);
  153. }
  154. template<bool IsRow>
  155. void Model::save_deleted_indices(ModelIndex const& parent, int first, int last)
  156. {
  157. Vector<ModelIndex> deleted_indices;
  158. for (auto& entry : m_persistent_handles) {
  159. auto current_index = entry.key;
  160. // Walk up the persistent handle's parents to see if it is contained
  161. // within the range that is being deleted.
  162. while (current_index.is_valid()) {
  163. auto current_parent = current_index.parent();
  164. if (current_parent == parent) {
  165. if constexpr (IsRow) {
  166. if (current_index.row() >= first && current_index.row() <= last)
  167. deleted_indices.append(current_index);
  168. } else {
  169. if (current_index.column() >= first && current_index.column() <= last)
  170. deleted_indices.append(current_index);
  171. }
  172. }
  173. current_index = current_parent;
  174. }
  175. }
  176. m_deleted_indices_stack.append(move(deleted_indices));
  177. }
  178. void Model::end_insert_rows()
  179. {
  180. auto operation = m_operation_stack.take_last();
  181. VERIFY(operation.type == OperationType::Insert);
  182. VERIFY(operation.direction == Direction::Row);
  183. handle_insert(operation);
  184. for_each_client([&operation](ModelClient& client) {
  185. client.model_did_insert_rows(operation.source_parent, operation.first, operation.last);
  186. });
  187. }
  188. void Model::end_insert_columns()
  189. {
  190. auto operation = m_operation_stack.take_last();
  191. VERIFY(operation.type == OperationType::Insert);
  192. VERIFY(operation.direction == Direction::Column);
  193. handle_insert(operation);
  194. for_each_client([&operation](ModelClient& client) {
  195. client.model_did_insert_columns(operation.source_parent, operation.first, operation.last);
  196. });
  197. }
  198. void Model::end_move_rows()
  199. {
  200. auto operation = m_operation_stack.take_last();
  201. VERIFY(operation.type == OperationType::Move);
  202. VERIFY(operation.direction == Direction::Row);
  203. handle_move(operation);
  204. for_each_client([&operation](ModelClient& client) {
  205. client.model_did_move_rows(operation.source_parent, operation.first, operation.last, operation.target_parent, operation.target);
  206. });
  207. }
  208. void Model::end_move_columns()
  209. {
  210. auto operation = m_operation_stack.take_last();
  211. VERIFY(operation.type == OperationType::Move);
  212. VERIFY(operation.direction == Direction::Column);
  213. handle_move(operation);
  214. for_each_client([&operation](ModelClient& client) {
  215. client.model_did_move_columns(operation.source_parent, operation.first, operation.last, operation.target_parent, operation.target);
  216. });
  217. }
  218. void Model::end_delete_rows()
  219. {
  220. auto operation = m_operation_stack.take_last();
  221. VERIFY(operation.type == OperationType::Delete);
  222. VERIFY(operation.direction == Direction::Row);
  223. handle_delete(operation);
  224. for_each_client([&operation](ModelClient& client) {
  225. client.model_did_delete_rows(operation.source_parent, operation.first, operation.last);
  226. });
  227. }
  228. void Model::end_delete_columns()
  229. {
  230. auto operation = m_operation_stack.take_last();
  231. VERIFY(operation.type == OperationType::Delete);
  232. VERIFY(operation.direction == Direction::Column);
  233. handle_delete(operation);
  234. for_each_client([&operation](ModelClient& client) {
  235. client.model_did_delete_columns(operation.source_parent, operation.first, operation.last);
  236. });
  237. }
  238. void Model::change_persistent_index_list(Vector<ModelIndex> const& old_indices, Vector<ModelIndex> const& new_indices)
  239. {
  240. VERIFY(old_indices.size() == new_indices.size());
  241. for (size_t i = 0; i < old_indices.size(); i++) {
  242. auto it = m_persistent_handles.find(old_indices.at(i));
  243. if (it == m_persistent_handles.end())
  244. continue;
  245. auto handle = move(it->value);
  246. m_persistent_handles.remove(it);
  247. auto new_index = new_indices.at(i);
  248. if (new_index.is_valid()) {
  249. handle->m_index = new_index;
  250. m_persistent_handles.set(new_index, move(handle));
  251. }
  252. }
  253. }
  254. void Model::handle_insert(Operation const& operation)
  255. {
  256. bool is_row = operation.direction == Direction::Row;
  257. Vector<ModelIndex*> to_shift;
  258. for (auto& entry : m_persistent_handles) {
  259. if (entry.key.parent() == operation.source_parent) {
  260. if (is_row && entry.key.row() >= operation.first) {
  261. to_shift.append(&entry.key);
  262. } else if (!is_row && entry.key.column() >= operation.first) {
  263. to_shift.append(&entry.key);
  264. }
  265. }
  266. }
  267. int offset = operation.last - operation.first + 1;
  268. for (auto current_index : to_shift) {
  269. int new_row = is_row ? current_index->row() + offset : current_index->row();
  270. int new_column = is_row ? current_index->column() : current_index->column() + offset;
  271. auto new_index = create_index(new_row, new_column, current_index->internal_data());
  272. auto it = m_persistent_handles.find(*current_index);
  273. auto handle = move(it->value);
  274. handle->m_index = new_index;
  275. m_persistent_handles.remove(it);
  276. m_persistent_handles.set(move(new_index), move(handle));
  277. }
  278. }
  279. void Model::handle_delete(Operation const& operation)
  280. {
  281. bool is_row = operation.direction == Direction::Row;
  282. Vector<ModelIndex> deleted_indices = m_deleted_indices_stack.take_last();
  283. Vector<ModelIndex*> to_shift;
  284. // Get rid of all persistent handles which have been marked for death
  285. for (auto& deleted_index : deleted_indices) {
  286. m_persistent_handles.remove(deleted_index);
  287. }
  288. for (auto& entry : m_persistent_handles) {
  289. if (entry.key.parent() == operation.source_parent) {
  290. if (is_row) {
  291. if (entry.key.row() > operation.last) {
  292. to_shift.append(&entry.key);
  293. }
  294. } else {
  295. if (entry.key.column() > operation.last) {
  296. to_shift.append(&entry.key);
  297. }
  298. }
  299. }
  300. }
  301. int offset = operation.last - operation.first + 1;
  302. for (auto current_index : to_shift) {
  303. int new_row = is_row ? current_index->row() - offset : current_index->row();
  304. int new_column = is_row ? current_index->column() : current_index->column() - offset;
  305. auto new_index = create_index(new_row, new_column, current_index->internal_data());
  306. auto it = m_persistent_handles.find(*current_index);
  307. auto handle = move(it->value);
  308. handle->m_index = new_index;
  309. m_persistent_handles.remove(it);
  310. m_persistent_handles.set(move(new_index), move(handle));
  311. }
  312. }
  313. void Model::handle_move(Operation const& operation)
  314. {
  315. bool is_row = operation.direction == Direction::Row;
  316. bool move_within = operation.source_parent == operation.target_parent;
  317. bool moving_down = operation.target > operation.first;
  318. if (move_within && operation.first == operation.target)
  319. return;
  320. if (is_row) {
  321. VERIFY(operation.target <= row_count(operation.target_parent));
  322. VERIFY(operation.last < row_count(operation.source_parent));
  323. } else {
  324. VERIFY(operation.target <= column_count(operation.target_parent));
  325. VERIFY(operation.last < column_count(operation.source_parent));
  326. }
  327. // NOTE: to_shift_down is used as a generic "to shift" when move_within is true.
  328. Vector<ModelIndex*> to_move; // Items to be moved between the source and target
  329. Vector<ModelIndex*> to_shift_down; // Items to be shifted down after a move-to
  330. Vector<ModelIndex*> to_shift_up; // Items to be shifted up after a move-from
  331. int count = operation.last - operation.first + 1;
  332. // [start, end)
  333. int work_area_start = min(operation.first, operation.target);
  334. int work_area_end = max(operation.last + 1, operation.target + count);
  335. for (auto& entry : m_persistent_handles) {
  336. int dimension = is_row ? entry.key.row() : entry.key.column();
  337. if (move_within) {
  338. if (entry.key.parent() == operation.source_parent) {
  339. if (dimension >= operation.first && dimension <= operation.last) {
  340. to_move.append(&entry.key);
  341. } else if (moving_down && dimension > operation.last && dimension < work_area_end) {
  342. to_shift_down.append(&entry.key);
  343. } else if (!moving_down && dimension >= work_area_start && dimension < operation.first) {
  344. to_shift_down.append(&entry.key);
  345. }
  346. }
  347. } else {
  348. if (entry.key.parent() == operation.source_parent) {
  349. if (dimension >= operation.first && dimension <= operation.last) {
  350. to_move.append(&entry.key);
  351. } else if (dimension > operation.last) {
  352. to_shift_up.append(&entry.key);
  353. }
  354. } else if (entry.key.parent() == operation.target_parent) {
  355. if (dimension >= operation.target) {
  356. to_shift_down.append(&entry.key);
  357. }
  358. }
  359. }
  360. }
  361. auto replace_handle = [&](ModelIndex const& current_index, int new_dimension, bool relative) {
  362. int new_row = is_row
  363. ? (relative
  364. ? current_index.row() + new_dimension
  365. : new_dimension)
  366. : current_index.row();
  367. int new_column = !is_row
  368. ? (relative
  369. ? current_index.column() + new_dimension
  370. : new_dimension)
  371. : current_index.column();
  372. auto new_index = index(new_row, new_column, operation.target_parent);
  373. auto it = m_persistent_handles.find(current_index);
  374. auto handle = move(it->value);
  375. handle->m_index = new_index;
  376. m_persistent_handles.remove(it);
  377. m_persistent_handles.set(move(new_index), move(handle));
  378. };
  379. for (auto current_index : to_move) {
  380. int dimension = is_row ? current_index->row() : current_index->column();
  381. int target_offset = dimension - operation.first;
  382. int new_dimension = operation.target + target_offset;
  383. replace_handle(*current_index, new_dimension, false);
  384. }
  385. if (move_within) {
  386. for (auto current_index : to_shift_down) {
  387. int dimension = is_row ? current_index->row() : current_index->column();
  388. int target_offset = moving_down ? dimension - (operation.last + 1) : dimension - work_area_start + count;
  389. int new_dimension = work_area_start + target_offset;
  390. replace_handle(*current_index, new_dimension, false);
  391. }
  392. } else {
  393. for (auto current_index : to_shift_down) {
  394. replace_handle(*current_index, count, true);
  395. }
  396. for (auto current_index : to_shift_up) {
  397. replace_handle(*current_index, count, true);
  398. }
  399. }
  400. }
  401. }