QmlDesigner: Add reverse item order in navigator

Extend drag and drop, move and reparenting buttons to take into account
reverse item option.

Task-number: QDS-2773
Change-Id: I755e233511567c12d171245efbdca4044e896ba2
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Henning Gruendl
2020-09-17 14:44:21 +02:00
committed by Henning Gründl
parent 3888c33404
commit 485c3c25ac
9 changed files with 118 additions and 38 deletions

View File

@@ -45,6 +45,7 @@ public:
virtual void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) = 0; virtual void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) = 0;
virtual void notifyIconsChanged() = 0; virtual void notifyIconsChanged() = 0;
virtual void setFilter(bool showObjects) = 0; virtual void setFilter(bool showObjects) = 0;
virtual void setOrder(bool reverse) = 0;
virtual void resetModel() = 0; virtual void resetModel() = 0;
}; };

View File

@@ -274,7 +274,7 @@ void static appendForcedNodes(const NodeListProperty &property, QList<ModelNode>
} }
} }
QList<ModelNode> filteredList(const NodeListProperty &property, bool filter) QList<ModelNode> filteredList(const NodeListProperty &property, bool filter, bool reverseOrder)
{ {
QList<ModelNode> list; QList<ModelNode> list;
@@ -288,6 +288,9 @@ QList<ModelNode> filteredList(const NodeListProperty &property, bool filter)
appendForcedNodes(property, list); appendForcedNodes(property, list);
if (reverseOrder)
std::reverse(list.begin(), list.end());
return list; return list;
} }
@@ -307,7 +310,9 @@ QModelIndex NavigatorTreeModel::index(int row, int column,
ModelNode modelNode; ModelNode modelNode;
if (parentModelNode.defaultNodeListProperty().isValid()) 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()) if (!modelNode.isValid())
return QModelIndex(); return QModelIndex();
@@ -338,7 +343,9 @@ QModelIndex NavigatorTreeModel::parent(const QModelIndex &index) const
int row = 0; int row = 0;
if (!parentModelNode.isRootNode() && parentModelNode.parentProperty().isNodeListProperty()) 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); return createIndexFromModelNode(row, 0, parentModelNode);
} }
@@ -358,7 +365,9 @@ int NavigatorTreeModel::rowCount(const QModelIndex &parent) const
int rows = 0; int rows = 0;
if (modelNode.defaultNodeListProperty().isValid()) if (modelNode.defaultNodeListProperty().isValid())
rows = filteredList(modelNode.defaultNodeListProperty(), m_showOnlyVisibleItems).count(); rows = filteredList(modelNode.defaultNodeListProperty(),
m_showOnlyVisibleItems,
m_reverseItemOrder).count();
return rows; return rows;
} }
@@ -450,6 +459,9 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
if (action == Qt::IgnoreAction) if (action == Qt::IgnoreAction)
return true; return true;
if (m_reverseItemOrder)
rowNumber = rowCount(dropModelIndex) - rowNumber;
if (dropModelIndex.model() == this) { if (dropModelIndex.model() == this) {
if (mimeData->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) { if (mimeData->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex); handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex);
@@ -832,6 +844,12 @@ void NavigatorTreeModel::setFilter(bool showOnlyVisibleItems)
resetModel(); resetModel();
} }
void NavigatorTreeModel::setOrder(bool reverseItemOrder)
{
m_reverseItemOrder = reverseItemOrder;
resetModel();
}
void NavigatorTreeModel::resetModel() void NavigatorTreeModel::resetModel()
{ {
beginResetModel(); beginResetModel();

View File

@@ -91,6 +91,7 @@ public:
void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) override; void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) override;
void notifyIconsChanged() override; void notifyIconsChanged() override;
void setFilter(bool showOnlyVisibleItems) override; void setFilter(bool showOnlyVisibleItems) override;
void setOrder(bool reverseItemOrder) override;
void resetModel() override; void resetModel() override;
void updateToolTipImage(const ModelNode &node, const QImage &image); void updateToolTipImage(const ModelNode &node, const QImage &image);
@@ -109,6 +110,7 @@ private:
QPointer<NavigatorView> m_view; QPointer<NavigatorView> m_view;
mutable QHash<ModelNode, QModelIndex> m_nodeIndexHash; mutable QHash<ModelNode, QModelIndex> m_nodeIndexHash;
bool m_showOnlyVisibleItems = true; bool m_showOnlyVisibleItems = true;
bool m_reverseItemOrder = false;
DesignerActionManager *m_actionManager = nullptr; DesignerActionManager *m_actionManager = nullptr;
}; };

View File

