[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [konversation/1.6] src/viewer: Reimplement ViewTree DND reordering.
From:       Eike Hein <hein () kde ! org>
Date:       2015-04-03 22:48:51
Message-ID: E1YeAOR-0002Q4-0i () scm ! kde ! org
[Download RAW message or body]

Git commit a341c48fa5f1e1bd6141355f3a01d640bd47988c by Eike Hein.
Committed on 03/04/2015 at 22:48.
Pushed by hein into branch '1.6'.

Reimplement ViewTree DND reordering.

BUG:341405

M  +157  -1    src/viewer/viewcontainer.cpp
M  +23   -1    src/viewer/viewcontainer.h
M  +2    -2    src/viewer/viewspringloader.cpp
M  +52   -14   src/viewer/viewtree.cpp
M  +7    -0    src/viewer/viewtree.h

http://commits.kde.org/konversation/a341c48fa5f1e1bd6141355f3a01d640bd47988c

diff --git a/src/viewer/viewcontainer.cpp b/src/viewer/viewcontainer.cpp
index 5c94073..f91ba11 100644
--- a/src/viewer/viewcontainer.cpp
+++ b/src/viewer/viewcontainer.cpp
@@ -57,6 +57,23 @@
 
 using namespace Konversation;
 
+ViewMimeData::ViewMimeData(ChatWindow *view) : QMimeData()
+, m_view(view)
+{
+    if (view) {
+        setData("application/x-konversation-chatwindow", view->getName().toUtf8());
+    }
+}
+
+ViewMimeData::~ViewMimeData()
+{
+}
+
+ChatWindow* ViewMimeData::view() const
+{
+    return m_view;
+}
+
 TabWidget::TabWidget(QWidget* parent) : QTabWidget(parent)
 {
 }
@@ -519,6 +536,145 @@ QVariant ViewContainer::data(const QModelIndex& index, int \
role) const  return QVariant();
 }
 
