SelectionProxyModel.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Source/Editor/SelectionProxyModel.h>
  9. #include <QtCore/QSortFilterProxyModel>
  10. namespace EMotionFX
  11. {
  12. SelectionProxyModel::SelectionProxyModel(QItemSelectionModel* sourceSelectionModel, QAbstractProxyModel* proxyModel, QObject* parent)
  13. : QItemSelectionModel(proxyModel, parent)
  14. , m_sourceSelectionModel(sourceSelectionModel)
  15. {
  16. connect(sourceSelectionModel, &QItemSelectionModel::selectionChanged, this, &SelectionProxyModel::OnSourceSelectionChanged);
  17. connect(sourceSelectionModel, &QItemSelectionModel::currentChanged, this, &SelectionProxyModel::OnSourceSelectionCurrentChanged);
  18. connect(proxyModel, &QAbstractItemModel::rowsInserted, this, &SelectionProxyModel::OnProxyModelRowsInserted);
  19. connect(this, &QItemSelectionModel::selectionChanged, this, &SelectionProxyModel::OnProxySelectionChanged);
  20. // Find the chain of proxy models
  21. QAbstractProxyModel* sourceProxyModel = proxyModel;
  22. while (sourceProxyModel)
  23. {
  24. m_proxyModels.emplace_back(sourceProxyModel);
  25. sourceProxyModel = qobject_cast<QAbstractProxyModel*>(sourceProxyModel->sourceModel());
  26. }
  27. const QItemSelection currentSelection = mapFromSource(m_sourceSelectionModel->selection());
  28. QItemSelectionModel::select(currentSelection, QItemSelectionModel::ClearAndSelect);
  29. const QModelIndex currentModelIndex = mapFromSource(m_sourceSelectionModel->currentIndex());
  30. QItemSelectionModel::setCurrentIndex(currentModelIndex, QItemSelectionModel::ClearAndSelect);
  31. }
  32. void SelectionProxyModel::setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
  33. {
  34. const QModelIndex sourcetIndex = mapToSource(index);
  35. m_sourceSelectionModel->setCurrentIndex(sourcetIndex, command);
  36. }
  37. void SelectionProxyModel::select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
  38. {
  39. const QModelIndex sourceIndex = mapToSource(index);
  40. m_sourceSelectionModel->select(sourceIndex, command);
  41. }
  42. void SelectionProxyModel::select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command)
  43. {
  44. const QItemSelection sourceSelection = mapToSource(selection);
  45. m_sourceSelectionModel->select(sourceSelection, command);
  46. }
  47. void SelectionProxyModel::clear()
  48. {
  49. m_sourceSelectionModel->clear();
  50. }
  51. void SelectionProxyModel::reset()
  52. {
  53. m_sourceSelectionModel->reset();
  54. }
  55. void SelectionProxyModel::clearCurrentIndex()
  56. {
  57. m_sourceSelectionModel->clearCurrentIndex();
  58. }
  59. void SelectionProxyModel::OnSourceSelectionCurrentChanged(const QModelIndex& current, const QModelIndex& previous)
  60. {
  61. AZ_UNUSED(previous);
  62. QModelIndex targetCurrent = mapFromSource(current);
  63. QItemSelectionModel::setCurrentIndex(targetCurrent, QItemSelectionModel::NoUpdate);
  64. }
  65. void SelectionProxyModel::OnSourceSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected)
  66. {
  67. QItemSelection targetSelected = mapFromSource(selected);
  68. QItemSelection targetDeselected = mapFromSource(deselected);
  69. QItemSelectionModel::select(targetSelected, QItemSelectionModel::Select);
  70. QItemSelectionModel::select(targetDeselected, QItemSelectionModel::Deselect);
  71. }
  72. void SelectionProxyModel::OnProxySelectionChanged(const QItemSelection& selected, const QItemSelection& deselected)
  73. {
  74. const QItemSelection sourceSelected = mapToSource(selected);
  75. const QItemSelection sourceDeselected = mapToSource(deselected);
  76. // Disconnect from the selectionChanged signal in the source model to
  77. // prevent recursion
  78. // We could also block the signals of the source selection model, but
  79. // someone else may be connected to its signals and expect to get an
  80. // update
  81. disconnect(m_sourceSelectionModel, &QItemSelectionModel::selectionChanged, this, &SelectionProxyModel::OnSourceSelectionChanged);
  82. if (selected.empty() && deselected.empty())
  83. {
  84. // Force the signal to fire
  85. emit m_sourceSelectionModel->selectionChanged({}, {});
  86. }
  87. else
  88. {
  89. m_sourceSelectionModel->select(sourceSelected, QItemSelectionModel::Select);
  90. m_sourceSelectionModel->select(sourceDeselected, QItemSelectionModel::Deselect);
  91. }
  92. connect(m_sourceSelectionModel, &QItemSelectionModel::selectionChanged, this, &SelectionProxyModel::OnSourceSelectionChanged);
  93. }
  94. void SelectionProxyModel::OnProxyModelRowsInserted([[maybe_unused]] const QModelIndex& parent, [[maybe_unused]] int first, [[maybe_unused]] int last)
  95. {
  96. QModelIndex sourceIndex = m_sourceSelectionModel->currentIndex();
  97. QModelIndex targetIndex = mapFromSource(sourceIndex);
  98. if (targetIndex != currentIndex())
  99. {
  100. QItemSelectionModel::setCurrentIndex(targetIndex, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
  101. }
  102. QItemSelection sourceSelection = m_sourceSelectionModel->selection();
  103. QItemSelection targetSelection = mapFromSource(sourceSelection);
  104. if (targetSelection != selection())
  105. {
  106. QItemSelectionModel::select(targetSelection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
  107. }
  108. }
  109. QModelIndex SelectionProxyModel::mapFromSource(const QModelIndex& sourceIndex)
  110. {
  111. QModelIndex mappedIndex = sourceIndex;
  112. for (AZStd::vector<QAbstractProxyModel*>::const_reverse_iterator itProxy = m_proxyModels.rbegin(); itProxy != m_proxyModels.rend(); ++itProxy)
  113. {
  114. mappedIndex = (*itProxy)->mapFromSource(mappedIndex);
  115. }
  116. return mappedIndex;
  117. }
  118. QItemSelection SelectionProxyModel::mapFromSource(const QItemSelection& sourceSelection)
  119. {
  120. QItemSelection mappedSelection = sourceSelection;
  121. for (AZStd::vector<QAbstractProxyModel*>::const_reverse_iterator itProxy = m_proxyModels.rbegin(); itProxy != m_proxyModels.rend(); ++itProxy)
  122. {
  123. mappedSelection = (*itProxy)->mapSelectionFromSource(mappedSelection);
  124. }
  125. return mappedSelection;
  126. }
  127. QModelIndex SelectionProxyModel::mapToSource(const QModelIndex& targetIndex)
  128. {
  129. QModelIndex mappedIndex = targetIndex;
  130. for (AZStd::vector<QAbstractProxyModel*>::const_iterator itProxy = m_proxyModels.begin(); itProxy != m_proxyModels.end(); ++itProxy)
  131. {
  132. mappedIndex = (*itProxy)->mapToSource(mappedIndex);
  133. }
  134. return mappedIndex;
  135. }
  136. QItemSelection SelectionProxyModel::mapToSource(const QItemSelection& targetSelection)
  137. {
  138. QItemSelection mappedSelection = targetSelection;
  139. for (AZStd::vector<QAbstractProxyModel*>::const_iterator itProxy = m_proxyModels.begin(); itProxy != m_proxyModels.end(); ++itProxy)
  140. {
  141. mappedSelection = (*itProxy)->mapSelectionToSource(mappedSelection);
  142. }
  143. return mappedSelection;
  144. }
  145. } // namespace EMotionFX