1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
5 #include "CommandHistory.h"
6 #include "RecursionLoopGuard.h"
7 #include "IUndoManager.h"
10 #include <QAdvancedTreeView.h>
11 #include <EditorStyleHelper.h>
12 #include "IEditorClassFactory.h"
14 REGISTER_HIDDEN_VIEWPANE_FACTORY(CHistoryPanel
, "Undo History", "Tools", true)
16 namespace Private_CommandHistory
18 class QHistoryModel
: public QAbstractTableModel
21 QHistoryModel(QWidget
* parent
, IUndoManager
* pCommandManager
);
23 int rowCount(const QModelIndex
& parent
= QModelIndex()) const;
24 int columnCount(const QModelIndex
& parent
= QModelIndex()) const;
25 QVariant
data(const QModelIndex
& index
, int role
= Qt::DisplayRole
) const;
26 QVariant
headerData(int section
, Qt::Orientation orientation
, int role
) const;
27 void OnCommandBufferChange(CUndoStep
* pCommand
, IUndoManager::ECommandChangeType change
, int index
);
28 void FillHistoryFromCommandBuffer();
30 CCrySignal
<void(CUndoStep
*, IUndoManager::ECommandChangeType
, int)> signalBufferChanged
;
33 IUndoManager
* m_pCommandManager
;
34 std::vector
<CUndoStep
*> m_commands
;
38 int getCurrentIndex() const
40 if (m_pCommandManager
)
41 return m_pCommandManager
->GetUndoStackLen();
46 QHistoryModel::QHistoryModel(QWidget
* parent
, IUndoManager
* pCommandManager
)
47 : QAbstractTableModel(parent
)
48 , m_pCommandManager(pCommandManager
)
50 FillHistoryFromCommandBuffer();
51 if (m_pCommandManager
)
52 m_pCommandManager
->signalBufferChanged
.Connect(this, &QHistoryModel::OnCommandBufferChange
);
54 m_font
= QFont(parent
->font());
58 QHistoryModel::~QHistoryModel()
60 if (m_pCommandManager
)
61 m_pCommandManager
->signalBufferChanged
.DisconnectObject(this);
64 void QHistoryModel::FillHistoryFromCommandBuffer()
68 if (m_pCommandManager
)
70 for (CUndoStep
* pCommand
: m_pCommandManager
->GetUndoStack())
71 m_commands
.push_back(pCommand
);
72 for (CUndoStep
* pCommand
: m_pCommandManager
->GetRedoStack())
73 m_commands
.push_back(pCommand
);
76 dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
79 void QHistoryModel::OnCommandBufferChange(CUndoStep
* pCommand
, IUndoManager::ECommandChangeType changeType
, int changedIndex
)
81 if (!m_pCommandManager
)
84 if (IUndoManager::eCommandChangeType_Move
& changeType
)
86 dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
89 if (IUndoManager::eCommandChangeType_Insert
& changeType
)
91 beginInsertRows(QModelIndex(), changedIndex
+ 1, changedIndex
+ 1);
92 m_commands
.insert(m_commands
.begin() + changedIndex
, pCommand
);
96 if (IUndoManager::eCommandChangeType_Remove
& changeType
)
98 if (-1 != changedIndex
&& 0 != m_commands
.size())
102 beginRemoveRows(QModelIndex(), changedIndex
+ 1, changedIndex
+ 1);
103 m_commands
.erase(m_commands
.begin() + changedIndex
);
106 else if (IUndoManager::eCommandChangeType_Undo
& changeType
)
108 beginRemoveRows(QModelIndex(), 1, changedIndex
);
109 m_commands
.erase(m_commands
.begin(), m_commands
.begin() + changedIndex
);
112 else if (IUndoManager::eCommandChangeType_Redo
& changeType
)
114 beginRemoveRows(QModelIndex(), rowCount() - (changedIndex
+ 1), rowCount() - 1);
115 m_commands
.erase(m_commands
.end() - changedIndex
, m_commands
.end());
121 signalBufferChanged(pCommand
, changeType
, changedIndex
);
124 int QHistoryModel::rowCount(const QModelIndex
& parent
) const
126 if (!parent
.isValid() && m_pCommandManager
)
127 return 1 + m_commands
.size();
131 int QHistoryModel::columnCount(const QModelIndex
& parent
) const
133 if (!parent
.isValid())
138 QVariant
QHistoryModel::data(const QModelIndex
& index
, int role
) const
140 int row
= index
.row();
141 int col
= index
.column();
145 case Qt::DisplayRole
:
148 return QString("Starting Point");
150 else if (m_commands
.size() >= row
&& m_pCommandManager
)
153 m_pCommandManager
->GetCommandName(m_commands
[row
- 1], name
);
154 return QString(name
.GetBuffer());
159 if (row
> getCurrentIndex())
162 font
.setItalic(true);
167 case Qt::TextColorRole
:
168 if (row
> getCurrentIndex())
170 QColor color
= GetStyleHelper()->disabledWindowTextColor();
178 QVariant
QHistoryModel::headerData(int section
, Qt::Orientation orientation
, int role
) const
180 if (orientation
== Qt::Horizontal
&& role
== Qt::DisplayRole
)
185 return QString("Commands");
192 class QHistoryView
: public QAdvancedTreeView
195 QHistoryView(IUndoManager
* pCommandManager
, QHistoryModel
* pModel
)
196 : m_pCommandManager(pCommandManager
)
197 , m_validating(false)
200 setSelectionMode(QAbstractItemView::SingleSelection
);
202 if (m_pCommandManager
&& pModel
)
204 pModel
->signalBufferChanged
.Connect(this, &QHistoryView::OnCommandBufferChange
);
213 void selectRow(int row
)
215 if (selectionModel() && model())
216 selectionModel()->select(model()->index(row
, 0), QItemSelectionModel::ClearAndSelect
);
219 void QHistoryView::OnCommandBufferChange(CUndoStep
* pCommand
, IUndoManager::ECommandChangeType changeType
, int index
)
221 RECURSION_GUARD(m_validating
);
223 if (IUndoManager::eCommandChangeType_Move
& changeType
)
225 selectRow(index
+ 1);
228 if (IUndoManager::eCommandChangeType_Insert
& changeType
)
230 selectRow(index
+ 1);
233 if (IUndoManager::eCommandChangeType_Remove
& changeType
)
237 if (m_pCommandManager
)
241 else if (IUndoManager::eCommandChangeType_Undo
& changeType
)
243 selectRow(model()->rowCount() - 1);
245 else if (IUndoManager::eCommandChangeType_Redo
& changeType
)
247 selectRow(model()->rowCount() - 1);
253 virtual void selectionChanged(const QItemSelection
& selected
, const QItemSelection
& deselected
) override
255 RECURSION_GUARD(m_validating
);
257 if (0 != selected
.size() && m_pCommandManager
)
259 int row
= selected
.front().top();
260 int count
= m_pCommandManager
->GetRedoStackLen() + m_pCommandManager
->GetUndoStackLen() + 1;
262 if (0 <= row
&& count
> row
)
264 int undoCount
= m_pCommandManager
->GetUndoStackLen();
265 int commandIndex
= row
- undoCount
;
267 if (commandIndex
> 0)
268 m_pCommandManager
->Redo(commandIndex
);
269 else if (commandIndex
< 0)
270 m_pCommandManager
->Undo(abs(commandIndex
));
274 __super::selectionChanged(selected
, deselected
);
279 IUndoManager
* m_pCommandManager
;
280 QHistoryModel
* m_pModel
;
284 CHistoryPanel::CHistoryPanel()
287 QVBoxLayout
* layout
= new QVBoxLayout();
288 layout
->setContentsMargins(1, 1, 1, 1);
291 IUndoManager
* pCommandManager
= GetIEditorImpl()->GetIUndoManager();
294 Private_CommandHistory::QHistoryModel
* pHistoryModel
= new Private_CommandHistory::QHistoryModel(this, pCommandManager
);
295 Private_CommandHistory::QHistoryView
* pHistoryList
= new Private_CommandHistory::QHistoryView(pCommandManager
, pHistoryModel
);
296 pHistoryList
->setModel(pHistoryModel
);
297 layout
->addWidget(pHistoryList
);
301 CHistoryPanel::~CHistoryPanel()