17#include <QStandardItemModel>
21QAbstractItemView::EditTriggers getEditTriggers() {
23 QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed | QAbstractItemView::AnyKeyPressed;
31 : QTreeView(parent), m_notifyee(nullptr), m_mainModel(0, columnHeadings.size(), this),
32 m_adaptedMainModel(m_mainModel, emptyCellStyle), m_filteredModel(
RowLocationAdapter(m_mainModel), this),
33 m_lastEdited(QModelIndex()) {
36 setSelectionMode(QAbstractItemView::ExtendedSelection);
37 setEditTriggers(getEditTriggers());
39 setContextMenuPolicy(Qt::ActionsContextMenu);
46 QTreeView::commitData(editor);
49 if (cellText != cellTextBefore) {
54 editAt(current_filtered_index);
59 QTreeView::selectionChanged(selected, deselected);
85 return QTreeView::edit(
index, trigger, event);
92 std::sort(selected.begin(), selected.end());
94 auto selectedRows = std::vector<Row>();
95 selectedRows.reserve(selected.size());
97 std::transform(selected.cbegin(), selected.cend(), std::back_inserter(selectedRows),
98 [&](
RowLocation const &location) ->
Row { return Row(location, cellsAt(location)); });
101 return extractSubtrees(selectedRows);
112 if (selectionModel()->isSelected(childIndex))
123 if (!selectionModel()->isSelected(childIndex))
124 descendantsList.append(childIndex);
138 auto implicitlySelected = QModelIndexList();
139 for (
auto &&row : selectedRows) {
140 if (isExpanded(row)) {
147 return implicitlySelected;
151 auto selection = selectionModel()->selectedRows();
154 std::vector<RowLocation> rowSelection;
155 rowSelection.reserve(selection.size());
156 std::transform(selection.begin(), selection.end(), std::back_inserter(rowSelection),
158 auto indexForMainModel = mapToMainModel(fromFilteredModel(index));
159 return rowLocation().atIndex(indexForMainModel);
179 std::sort(rowsToRemove.begin(), rowsToRemove.end());
180 for (
auto rowIt = rowsToRemove.crbegin(); rowIt < rowsToRemove.crend(); ++rowIt)
195 closePersistentEditor(cellIndex.
untyped());
214 std::vector<Cell>
const &cells) {
217 closeEditorIfCellIsUneditable(cellIndex, cells[column]);
228 auto const insertionParent = rootToRemove.
parent();
237 auto newRootIndexToRemove =
below(originalRootIndexToRemove.untyped());
243 build(parent,
index, subtree);
247 for (
auto &&subtree : subtrees)
257 assertOrThrow(replacementPoints.size() > 0,
"replaceRows: Passed an empty list of replacement points."
258 "At least one replacement point is required.");
259 auto replacementPoint = replacementPoints.cbegin();
260 auto replacement = replacements.cbegin();
262 for (; replacementPoint != replacementPoints.cend() && replacement != replacements.cend();
263 ++replacementPoint, ++replacement) {
267 if (replacementPoints.size() > replacements.size())
268 for (; replacementPoint != replacementPoints.cend(); ++replacementPoint)
270 else if (replacementPoints.size() < replacements.size())
271 for (; replacement != replacements.cend(); ++replacement)
276 m_mainModel.setHorizontalHeaderLabels(columnHeadings);
278 for (
auto i = 0; i < model()->columnCount(); ++i)
279 resizeColumnToContents(i);
297 return index.parent();
302 auto parentIndex =
index.parent();
303 return m_mainModel.rowCount(parentIndex.untyped()) == 1;
316 assertOrThrow(indexToRemove.isValid(),
"removeRowAt: Attempted to remove the invisible root item.");
327 if (rowIndexToSwitchTo.isValid()) {
328 setCurrentIndex(rowIndexToSwitchTo);
332 setCurrentIndex(rowIndexToSwitchTo);
340 auto firstChild = std::vector<int>{0};
355 "Attempted to add row with more cells than columns. Increase "
356 "the number of columns by increasing the number of headings.");
377 QTreeView::clearSelection();
378 setCurrentIndex(
index.untyped());
391 while (expandAt.isValid()) {
392 setExpanded(expandAt,
true);
402std::pair<QModelIndexForFilteredModel, bool>
431 auto current = currentIndex();
432 setCurrentIndex(QModelIndex());
433 setCurrentIndex(current);
436 auto index = cell.first;
437 auto isNew = cell.second;
458 switch (event->key()) {
460 if (event->modifiers() & Qt::ControlModifier) {
465 case Qt::Key_Enter: {
466 if (event->modifiers() & Qt::ShiftModifier) {
477 if (event->modifiers() & Qt::ControlModifier) {
483 if (event->modifiers() & Qt::ControlModifier) {
489 if (event->modifiers() & Qt::ControlModifier) {
495 QTreeView::keyPressEvent(event);
500 return ::MantidQt::MantidWidgets::Batch::fromMainModel(mainModelIndex,
m_mainModel);
504 return ::MantidQt::MantidWidgets::Batch::fromFilteredModel(filteredModelIndex,
m_filteredModel);
511 while (!result.first && result.second.isValid() && !
isEditable(result.second))
518 while (currentIndex.isValid() && !
isEditable(currentIndex))
524 if (cursorAction == QAbstractItemView::MoveNext)
526 else if (cursorAction == QAbstractItemView::MovePrevious)
529 return QTreeView::moveCursor(cursorAction, modifiers);
533 auto shouldMakeNewRowBelow = result.first;
534 if (shouldMakeNewRowBelow) {
556 if (maybeIndexOfNewRow.has_value()) {
559 return QModelIndex();
562 return result.second;
void assertOrThrow(bool condition, std::string const &message)
See the developer documentation for Batch Widget at developer.mantidproject.org/BatchWidget/index....
std::map< DeltaEMode::Type, std::string > index