+Qt::DropActions ViewContainer::supportedDragActions() const
+{
+    return Qt::MoveAction;
+}
+
+Qt::DropActions ViewContainer::supportedDropActions() const
+{
+    return Qt::MoveAction;
+}
+
+Qt::ItemFlags ViewContainer::flags(const QModelIndex &index) const
+{
+    Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index);
+
+    return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
+}
+
+QStringList ViewContainer::mimeTypes() const
+{
+    return QStringList() << QLatin1String("application/x-konversation-chatwindow");
+}
+
+QMimeData* ViewContainer::mimeData(const QModelIndexList &indexes) const
+{
+    if (!indexes.length()) {
+        return new ViewMimeData(0);
+    }
+
+    const QModelIndex &idx = indexes.at(0);
+
+    if (!idx.isValid()) {
+        return new ViewMimeData(0);
+    }
+
+    return new ViewMimeData(static_cast<ChatWindow *>(idx.internalPointer()));
+}
+
+bool ViewContainer::canDropMimeData(const QMimeData *data, Qt::DropAction action, \
int row, int column, const QModelIndex &parent) const +{
+    if (action != Qt::MoveAction) {
+        return false;
+    }
+
+    if (!data->hasFormat("application/x-konversation-chatwindow")) {
+        return false;
+    }
+
+    if (row == -1 || column != 0) {
+        return false;
+    }
+
+    ChatWindow *dragView = static_cast<const ViewMimeData *>(data)->view();
+
+    if (!dragView->isTopLevelView()
+        && (!parent.isValid()
+        || (dragView->getServer() != static_cast<ChatWindow* \
>(parent.internalPointer())->getServer()))) { +        return false;
+    }
+
+    if (dragView->isTopLevelView() && parent.isValid()) {
+        return false;
+    }
+
+    if (m_viewTree && !m_viewTree->showDropIndicator()) {
+        m_viewTree->setDropIndicatorShown(true);
+        m_viewTree->viewport()->update();
+    }
+
+    return true;
+}
+
+bool ViewContainer::dropMimeData(const QMimeData *data, Qt::DropAction action, int \
row, int column, const QModelIndex &parent) +{
+    if (action != Qt::MoveAction) {
+        return false;
+    }
+
+    if (!data->hasFormat("application/x-konversation-chatwindow")) {
+        return false;
+    }
+
+    if (row == -1 || column != 0) {
+        return false;
+    }
+
+    ChatWindow *dragView = static_cast<const ViewMimeData *>(data)->view();
+    QModelIndex dragIdx = indexForView(dragView);
+
+    if (dragView->isTopLevelView()) {
+        if (parent.isValid()) {
+            return false;
+        }
+
+        for (int i = row < dragIdx.row() ? 0 : 1; i < std::abs(dragIdx.row() - row); \
++i) { +            (row < dragIdx.row()) ? moveViewLeft() : moveViewRight();
+        }
+
+        return true;
+    } else {
+        if (!parent.isValid()) {
+            return false;
+        }
+
+        int from = m_tabWidget->indexOf(dragView);
+        int to = m_tabWidget->indexOf(static_cast<ChatWindow* \
>(parent.internalPointer())) + row; +
+        if (to < from) {
+            ++to;
+        }
+
+        if (from == to) {
+            return false;
+        }
+
+        beginMoveRows(parent, dragIdx.row(), dragIdx.row(), parent, row);
+
+        m_tabWidget->blockSignals(true);
+        m_tabWidget->tabBar()->moveTab(from, to);
+        m_tabWidget->blockSignals(false);
+
+        endMoveRows();
+
+        viewSwitched(m_tabWidget->currentIndex());
+
+        return true;
+    }
+
+    return false;
+}
+
+bool ViewContainer::removeRows(int row, int count, const QModelIndex &parent)
+{
+    Q_UNUSED(row)
+    Q_UNUSED(count)
+    Q_UNUSED(parent)
+
+    return true;
+}
+
 void ViewContainer::updateAppearance()
 {
     if (Preferences::self()->tabPlacement()==Preferences::Left && m_viewTree == 0)
@@ -1519,7 +1675,7 @@ void ViewContainer::unclutterTabs()
 
     emit endResetModel();
 
-    emit viewSwitched(m_tabWidget->currentIndex());
+    viewSwitched(m_tabWidget->currentIndex());
 }
 
 void ViewContainer::viewSwitched(int newIndex)
diff --git a/src/viewer/viewcontainer.h b/src/viewer/viewcontainer.h
index c044f04..cf433c0 100644
--- a/src/viewer/viewcontainer.h
+++ b/src/viewer/viewcontainer.h
@@ -17,7 +17,7 @@
 #include "server.h"
 
 #include <QAbstractItemModel>
-
+#include <QMimeData>
 #include <QTabWidget>
 
 class QSplitter;
@@ -45,6 +45,18 @@ namespace Konversation
     }
 }
 
+class ViewMimeData : public QMimeData
+{
+    public:
+        explicit ViewMimeData(ChatWindow *view);
+        ~ViewMimeData();
+
+        ChatWindow* view() const;
+
+    private:
+        ChatWindow *m_view;
+};
+
 class TabWidget : public QTabWidget
 {
     Q_OBJECT
@@ -94,6 +106,16 @@ class ViewContainer : public QAbstractItemModel
 
         QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
 
+        Qt::DropActions supportedDragActions() const;
+        Qt::DropActions supportedDropActions() const;
+        Qt::ItemFlags flags(const QModelIndex &index) const;
+        QStringList mimeTypes() const;
+        QMimeData* mimeData(const QModelIndexList &indexes) const;
+        bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, \
int column, const QModelIndex &parent) const; +        bool dropMimeData(const \
QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex \
&parent); +
+        bool removeRows(int row, int count, const QModelIndex &parent = \
QModelIndex()); +
         QString currentViewTitle();
         QString currentViewURL(bool passNetwork = true);
 
