diff --git a/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h b/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h index d560eb2824a..8c914b50e45 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h +++ b/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h @@ -45,6 +45,7 @@ public: virtual void notifyModelNodesMoved(const QList &modelNodes) = 0; virtual void notifyIconsChanged() = 0; virtual void setFilter(bool showObjects) = 0; + virtual void setOrder(bool reverse) = 0; virtual void resetModel() = 0; }; diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp index 3312a16adb8..a2419a351f3 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp @@ -274,7 +274,7 @@ void static appendForcedNodes(const NodeListProperty &property, QList } } -QList filteredList(const NodeListProperty &property, bool filter) +QList filteredList(const NodeListProperty &property, bool filter, bool reverseOrder) { QList list; @@ -288,6 +288,9 @@ QList filteredList(const NodeListProperty &property, bool filter) appendForcedNodes(property, list); + if (reverseOrder) + std::reverse(list.begin(), list.end()); + return list; } @@ -307,7 +310,9 @@ QModelIndex NavigatorTreeModel::index(int row, int column, ModelNode modelNode; if (parentModelNode.defaultNodeListProperty().isValid()) - modelNode = filteredList(parentModelNode.defaultNodeListProperty(), m_showOnlyVisibleItems).at(row); + modelNode = filteredList(parentModelNode.defaultNodeListProperty(), + m_showOnlyVisibleItems, + m_reverseItemOrder).at(row); if (!modelNode.isValid()) return QModelIndex(); @@ -338,7 +343,9 @@ QModelIndex NavigatorTreeModel::parent(const QModelIndex &index) const int row = 0; if (!parentModelNode.isRootNode() && parentModelNode.parentProperty().isNodeListProperty()) - row = filteredList(parentModelNode.parentProperty().toNodeListProperty(), m_showOnlyVisibleItems).indexOf(parentModelNode); + row = filteredList(parentModelNode.parentProperty().toNodeListProperty(), + m_showOnlyVisibleItems, + m_reverseItemOrder).indexOf(parentModelNode); return createIndexFromModelNode(row, 0, parentModelNode); } @@ -358,7 +365,9 @@ int NavigatorTreeModel::rowCount(const QModelIndex &parent) const int rows = 0; if (modelNode.defaultNodeListProperty().isValid()) - rows = filteredList(modelNode.defaultNodeListProperty(), m_showOnlyVisibleItems).count(); + rows = filteredList(modelNode.defaultNodeListProperty(), + m_showOnlyVisibleItems, + m_reverseItemOrder).count(); return rows; } @@ -450,6 +459,9 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData, if (action == Qt::IgnoreAction) return true; + if (m_reverseItemOrder) + rowNumber = rowCount(dropModelIndex) - rowNumber; + if (dropModelIndex.model() == this) { if (mimeData->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) { handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex); @@ -832,6 +844,12 @@ void NavigatorTreeModel::setFilter(bool showOnlyVisibleItems) resetModel(); } +void NavigatorTreeModel::setOrder(bool reverseItemOrder) +{ + m_reverseItemOrder = reverseItemOrder; + resetModel(); +} + void NavigatorTreeModel::resetModel() { beginResetModel(); diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h index 6ab81960ca7..67c59b1aab6 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h @@ -91,6 +91,7 @@ public: void notifyModelNodesMoved(const QList &modelNodes) override; void notifyIconsChanged() override; void setFilter(bool showOnlyVisibleItems) override; + void setOrder(bool reverseItemOrder) override; void resetModel() override; void updateToolTipImage(const ModelNode &node, const QImage &image); @@ -109,6 +110,7 @@ private: QPointer m_view; mutable QHash m_nodeIndexHash; bool m_showOnlyVisibleItems = true; + bool m_reverseItemOrder = false; DesignerActionManager *m_actionManager = nullptr; }; diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp index 1cc16d73f40..90284fec0a6 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp @@ -69,6 +69,36 @@ static inline void setScenePos(const QmlDesigner::ModelNode &modelNode,const QPo } } +static inline void moveNodesUp(const QList &nodes) +{ + for (const auto &node : nodes) { + if (!node.isRootNode() && node.parentProperty().isNodeListProperty()) { + int oldIndex = node.parentProperty().indexOf(node); + int index = oldIndex; + index--; + if (index < 0) + index = node.parentProperty().count() - 1; //wrap around + if (oldIndex != index) + node.parentProperty().toNodeListProperty().slide(oldIndex, index); + } + } +} + +static inline void moveNodesDown(const QList &nodes) +{ + for (const auto &node : nodes) { + if (!node.isRootNode() && node.parentProperty().isNodeListProperty()) { + int oldIndex = node.parentProperty().indexOf(node); + int index = oldIndex; + index++; + if (index >= node.parentProperty().count()) + index = 0; //wrap around + if (oldIndex != index) + node.parentProperty().toNodeListProperty().slide(oldIndex, index); + } + } +} + namespace QmlDesigner { NavigatorView::NavigatorView(QObject* parent) : @@ -119,6 +149,9 @@ void NavigatorView::modelAttached(Model *model) m_currentModelInterface->setFilter( DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS).toBool()); + m_currentModelInterface->setOrder( + DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_REVERSE_ITEM_ORDER).toBool()); + // Expand everything to begin with to ensure model node to index cache is populated treeView->expandAll(); @@ -307,7 +340,7 @@ void NavigatorView::auxiliaryDataChanged(const ModelNode &modelNode, void NavigatorView::instanceErrorChanged(const QVector &errorNodeList) { - foreach (const ModelNode &modelNode, errorNodeList) + for (const ModelNode &modelNode : errorNodeList) m_currentModelInterface->notifyDataChanged(modelNode); } @@ -348,7 +381,7 @@ void NavigatorView::leftButtonClicked() bool blocked = blockSelectionChangedSignal(true); - foreach (const ModelNode &node, selectedModelNodes()) { + for (const ModelNode &node : selectedModelNodes()) { if (!node.isRootNode() && !node.parentProperty().parentModelNode().isRootNode()) { if (QmlItemNode::isValidQmlItemNode(node)) { QPointF scenePos = QmlItemNode(node).instanceScenePosition(); @@ -371,11 +404,23 @@ void NavigatorView::rightButtonClicked() return; //Semantics are unclear for multi selection. bool blocked = blockSelectionChangedSignal(true); - foreach (const ModelNode &node, selectedModelNodes()) { + bool reverse = DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_REVERSE_ITEM_ORDER).toBool(); + + for (const ModelNode &node : selectedModelNodes()) { if (!node.isRootNode() && node.parentProperty().isNodeListProperty() && node.parentProperty().count() > 1) { int index = node.parentProperty().indexOf(node); - index--; - if (index >= 0) { //for the first node the semantics are not clear enough. Wrapping would be irritating. + + bool indexOk = false; + + if (reverse) { + index++; + indexOk = (index < node.parentProperty().count()); + } else { + index--; + indexOk = (index >= 0); + } + + if (indexOk) { //for the first node the semantics are not clear enough. Wrapping would be irritating. ModelNode newParent = node.parentProperty().toNodeListProperty().at(index); if (QmlItemNode::isValidQmlItemNode(node) @@ -399,17 +444,13 @@ void NavigatorView::rightButtonClicked() void NavigatorView::upButtonClicked() { bool blocked = blockSelectionChangedSignal(true); - foreach (const ModelNode &node, selectedModelNodes()) { - if (!node.isRootNode() && node.parentProperty().isNodeListProperty()) { - int oldIndex = node.parentProperty().indexOf(node); - int index = oldIndex; - index--; - if (index < 0) - index = node.parentProperty().count() - 1; //wrap around - if (oldIndex != index) - node.parentProperty().toNodeListProperty().slide(oldIndex, index); - } - } + bool reverse = DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_REVERSE_ITEM_ORDER).toBool(); + + if (reverse) + moveNodesDown(selectedModelNodes()); + else + moveNodesUp(selectedModelNodes()); + updateItemSelection(); blockSelectionChangedSignal(blocked); } @@ -417,17 +458,13 @@ void NavigatorView::upButtonClicked() void NavigatorView::downButtonClicked() { bool blocked = blockSelectionChangedSignal(true); - foreach (const ModelNode &node, selectedModelNodes()) { - if (!node.isRootNode() && node.parentProperty().isNodeListProperty()) { - int oldIndex = node.parentProperty().indexOf(node); - int index = oldIndex; - index++; - if (index >= node.parentProperty().count()) - index = 0; //wrap around - if (oldIndex != index) - node.parentProperty().toNodeListProperty().slide(oldIndex, index); - } - } + bool reverse = DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_REVERSE_ITEM_ORDER).toBool(); + + if (reverse) + moveNodesUp(selectedModelNodes()); + else + moveNodesDown(selectedModelNodes()); + updateItemSelection(); blockSelectionChangedSignal(blocked); } @@ -439,6 +476,13 @@ void NavigatorView::filterToggled(bool flag) DesignerSettings::setValue(DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, flag); } +void NavigatorView::reverseOrderToggled(bool flag) +{ + m_currentModelInterface->setOrder(flag); + treeWidget()->expandAll(); + DesignerSettings::setValue(DesignerSettingsKey::NAVIGATOR_REVERSE_ITEM_ORDER, flag); +} + void NavigatorView::changeSelection(const QItemSelection & /*newSelection*/, const QItemSelection &/*deselected*/) { if (m_blockSelectionChangedSignal) @@ -470,7 +514,7 @@ void NavigatorView::updateItemSelection() return; QItemSelection itemSelection; - foreach (const ModelNode &node, selectedModelNodes()) { + for (const ModelNode &node : selectedModelNodes()) { const QModelIndex index = indexForModelNode(node); if (index.isValid()) { @@ -500,7 +544,7 @@ void NavigatorView::updateItemSelection() treeWidget()->scrollTo(indexForModelNode(selectedModelNodes().constFirst())); // make sure selected nodes are visible - foreach (const QModelIndex &selectedIndex, itemSelection.indexes()) { + for (const QModelIndex &selectedIndex : itemSelection.indexes()) { if (selectedIndex.column() == 0) expandAncestors(selectedIndex); } @@ -566,6 +610,7 @@ void NavigatorView::setupWidget() connect(m_widget.data(), &NavigatorWidget::downButtonClicked, this, &NavigatorView::downButtonClicked); connect(m_widget.data(), &NavigatorWidget::upButtonClicked, this, &NavigatorView::upButtonClicked); connect(m_widget.data(), &NavigatorWidget::filterToggled, this, &NavigatorView::filterToggled); + connect(m_widget.data(), &NavigatorWidget::reverseOrderToggled, this, &NavigatorView::reverseOrderToggled); #ifndef QMLDESIGNER_TEST auto idDelegate = new NameItemDelegate(this); diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.h b/src/plugins/qmldesigner/components/navigator/navigatorview.h index 49605e145c3..b237cb5ca6c 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorview.h +++ b/src/plugins/qmldesigner/components/navigator/navigatorview.h @@ -111,6 +111,7 @@ private: void upButtonClicked(); void downButtonClicked(); void filterToggled(bool); + void reverseOrderToggled(bool); protected: //functions QTreeView *treeWidget() const; diff --git a/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp b/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp index 5c326f65faf..3813881f550 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp @@ -127,14 +127,24 @@ QList NavigatorWidget::createToolBarWidgets() filter->setPopupMode(QToolButton::InstantPopup); filter->setProperty("noArrow", true); auto filterMenu = new QMenu(filter); - auto objectAction = new QAction(tr("Show only visible items."), nullptr); - objectAction->setCheckable(true); + auto filterAction = new QAction(tr("Show only visible items."), nullptr); + filterAction->setCheckable(true); bool filterFlag = DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS).toBool(); - objectAction->setChecked(filterFlag); + filterAction->setChecked(filterFlag); + + connect(filterAction, &QAction::toggled, this, &NavigatorWidget::filterToggled); + filterMenu->addAction(filterAction); + + auto reverseAction = new QAction(tr("Reverse item order."), nullptr); + reverseAction->setCheckable(true); + + bool reverseFlag = DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_REVERSE_ITEM_ORDER).toBool(); + reverseAction->setChecked(reverseFlag); + + connect(reverseAction, &QAction::toggled, this, &NavigatorWidget::reverseOrderToggled); + filterMenu->addAction(reverseAction); - connect(objectAction, &QAction::toggled, this, &NavigatorWidget::filterToggled); - filterMenu->addAction(objectAction); filter->setMenu(filterMenu); buttons.append(filter); diff --git a/src/plugins/qmldesigner/components/navigator/navigatorwidget.h b/src/plugins/qmldesigner/components/navigator/navigatorwidget.h index b6240aa3bb9..9c1c962c435 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorwidget.h +++ b/src/plugins/qmldesigner/components/navigator/navigatorwidget.h @@ -61,6 +61,7 @@ signals: void upButtonClicked(); void downButtonClicked(); void filterToggled(bool); + void reverseOrderToggled(bool); private: // functions NavigatorView *navigatorView() const; diff --git a/src/plugins/qmldesigner/designersettings.cpp b/src/plugins/qmldesigner/designersettings.cpp index 540d0746ce4..8762667fdaf 100644 --- a/src/plugins/qmldesigner/designersettings.cpp +++ b/src/plugins/qmldesigner/designersettings.cpp @@ -74,6 +74,7 @@ void DesignerSettings::fromSettings(QSettings *settings) restoreValue(settings, DesignerSettingsKey::IGNORE_DEVICE_PIXEL_RATIO, false); restoreValue(settings, DesignerSettingsKey::STATESEDITOR_EXPANDED, true); restoreValue(settings, DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, true); + restoreValue(settings, DesignerSettingsKey::NAVIGATOR_REVERSE_ITEM_ORDER, false); restoreValue(settings, DesignerSettingsKey::STANDALONE_MODE, false); restoreValue(settings, DesignerSettingsKey::ENABLE_TIMELINEVIEW, #if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0)) diff --git a/src/plugins/qmldesigner/designersettings.h b/src/plugins/qmldesigner/designersettings.h index 3334c3a693d..7667b784824 100644 --- a/src/plugins/qmldesigner/designersettings.h +++ b/src/plugins/qmldesigner/designersettings.h @@ -62,6 +62,7 @@ const char DEBUG_PUPPET[] = "DebugPuppet"; const char FORWARD_PUPPET_OUTPUT[] = "ForwardPuppetOutput"; const char STATESEDITOR_EXPANDED[] = "StatesEditorExpanded"; const char NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS[] = "NavigatorShowOnlyVisibleItems"; +const char NAVIGATOR_REVERSE_ITEM_ORDER[] = "NavigatorReverseItemOrder"; const char REFORMAT_UI_QML_FILES[] = "ReformatUiQmlFiles"; /* These settings are not exposed in ui. */ const char IGNORE_DEVICE_PIXEL_RATIO[] = "IgnoreDevicePixelRaio"; /* The settings can be used to turn off the feature, if there are serious issues */ const char STANDALONE_MODE[] = "StandAloneMode";