[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