diff --git a/src/viewer/viewspringloader.cpp b/src/viewer/viewspringloader.cpp
index 1110487..604e5e7 100644
--- a/src/viewer/viewspringloader.cpp
+++ b/src/viewer/viewspringloader.cpp
@@ -48,7 +48,7 @@ bool ViewSpringLoader::eventFilter(QObject* watched, QEvent* event)
 {
     if (event->type() == QEvent::DragEnter)
     {
-        if (!static_cast<QDragEnterEvent*>(event)->mimeData()->hasFormat("application/x-qlistviewitem"))
 +        if (!static_cast<QDragEnterEvent*>(event)->mimeData()->hasFormat("application/x-konversation-chatwindow"))
  {
             m_hoveredWidget = static_cast<QWidget*>(watched);
 
@@ -61,7 +61,7 @@ bool ViewSpringLoader::eventFilter(QObject* watched, QEvent* event)
     {
         QDragMoveEvent* dragMoveEvent = static_cast<QDragMoveEvent*>(event);
 
-        if (!dragMoveEvent->mimeData()->hasFormat("application/x-qlistviewitem"))
+        if (!dragMoveEvent->mimeData()->hasFormat("application/x-konversation-chatwindow"))
  {
             ChatWindow* hoveredView = viewForPos(watched, dragMoveEvent->pos());
 
diff --git a/src/viewer/viewtree.cpp b/src/viewer/viewtree.cpp
index 7a5225a..f3352c6 100644
--- a/src/viewer/viewtree.cpp
+++ b/src/viewer/viewtree.cpp
@@ -19,8 +19,10 @@
 #include <QContextMenuEvent>
 #include <QCoreApplication>
 #include <QFontDatabase>
+#include <QGuiApplication>
 #include <QPainter>
 #include <QItemSelectionModel>
+#include <QStyleHints>
 #include <QToolTip>
 
 // FIXME KF5 Port: Not DPI-aware.
@@ -157,12 +159,11 @@ ViewTree::ViewTree(QWidget* parent) : QTreeView(parent)
 
     setEditTriggers(QAbstractItemView::NoEditTriggers);
 
+    setDragEnabled(true); // We initiate drags ourselves below.
     setAcceptDrops(true);
     viewport()->setAcceptDrops(true);
     setDragDropMode(QAbstractItemView::DropOnly);
-
-    setDragEnabled(false);
-    setDropIndicatorShown(false);
+    setDropIndicatorShown(true);
 
     setBackgroundRole(QPalette::Base);
 
@@ -175,7 +176,7 @@ ViewTree::~ViewTree()
 {
 }
 
-void ViewTree::setModel (QAbstractItemModel *model)
+void ViewTree::setModel(QAbstractItemModel *model)
 {
     QTreeView::setModel(model);
 
@@ -184,6 +185,10 @@ void ViewTree::setModel (QAbstractItemModel *model)
     connect(selectionModel(), &QItemSelectionModel::selectionChanged, this, \
&ViewTree::selectionChanged);  }
 
+bool ViewTree::dropIndicatorOnItem() const
+{
+    return (dropIndicatorPosition() == OnItem);
+}
 void ViewTree::updateAppearance()
 {
     if (Preferences::self()->customTabFont())
@@ -300,15 +305,13 @@ void ViewTree::mousePressEvent(QMouseEvent* event)
         event->ignore();
 
         return;
-    } else if (event->button() == Qt::MiddleButton && \
Preferences::self()->middleClickClose()) { +    } else if (event->button() == \
Qt::MiddleButton) { +        m_pressPos = event->pos();
+
         const QModelIndex& idx = indexAt(event->pos());
 
         if (idx.isValid()) {
             m_pressedView = static_cast<ChatWindow*>(idx.internalPointer());
-
-            event->ignore();
-
-            return;
         }
     }
 
@@ -317,12 +320,16 @@ void ViewTree::mousePressEvent(QMouseEvent* event)
 
 void ViewTree::mouseReleaseEvent(QMouseEvent* event)
 {
-    if (event->button() == Qt::MiddleButton && \
                Preferences::self()->middleClickClose()) {
-        const QModelIndex& idx = indexAt(event->pos());
+    if (event->button() == Qt::MiddleButton) {
+        m_pressPos = QPoint();
 
-        if (idx.isValid()) {
-            if (m_pressedView != 0 && m_pressedView == \
                static_cast<ChatWindow*>(idx.internalPointer())) {
-                emit closeView(m_pressedView.data());
+        if (Preferences::self()->middleClickClose()) {
+            const QModelIndex& idx = indexAt(event->pos());
+
+            if (idx.isValid()) {
+                if (m_pressedView != 0 && m_pressedView == \
static_cast<ChatWindow*>(idx.internalPointer())) { +                    emit \
closeView(m_pressedView.data()); +                }
             }
         }
     }
@@ -332,6 +339,37 @@ void ViewTree::mouseReleaseEvent(QMouseEvent* event)
     QTreeView::mouseReleaseEvent(event);
 }
 
+void ViewTree::mouseMoveEvent(QMouseEvent* event)
+{
+    if (m_pressedView && (m_pressPos - event->pos()).manhattanLength() >= \
QGuiApplication::styleHints()->startDragDistance()) { +        \
selectionModel()->select(indexAt(event->pos()), QItemSelectionModel::ClearAndSelect); \
+        startDrag(Qt::MoveAction); +        m_pressPos = QPoint();
+        m_pressedView = 0;
+    }
+
+    QTreeView::mouseMoveEvent(event);
+}
+
+void ViewTree::dragEnterEvent(QDragEnterEvent* event)
+{
+    if (event->source() == this && event->possibleActions() & Qt::MoveAction) {
+        event->accept();
+        setState(DraggingState);
+    } else {
+        event->ignore();
+    }
+}
+
+void ViewTree::dragMoveEvent(QDragMoveEvent* event)
+{
+    QTreeView::dragMoveEvent(event);
+
+    // Work around Qt being idiotic and not hiding the drop indicator when we want \
it to. +    setDropIndicatorShown(event->isAccepted() && !dropIndicatorOnItem());
+    viewport()->update();
+}
+
 void ViewTree::contextMenuEvent(QContextMenuEvent* event)
 {
     const QModelIndex& idx = indexAt(event->pos());
diff --git a/src/viewer/viewtree.h b/src/viewer/viewtree.h
index 0b9d38e..02338ba 100644
--- a/src/viewer/viewtree.h
+++ b/src/viewer/viewtree.h
@@ -48,6 +48,8 @@ class ViewTree : public QTreeView
 
         virtual void setModel(QAbstractItemModel *model);
 
+        bool dropIndicatorOnItem() const;
+
     public Q_SLOTS:
         void updateAppearance();
         void selectView(const QModelIndex &index);
@@ -65,6 +67,9 @@ class ViewTree : public QTreeView
         void resizeEvent(QResizeEvent* event);
         void mousePressEvent(QMouseEvent* event);
         void mouseReleaseEvent(QMouseEvent* event);
+        void mouseMoveEvent(QMouseEvent *event);
+        void dragEnterEvent(QDragEnterEvent *event);
+        void dragMoveEvent(QDragMoveEvent *event);
         void contextMenuEvent(QContextMenuEvent* event);
         void wheelEvent(QWheelEvent* event);
         void keyPressEvent(QKeyEvent* event);
@@ -74,6 +79,8 @@ class ViewTree : public QTreeView
 
     private:
         QPointer<ChatWindow> m_pressedView;
+
+        QPoint m_pressPos;
 };
 
 #endif


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic