From 3cc491f45a80fce397c9440397f1190968dcbadf Mon Sep 17 00:00:00 2001
From: Thomas Hartmann <Thomas.Hartmann@nokia.com>
Date: Thu, 28 Apr 2011 17:12:45 +0200
Subject: [PATCH] QmlDesigner.navigator: add tool buttons for
 sliding/reparenting

This patch adds for tool buttons that allow
sliding and reparenting in the navigator.
---
 .../components/navigator/arrowdown.png        | Bin 0 -> 390 bytes
 .../components/navigator/arrowleft.png        | Bin 0 -> 471 bytes
 .../components/navigator/arrowright.png       | Bin 0 -> 455 bytes
 .../components/navigator/arrowup.png          | Bin 0 -> 376 bytes
 .../components/navigator/navigator.pri        |   2 +
 .../components/navigator/navigator.qrc        |   8 ++
 .../components/navigator/navigatorview.cpp    |  79 +++++++++++++++++-
 .../components/navigator/navigatorview.h      |   7 +-
 .../components/navigator/navigatorwidget.cpp  |  58 ++++++++++++-
 .../components/navigator/navigatorwidget.h    |  14 +++-
 src/plugins/qmldesigner/designmodewidget.cpp  |  21 +++++
 11 files changed, 182 insertions(+), 7 deletions(-)
 create mode 100644 src/plugins/qmldesigner/components/navigator/arrowdown.png
 create mode 100644 src/plugins/qmldesigner/components/navigator/arrowleft.png
 create mode 100644 src/plugins/qmldesigner/components/navigator/arrowright.png
 create mode 100644 src/plugins/qmldesigner/components/navigator/arrowup.png
 create mode 100644 src/plugins/qmldesigner/components/navigator/navigator.qrc

diff --git a/src/plugins/qmldesigner/components/navigator/arrowdown.png b/src/plugins/qmldesigner/components/navigator/arrowdown.png
new file mode 100644
index 0000000000000000000000000000000000000000..0efd6b4de362219d87d547f13eb6fc26f28d2717
GIT binary patch
literal 390
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6U4S$Y
z{B+)352QE?JR*x37`TN&n2}-D90{Nxdx@v7EBkF08D4H?O?Tl=ppayVYeb22er|4R
zUI~M9QEFmIYKlU6W=V#EyQgnJcq5-UP|-tA7sn8b({m>u<UM4-;~K9mc7kipzqz7T
z%*s;)6IiU6)*RrHZM;{T)Vk(?s-s%ViUiFdp}+5Iep|~<HP~z|aH;F16%)H>_wl?H
z?hMadx(<j*cok_g9(a8EpYAWWrWhyVU!qSYcya7k>FE2jy{Uii%+@sFvpLs2rrfP4
zUSzzPafiiu<4ny{l6NeVzwKQjxx?zgn-h{V;=irGuX1+o<a)MahdxL6B$uU3GGQ!n
z<#&7VMr}inZo$-&s;>(^@%J6LsM(RHmp6&eS9<c6l|~`Kp6j$$OmWt%ew!ZE5IpT4
b?-!PxYh1qy>TPZWdX~Y{)z4*}Q$iB}nj?+@

literal 0
HcmV?d00001