@@ -69,6 +69,36 @@ static inline void setScenePos(const QmlDesigner::ModelNode &modelNode,const QPo
} }
} }
static inline void moveNodesUp(const QList<QmlDesigner::ModelNode> &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<QmlDesigner::ModelNode> &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 { namespace QmlDesigner {
NavigatorView::NavigatorView(QObject* parent) : NavigatorView::NavigatorView(QObject* parent) :
@@ -119,6 +149,9 @@ void NavigatorView::modelAttached(Model *model)
m_currentModelInterface->setFilter( m_currentModelInterface->setFilter(
DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS).toBool()); 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 // Expand everything to begin with to ensure model node to index cache is populated
treeView->expandAll(); treeView->expandAll();
@@ -307,7 +340,7 @@ void NavigatorView::auxiliaryDataChanged(const ModelNode &modelNode,
void NavigatorView::instanceErrorChanged(const QVector<ModelNode> &errorNodeList) void NavigatorView::instanceErrorChanged(const QVector<ModelNode> &errorNodeList)
{ {
foreach (const ModelNode &modelNode, errorNodeList) for (const ModelNode &modelNode : errorNodeList)
m_currentModelInterface->notifyDataChanged(modelNode); m_currentModelInterface->notifyDataChanged(modelNode);
} }
@@ -348,7 +381,7 @@ void NavigatorView::leftButtonClicked()
bool blocked = blockSelectionChangedSignal(true); bool blocked = blockSelectionChangedSignal(true);
foreach (const ModelNode &node, selectedModelNodes()) { for (const ModelNode &node : selectedModelNodes()) {
if (!node.isRootNode() && !node.parentProperty().parentModelNode().isRootNode()) { if (!node.isRootNode() && !node.parentProperty().parentModelNode().isRootNode()) {
if (QmlItemNode::isValidQmlItemNode(node)) { if (QmlItemNode::isValidQmlItemNode(node)) {
QPointF scenePos = QmlItemNode(node).instanceScenePosition(); QPointF scenePos = QmlItemNode(node).instanceScenePosition();
@@ -371,11 +404,23 @@ void NavigatorView::rightButtonClicked()
return; //Semantics are unclear for multi selection. return; //Semantics are unclear for multi selection.
bool blocked = blockSelectionChangedSignal(true); 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) { if (!node.isRootNode() && node.parentProperty().isNodeListProperty() && node.parentProperty().count() > 1) {
int index = node.parentProperty().indexOf(node); int index = node.parentProperty().indexOf(node);
bool indexOk = false;
if (reverse) {
index++;
indexOk = (index < node.parentProperty().count());
} else {
index--; index--;
if (index >= 0) { //for the first node the semantics are not clear enough. Wrapping would be irritating. 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); ModelNode newParent = node.parentProperty().toNodeListProperty().at(index);
if (QmlItemNode::isValidQmlItemNode(node) if (QmlItemNode::isValidQmlItemNode(node)
@@ -399,17 +444,13 @@ void NavigatorView::rightButtonClicked()
void NavigatorView::upButtonClicked() void NavigatorView::upButtonClicked()
{ {
bool blocked = blockSelectionChangedSignal(true); bool blocked = blockSelectionChangedSignal(true);
foreach (const ModelNode &node, selectedModelNodes()) { bool reverse = DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_REVERSE_ITEM_ORDER).toBool();
if (!node.isRootNode() && node.parentProperty().isNodeListProperty()) {
int oldIndex = node.parentProperty().indexOf(node); if (reverse)
int index = oldIndex; moveNodesDown(selectedModelNodes());
index--; else
if (index < 0) moveNodesUp(selectedModelNodes());
index = node.parentProperty().count() - 1; //wrap around
if (oldIndex != index)
node.parentProperty().toNodeListProperty().slide(oldIndex, index);
}
}
updateItemSelection(); updateItemSelection();
blockSelectionChangedSignal(blocked); blockSelectionChangedSignal(blocked);
} }
@@ -417,17 +458,13 @@ void NavigatorView::upButtonClicked()
void NavigatorView::downButtonClicked() void NavigatorView::downButtonClicked()
{ {
bool blocked = blockSelectionChangedSignal(true); bool blocked = blockSelectionChangedSignal(true);
foreach (const ModelNode &node, selectedModelNodes()) { bool reverse = DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_REVERSE_ITEM_ORDER).toBool();
if (!node.isRootNode() && node.parentProperty().isNodeListProperty()) {
int oldIndex = node.parentProperty().indexOf(node); if (reverse)
int index = oldIndex; moveNodesUp(selectedModelNodes());
index++; else
if (index >= node.parentProperty().count()) moveNodesDown(selectedModelNodes());
index = 0; //wrap around
if (oldIndex != index)
node.parentProperty().toNodeListProperty().slide(oldIndex, index);
}
}
updateItemSelection(); updateItemSelection();
blockSelectionChangedSignal(blocked); blockSelectionChangedSignal(blocked);
} }
@@ -439,6 +476,13 @@ void NavigatorView::filterToggled(bool flag)
DesignerSettings::setValue(DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, 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*/) void NavigatorView::changeSelection(const QItemSelection & /*newSelection*/, const QItemSelection &/*deselected*/)
{ {
if (m_blockSelectionChangedSignal) if (m_blockSelectionChangedSignal)
@@ -470,7 +514,7 @@ void NavigatorView::updateItemSelection()
return; return;
QItemSelection itemSelection; QItemSelection itemSelection;
foreach (const ModelNode &node, selectedModelNodes()) { for (const ModelNode &node : selectedModelNodes()) {
const QModelIndex index = indexForModelNode(node); const QModelIndex index = indexForModelNode(node);
if (index.isValid()) { if (index.isValid()) {
@@ -500,7 +544,7 @@ void NavigatorView::updateItemSelection()
treeWidget()->scrollTo(indexForModelNode(selectedModelNodes().constFirst())); treeWidget()->scrollTo(indexForModelNode(selectedModelNodes().constFirst()));
// make sure selected nodes are visible // make sure selected nodes are visible
foreach (const QModelIndex &selectedIndex, itemSelection.indexes()) { for (const QModelIndex &selectedIndex : itemSelection.indexes()) {
if (selectedIndex.column() == 0) if (selectedIndex.column() == 0)
expandAncestors(selectedIndex); expandAncestors(selectedIndex);
} }
@@ -566,6 +610,7 @@ void NavigatorView::setupWidget()
connect(m_widget.data(), &NavigatorWidget::downButtonClicked, this, &NavigatorView::downButtonClicked); connect(m_widget.data(), &NavigatorWidget::downButtonClicked, this, &NavigatorView::downButtonClicked);
connect(m_widget.data(), &NavigatorWidget::upButtonClicked, this, &NavigatorView::upButtonClicked); connect(m_widget.data(), &NavigatorWidget::upButtonClicked, this, &NavigatorView::upButtonClicked);
connect(m_widget.data(), &NavigatorWidget::filterToggled, this, &NavigatorView::filterToggled); connect(m_widget.data(), &NavigatorWidget::filterToggled, this, &NavigatorView::filterToggled);
connect(m_widget.data(), &NavigatorWidget::reverseOrderToggled, this, &NavigatorView::reverseOrderToggled);
#ifndef QMLDESIGNER_TEST #ifndef QMLDESIGNER_TEST
auto idDelegate = new NameItemDelegate(this); auto idDelegate = new NameItemDelegate(this);

View File

@@ -111,6 +111,7 @@ private:
void upButtonClicked(); void upButtonClicked();
void downButtonClicked(); void downButtonClicked();
void filterToggled(bool); void filterToggled(bool);
void reverseOrderToggled(bool);
protected: //functions protected: //functions
QTreeView *treeWidget() const; QTreeView *treeWidget() const;

View File

@@ -127,14 +127,24 @@ QList<QToolButton *> NavigatorWidget::createToolBarWidgets()
filter->setPopupMode(QToolButton::InstantPopup); filter->setPopupMode(QToolButton::InstantPopup);
filter->setProperty("noArrow", true); filter->setProperty("noArrow", true);
auto filterMenu = new QMenu(filter); auto filterMenu = new QMenu(filter);
auto objectAction = new QAction(tr("Show only visible items."), nullptr); auto filterAction = new QAction(tr("Show only visible items."), nullptr);
objectAction->setCheckable(true); filterAction->setCheckable(true);
bool filterFlag = DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS).toBool(); 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); filter->setMenu(filterMenu);
buttons.append(filter); buttons.append(filter);

View File

@@ -61,6 +61,7 @@ signals:
void upButtonClicked(); void upButtonClicked();
void downButtonClicked(); void downButtonClicked();
void filterToggled(bool); void filterToggled(bool);
void reverseOrderToggled(bool);
private: // functions private: // functions
NavigatorView *navigatorView() const; NavigatorView *navigatorView() const;

View File

@@ -74,6 +74,7 @@ void DesignerSettings::fromSettings(QSettings *settings)
restoreValue(settings, DesignerSettingsKey::IGNORE_DEVICE_PIXEL_RATIO, false); restoreValue(settings, DesignerSettingsKey::IGNORE_DEVICE_PIXEL_RATIO, false);
restoreValue(settings, DesignerSettingsKey::STATESEDITOR_EXPANDED, true); restoreValue(settings, DesignerSettingsKey::STATESEDITOR_EXPANDED, true);
restoreValue(settings, DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, 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::STANDALONE_MODE, false);
restoreValue(settings, DesignerSettingsKey::ENABLE_TIMELINEVIEW, restoreValue(settings, DesignerSettingsKey::ENABLE_TIMELINEVIEW,
#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0)) #if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))

View File

@@ -62,6 +62,7 @@ const char DEBUG_PUPPET[] = "DebugPuppet";
const char FORWARD_PUPPET_OUTPUT[] = "ForwardPuppetOutput"; const char FORWARD_PUPPET_OUTPUT[] = "ForwardPuppetOutput";
const char STATESEDITOR_EXPANDED[] = "StatesEditorExpanded"; const char STATESEDITOR_EXPANDED[] = "StatesEditorExpanded";
const char NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS[] = "NavigatorShowOnlyVisibleItems"; 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 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 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"; const char STANDALONE_MODE[] = "StandAloneMode";