Model.cpp 16 KB

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