diff --git a/src/plugins/qmldesigner/components/navigator/arrowleft.png b/src/plugins/qmldesigner/components/navigator/arrowleft.png
new file mode 100644
index 0000000000000000000000000000000000000000..c9bf785829741d962e10adbcc901b317e1654887
GIT binary patch
literal 471
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6U4S$Y
z{B+)352QE?JR*x37`TN&n2}-D90{Nxdx@v7EBkF08D1{a|IfAu0)-??Tq8=H^K)}k
z^GX<;i&7IyQd1PlGfOfQ+&z5*!W;R-fmRuLx;TbdoL+i)uiunFfny)<A3EjKB(zCo
zf`+af*ZYIhvJGy!ZC|MTkcnr8K!%vqg+r&J4dR-oeiac@I}&j~O-Y_<(~&ffdlH*Z
z9||chdiMX!nc{oX?F0qS^L9+M`ygj`&r?BZ+s8w?Nl)xQSj9b*-Q~>bazuK~1KoX#
zBn7+wvSf)?i0jrIV602x4YxSINxA3w&QAHQE!G*2gUjk#Cbujrob}W6)sM+aYpYyx
zRQ{-1>pzlyRxmT$&a*LZ-t)r7s=bTq+Ll`!%Q-Z8#);i(Qjzx$OVr(8v!Uzyk2%)<
zOWDO|-mkcD`j4aE*9}=o(z0*V?;LPqS}ZzowMo6u{p|lXkBzn!%vfx9Y;(}5e+San
zbnH2jRwkpr^bF5e)oDTZlGTsr-FX?Wv2@LH`Tcj)m69?8&c@%robu-KtE|7kAZGA%
L^>bP0l+XkK>P5f<

literal 0
HcmV?d00001

diff --git a/src/plugins/qmldesigner/components/navigator/arrowright.png b/src/plugins/qmldesigner/components/navigator/arrowright.png
new file mode 100644
index 0000000000000000000000000000000000000000..06f50ebae8d1dfe6b3ac5ef64499a036fa60672a
GIT binary patch
literal 455
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6U4S$Y
z{B+)352QE?JR*x37`TN&n2}-D90{Nxdx@v7EBkF08D4P_pU0<xatx9st`Q~9`MJ5N
zc_j?aMX8A;sVNHOnI#zt?w-B@;f;LaK&zBIT^vI!PA|Q*TdyThg!RGsACjy_B3!L5
z%Fh*D-U^CnO%)eVVQCFhaZ!|Wc+9w`)k9@>fWTZY#X|X6wkPF}_MG-BJC{0l>$h9a
zWvX0U&XgaPt~#FS^5(z$1Kw`IjbFnX`DKz-mCXJt8T3@oNibD1dzBFHa%WjU{IXk8
zt5ochn7l1?maZv1;6LY~<?6j^AGbc+F!PD@oMcO-V;cjn=9n2aO&6&<UC6+nk<2%J
z#{nj((5T#{7Z})#?@#{Ha`K4$B~R<SvEh{)rmhXS>9zUVF_&|<UuH=eN9Zq=36VG?
z@@w-a_jjHb+143MYi-*Y>17$P`(<AIPd!&V!>+ACr!MCIb3E?LeY>>ixn#Agaq;#k
ro4(8b={z7@wlDl&q05mR^FQ27S-ulHkL#5KgOtJ3)z4*}Q$iB}L+Gnl

literal 0
HcmV?d00001

diff --git a/src/plugins/qmldesigner/components/navigator/arrowup.png b/src/plugins/qmldesigner/components/navigator/arrowup.png
new file mode 100644
index 0000000000000000000000000000000000000000..098b1894a89a22b534bb63284140e6202c9c5b94
GIT binary patch
literal 376
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6U4S$Y
z{B+)352QE?JR*x37`TN&n2}-D90{Nxdx@v7EBkF08D4Iloj>?MLXst}5hc#~xw)x%
zB@E6*sfi`2DGKG8B^e6tp1uL$jeO!jMVCEY978Nl&z*dhx7mQFb^ijr34IeLzmIJc
zeZf(}V&#;cz#5j&daqVfJEb+QM<kN-@5UAvA^UsZc@8+Pe6?g%|KfQC3UZCHdpb_6
zy>`7;;QRq59^FX+huPGG({KA7U^t^xlrJ>nbIQ7%7PoTpzo;y1+B<_m;Z}3fLP_sQ
z4>nwPy0ePq%K<H=>kC#jTe@H0u|x99yBg+qsVyo>v+wS2Sbq4u>ytY*y}Ngukh^Pj
z{nH#N%gwPb58J$wpJb`F{aJX^3$_2jEbr(1@B9#2I<@{`Q0Ij;=0;QeH;Ov_EC70s
N!PC{xWt~$(695YEkfi_s

literal 0
HcmV?d00001

diff --git a/src/plugins/qmldesigner/components/navigator/navigator.pri b/src/plugins/qmldesigner/components/navigator/navigator.pri
index 75e5333d791..3ce8bc68776 100644
--- a/src/plugins/qmldesigner/components/navigator/navigator.pri
+++ b/src/plugins/qmldesigner/components/navigator/navigator.pri
@@ -8,3 +8,5 @@ HEADERS += navigatorview.h \
     navigatortreemodel.h \
     navigatorwidget.h \
     navigatortreeview.h
+
+RESOURCES += navigator.qrc
diff --git a/src/plugins/qmldesigner/components/navigator/navigator.qrc b/src/plugins/qmldesigner/components/navigator/navigator.qrc
new file mode 100644
index 00000000000..4b911febf9a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/navigator/navigator.qrc
@@ -0,0 +1,8 @@
+<RCC>
+    <qresource prefix="/navigator/icon">
+        <file>arrowdown.png</file>
+        <file>arrowleft.png</file>
+        <file>arrowright.png</file>
+        <file>arrowup.png</file>
+    </qresource>
+</RCC>
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
index 408d299aa9c..c15d04c2e70 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
@@ -46,12 +46,18 @@ namespace QmlDesigner {
 NavigatorView::NavigatorView(QObject* parent) :
         AbstractView(parent),
         m_blockSelectionChangedSignal(false),
-        m_widget(new NavigatorWidget),
+        m_widget(new NavigatorWidget(this)),
         m_treeModel(new NavigatorTreeModel(this))
 {
     m_widget->setTreeModel(m_treeModel.data());
 
     connect(treeWidget()->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(changeSelection(QItemSelection,QItemSelection)));
+
+    connect(m_widget.data(), SIGNAL(leftButtonClicked()), this, SLOT(leftButtonClicked()));
+    connect(m_widget.data(), SIGNAL(rightButtonClicked()), this, SLOT(rightButtonClicked()));
+    connect(m_widget.data(), SIGNAL(downButtonClicked()), this, SLOT(downButtonClicked()));
+    connect(m_widget.data(), SIGNAL(upButtonClicked()), this, SLOT(upButtonClicked()));
+
     treeWidget()->setIndentation(treeWidget()->indentation() * 0.5);
 
     NameItemDelegate *idDelegate = new NameItemDelegate(this,m_treeModel.data());
@@ -80,7 +86,7 @@ NavigatorView::~NavigatorView()
         delete m_widget.data();
 }
 
-QWidget *NavigatorView::widget()
+NavigatorWidget *NavigatorView::widget()
 {
     return m_widget.data();
 }
@@ -256,6 +262,75 @@ void NavigatorView::changeToComponent(const QModelIndex &index)
     }
 }
 
+void NavigatorView::leftButtonClicked()
+{
+    if (selectedModelNodes().count() > 1)
+        return; //Semantics are unclear for multi selection.
+
+    bool blocked = blockSelectionChangedSignal(true);
+
+    foreach (const ModelNode &node, selectedModelNodes()) {
+        if (!node.isRootNode() && !node.parentProperty().parentModelNode().isRootNode())
+            node.parentProperty().parentModelNode().parentProperty().reparentHere(node);
+    }
+    updateItemSelection();
+    blockSelectionChangedSignal(blocked);
+}
+
+void NavigatorView::rightButtonClicked()
+{
+    if (selectedModelNodes().count() > 1)
+        return; //Semantics are unclear for multi selection.
+
+    bool blocked = blockSelectionChangedSignal(true);
+    foreach (const ModelNode &node, selectedModelNodes()) {
+        if (!node.isRootNode() && node.parentProperty().isNodeListProperty() && node.parentProperty().toNodeListProperty().count() > 1) {
+            int index = node.parentProperty().toNodeListProperty().indexOf(node);
+            index--;
+            if (index >= 0) { //for the first node the semantics are not clear enough. Wrapping would be irritating.
+                ModelNode newParent = node.parentProperty().toNodeListProperty().at(index);
+                newParent.nodeAbstractProperty(newParent.metaInfo().defaultPropertyName()).reparentHere(node);
+            }
+        }
+    }
+    updateItemSelection();
+    blockSelectionChangedSignal(blocked);
+}
+
+void NavigatorView::upButtonClicked()
+{
+    bool blocked = blockSelectionChangedSignal(true);
+    foreach (const ModelNode &node, selectedModelNodes()) {
+        if (!node.isRootNode() && node.parentProperty().isNodeListProperty()) {
+            int oldIndex = node.parentProperty().toNodeListProperty().indexOf(node);
+            int index = oldIndex;
+            index--;
+            if (index < 0)
+                index = node.parentProperty().toNodeListProperty().count() - 1; //wrap around
+            node.parentProperty().toNodeListProperty().slide(oldIndex, index);
+        }
+    }
+    updateItemSelection();
+    blockSelectionChangedSignal(blocked);
+}
+
+void NavigatorView::downButtonClicked()
+{
+    bool blocked = blockSelectionChangedSignal(true);
+    foreach (const ModelNode &node, selectedModelNodes()) {
+        if (!node.isRootNode() && node.parentProperty().isNodeListProperty()) {
+            int oldIndex = node.parentProperty().toNodeListProperty().indexOf(node);
+            int index = oldIndex;
+            index++;
+            if (index >= node.parentProperty().toNodeListProperty().count())
+                index = 0; //wrap around
+            node.parentProperty().toNodeListProperty().slide(oldIndex, index);
+        }
+    }
+    updateItemSelection();
+    blockSelectionChangedSignal(blocked);
+}
+
 void NavigatorView::changeSelection(const QItemSelection & /*newSelection*/, const QItemSelection &/*deselected*/)
 {
     if (m_blockSelectionChangedSignal)
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.h b/src/plugins/qmldesigner/components/navigator/navigatorview.h
index c51524eac52..825eae0e679 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.h
@@ -59,7 +59,7 @@ public:
     NavigatorView(QObject* parent = 0);
     ~NavigatorView();
 
-    QWidget *widget();
+    NavigatorWidget *widget();
 
     // AbstractView
     void modelAttached(Model *model);
@@ -104,6 +104,11 @@ private slots:
     void updateItemSelection();
     void changeToComponent(const QModelIndex &index);
 
+    void leftButtonClicked();
+    void rightButtonClicked();
+    void upButtonClicked();
+    void downButtonClicked();
+
 protected: //functions
     QTreeView *treeWidget();
     NavigatorTreeModel *treeModel();
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp b/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp
index 59d6297c664..d81e1e741c5 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp
@@ -36,15 +36,17 @@
 #include <model.h>
 
 #include "navigatorwidget.h"
+#include "navigatorview.h"
 
 #include <utils/fileutils.h>
 
 
 namespace QmlDesigner {
 
-NavigatorWidget::NavigatorWidget(QWidget* parent) :
-        QFrame(parent),
-        m_treeView(new NavigatorTreeView)
+NavigatorWidget::NavigatorWidget(NavigatorView *view) :
+        QFrame(),
+        m_treeView(new NavigatorTreeView),
+        m_navigatorView(view)
 {
     m_treeView->setDragEnabled(true);
     m_treeView->setAcceptDrops(true);
@@ -79,4 +81,54 @@ void NavigatorWidget::setTreeModel(QAbstractItemModel* model)
     m_treeView->setModel(model);
 }
 
+QList<QToolButton *> NavigatorWidget::createToolBarWidgets()
+{
+    QList<QToolButton *> buttons;
+
+    buttons << new QToolButton();
+    buttons.last()->setIcon(QIcon(":/navigator/icon/arrowleft.png"));
+    buttons.last()->setToolTip(tr("Become first sibling of parent (CTRL + Left)"));
+    buttons.last()->setShortcut(QKeySequence(Qt::Key_Left | Qt::CTRL));
+    connect(buttons.last(), SIGNAL(clicked()), this, SIGNAL(leftButtonClicked()));
+    buttons << new QToolButton();
+    buttons.last()->setIcon(QIcon(":/navigator/icon/arrowright.png"));
+    buttons.last()->setToolTip(tr("Become child of first silbing (CTRL + Right)"));
+    buttons.last()->setShortcut(QKeySequence(Qt::Key_Right | Qt::CTRL));
+    connect(buttons.last(), SIGNAL(clicked()), this, SIGNAL(rightButtonClicked()));
+
+    buttons << new QToolButton();
+    buttons.last()->setIcon(QIcon(":/navigator/icon/arrowdown.png"));
+    buttons.last()->setToolTip(tr("Move down (CTRL + Down)"));
+    buttons.last()->setShortcut(QKeySequence(Qt::Key_Down | Qt::CTRL));
+    connect(buttons.last(), SIGNAL(clicked()), this, SIGNAL(downButtonClicked()));
+
+    buttons << new QToolButton();
+    buttons.last()->setIcon(QIcon(":/navigator/icon/arrowup.png"));
+    buttons.last()->setToolTip(tr("Move up (CTRL + Up)"));
+    buttons.last()->setShortcut(QKeySequence(Qt::Key_Up | Qt::CTRL));
+    connect(buttons.last(), SIGNAL(clicked()), this, SIGNAL(upButtonClicked()));
+
+    return buttons;
+}
+
+QString NavigatorWidget::contextHelpId() const
+{
+    if (!navigatorView())
+        return QString();
+
+    QList<ModelNode> nodes = navigatorView()->selectedModelNodes();
+    QString helpId;
+    if (!nodes.isEmpty()) {
+        helpId = nodes.first().type();
+        helpId.replace("QtQuick", "QML");
+    }
+
+    return helpId;
+}
+
+NavigatorView *NavigatorWidget::navigatorView() const
+{
+    return m_navigatorView.data();
+}
+
 }
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorwidget.h b/src/plugins/qmldesigner/components/navigator/navigatorwidget.h
index 2d78b6382f8..c09d2c6de1a 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorwidget.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatorwidget.h
@@ -35,25 +35,37 @@
 
 #include <QFrame>
 #include <QAbstractItemModel>
+#include <QtGui/QToolButton>
 
 #include "navigatortreeview.h"
 
 namespace QmlDesigner {
 
 class Model;
+class NavigatorView;
 
 class NavigatorWidget: public QFrame
 {
     Q_OBJECT
 public:
-    NavigatorWidget(QWidget* parent = 0);
+    NavigatorWidget(NavigatorView *view);
     virtual ~NavigatorWidget();
 
     void setTreeModel(QAbstractItemModel *model);
     QTreeView *treeView() const { return m_treeView; }
+    QList<QToolButton *> createToolBarWidgets();
+    QString contextHelpId() const;
+
+signals:
+    void leftButtonClicked();
+    void rightButtonClicked();
+    void upButtonClicked();
+    void downButtonClicked();
 
 private:
+    NavigatorView *navigatorView() const;
     NavigatorTreeView *m_treeView;
+    QWeakPointer<NavigatorView> m_navigatorView;
 };
 
 }
diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp
index 7bd0faefa56..bbaa948d1bc 100644
--- a/src/plugins/qmldesigner/designmodewidget.cpp
+++ b/src/plugins/qmldesigner/designmodewidget.cpp
@@ -153,6 +153,27 @@ QList<QToolButton *> ItemLibrarySideBarItem::createToolBarWidgets()
     return qobject_cast<ItemLibraryWidget*>(widget())->createToolBarWidgets();
 }
 
+class NavigatorSideBarItem : public Core::SideBarItem
+{
+public:
+    explicit NavigatorSideBarItem(NavigatorWidget *widget, const QString &id);
+    virtual ~NavigatorSideBarItem();
+
+    virtual QList<QToolButton *> createToolBarWidgets();
+};
+
+NavigatorSideBarItem::NavigatorSideBarItem(NavigatorWidget *widget, const QString &id) : Core::SideBarItem(widget, id) {}
+
+NavigatorSideBarItem::~NavigatorSideBarItem()
+{
+
+}
+
+QList<QToolButton *> NavigatorSideBarItem::createToolBarWidgets()
+{
+    return qobject_cast<NavigatorWidget*>(widget())->createToolBarWidgets();
+}
+
 void DocumentWarningWidget::goToError()
 {
     m_designModeWidget->textEditor()->gotoLine(m_error.line(), m_error.column() - 1);
-- 
GitLab