From a9d772796ce91951ce0452cec98971b3d2d1f302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Sun, 9 May 2010 16:34:58 +0000 Subject: [PATCH] Drag&Drop support for window tabs in Aurorae. svn path=/trunk/KDE/kdebase/workspace/; revision=1124608 --- clients/aurorae/src/aurorae.cpp | 21 +++++++++ clients/aurorae/src/aurorae.h | 3 ++ clients/aurorae/src/lib/auroraescene.cpp | 60 +++++++++++++++++++++++- clients/aurorae/src/lib/auroraescene.h | 11 +++++ clients/aurorae/src/lib/auroraetab.cpp | 39 +++++++++++++++ clients/aurorae/src/lib/auroraetab.h | 8 +++- clients/aurorae/src/lib/auroraetheme.cpp | 11 +++++ clients/aurorae/src/lib/auroraetheme.h | 3 ++ 8 files changed, 153 insertions(+), 3 deletions(-) diff --git a/clients/aurorae/src/aurorae.cpp b/clients/aurorae/src/aurorae.cpp index 9a6965cece..623c2a3e5d 100644 --- a/clients/aurorae/src/aurorae.cpp +++ b/clients/aurorae/src/aurorae.cpp @@ -50,6 +50,7 @@ void AuroraeFactory::init() m_theme->setBorderSize((KDecorationDefines::BorderSize)themeGroup.readEntry("BorderSize", KDecorationDefines::BorderNormal)); m_theme->setButtonSize((KDecorationDefines::BorderSize)themeGroup.readEntry("ButtonSize", KDecorationDefines::BorderNormal)); m_theme->setShowTooltips(options()->showTooltips()); + m_theme->setTabDragMimeType(clientGroupItemDragMimeType()); } AuroraeFactory::~AuroraeFactory() @@ -156,6 +157,9 @@ AuroraeClient::AuroraeClient(KDecorationBridge *bridge, KDecorationFactory *fact SLOT(tabMouseButtonPress(QGraphicsSceneMouseEvent*,int))); connect(m_scene, SIGNAL(tabMouseButtonRelease(QGraphicsSceneMouseEvent*,int)), SLOT(tabMouseButtonRelease(QGraphicsSceneMouseEvent*,int))); + connect(m_scene, SIGNAL(tabRemoved(int)), SLOT(tabRemoved(int))); + connect(m_scene, SIGNAL(tabMoved(int,int)), SLOT(tabMoved(int,int))); + connect(m_scene, SIGNAL(tabMovedToGroup(long int,int)), SLOT(tabMovedToGroup(long int,int))); connect(this, SIGNAL(keepAboveChanged(bool)), SLOT(keepAboveChanged(bool))); connect(this, SIGNAL(keepBelowChanged(bool)), SLOT(keepBelowChanged(bool))); } @@ -438,6 +442,8 @@ void AuroraeClient::tabMouseButtonPress(QGraphicsSceneMouseEvent *e, int index) if (buttonToWindowOperation(e->buttons()) == OperationsOp) { displayClientMenu(index, e->screenPos()); return; + } else if (buttonToWindowOperation(e->buttons()) == ClientGroupDragOp) { + m_scene->setUniqueTabDragId(index, itemId(index)); } titlePressed(e->button(), e->buttons()); m_clickInProgress = true; @@ -452,6 +458,21 @@ void AuroraeClient::tabMouseButtonRelease(QGraphicsSceneMouseEvent *e, int index m_clickInProgress = false; } +void AuroraeClient::tabRemoved(int index) +{ + removeFromClientGroup(index); +} + +void AuroraeClient::tabMoved(int index, int before) +{ + moveItemInClientGroup(index, before); +} + +void AuroraeClient::tabMovedToGroup(long int uid, int before) +{ + moveItemToClientGroup(uid, before); +} + } // namespace Aurorae extern "C" diff --git a/clients/aurorae/src/aurorae.h b/clients/aurorae/src/aurorae.h index 9336b81eba..12cd90f234 100644 --- a/clients/aurorae/src/aurorae.h +++ b/clients/aurorae/src/aurorae.h @@ -89,6 +89,9 @@ private slots: void titleMouseMoved(Qt::MouseButton button, Qt::MouseButtons buttons); void tabMouseButtonPress(QGraphicsSceneMouseEvent *e, int index); void tabMouseButtonRelease(QGraphicsSceneMouseEvent *e, int index); + void tabRemoved(int index); + void tabMoved(int index, int before); + void tabMovedToGroup(long int uid, int before); protected: virtual bool eventFilter(QObject *o, QEvent *e); diff --git a/clients/aurorae/src/lib/auroraescene.cpp b/clients/aurorae/src/lib/auroraescene.cpp index 48f69a426d..d1eb8c7f3b 100644 --- a/clients/aurorae/src/lib/auroraescene.cpp +++ b/clients/aurorae/src/lib/auroraescene.cpp @@ -27,8 +27,10 @@ #include #include #include +#include #include #include +#include // KDE #include #include @@ -789,8 +791,7 @@ void AuroraeScene::addTab(const QString &caption) connect(tab, SIGNAL(mouseButtonRelease(QGraphicsSceneMouseEvent*,int)), SIGNAL(tabMouseButtonRelease(QGraphicsSceneMouseEvent*,int))); connect(tab, SIGNAL(mouseDblClicked()), SIGNAL(titleDoubleClicked())); - connect(tab, SIGNAL(mouseMoved(Qt::MouseButton,Qt::MouseButtons)), - SIGNAL(titleMouseMoved(Qt::MouseButton,Qt::MouseButtons))); + connect(tab, SIGNAL(tabRemoved(int)), SIGNAL(tabRemoved(int))); static_cast(m_title->layout())->addItem(tab); tab->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_title->layout()->invalidate(); @@ -847,6 +848,16 @@ bool AuroraeScene::isFocusedTab(int index) const return (index == m_focusedTab); } +void AuroraeScene::setUniqueTabDragId(int index, long int id) +{ + for (int i=0; ilayout()->count(); ++i) { + if (static_cast(m_title->layout()->itemAt(i))->index() == index) { + static_cast(m_title->layout()->itemAt(i))->setUniqueTabId(id); + break; + } + } +} + void AuroraeScene::mousePressEvent(QGraphicsSceneMouseEvent* event) { QGraphicsScene::mousePressEvent(event); @@ -892,6 +903,51 @@ void AuroraeScene::wheelEvent(QGraphicsSceneWheelEvent* event) } } +void AuroraeScene::dragEnterEvent(QGraphicsSceneDragDropEvent* event) +{ + QGraphicsScene::dragEnterEvent(event); + if (event->mimeData()->hasFormat(m_theme->tabDragMimeType())) { + event->accept(); + } +} + +void AuroraeScene::dragMoveEvent(QGraphicsSceneDragDropEvent* event) +{ + QGraphicsScene::dragMoveEvent(event); + if (event->mimeData()->hasFormat(m_theme->tabDragMimeType())) { + event->accept(); + } +} + +void AuroraeScene::dropEvent(QGraphicsSceneDragDropEvent *event) +{ + QGraphicsScene::dropEvent(event); + if (event->mimeData()->hasFormat(m_theme->tabDragMimeType())) { + QList ids = event->mimeData()->data(m_theme->tabDragMimeType()).split('/'); + bool insideScene = false; + foreach (QGraphicsView *view, views()) { + if (view->window() == event->source()->window()) { + insideScene = true; + break; + } + } + int index = -1; + if (QGraphicsItem *item = itemAt(event->scenePos())) { + if (AuroraeTab *tab = dynamic_cast(item)) { + index = tab->index(); + } + } + if (insideScene) { + // move inside decoration + emit tabMoved(ids[1].toInt(), index); + } else { + // move to this decoration + long source = ids[0].toLong(); + emit tabMovedToGroup(source, index); + } + } +} + QString AuroraeScene::buttonsToDirection(const QString &buttons) { QString ret; diff --git a/clients/aurorae/src/lib/auroraescene.h b/clients/aurorae/src/lib/auroraescene.h index 601f8347af..89cee3ee3c 100644 --- a/clients/aurorae/src/lib/auroraescene.h +++ b/clients/aurorae/src/lib/auroraescene.h @@ -99,6 +99,11 @@ public: * @returns true if the tab at given index is the focused one. */ bool isFocusedTab(int index) const; + /** + * Sets the unique tab id for dragging the tab specified by \p index. + * When the tab is clicked this will enable dragging till the mouse is released. + */ + void setUniqueTabDragId(int index, long int id); const QString &leftButtons() const; const QString &rightButtons() const; @@ -120,6 +125,9 @@ Q_SIGNALS: void wheelEvent(int delta); void tabMouseButtonPress(QGraphicsSceneMouseEvent*, int); void tabMouseButtonRelease(QGraphicsSceneMouseEvent*, int); + void tabRemoved(int); + void tabMoved(int index, int before); + void tabMovedToGroup(long int uid, int before); void activeChanged(); @@ -130,6 +138,9 @@ protected: virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event); virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event); virtual void wheelEvent(QGraphicsSceneWheelEvent* event); + virtual void dragEnterEvent(QGraphicsSceneDragDropEvent *event); + virtual void dragMoveEvent(QGraphicsSceneDragDropEvent *event); + virtual void dropEvent(QGraphicsSceneDragDropEvent *event); private Q_SLOTS: void resetTheme(); diff --git a/clients/aurorae/src/lib/auroraetab.cpp b/clients/aurorae/src/lib/auroraetab.cpp index 8ca7cdffa6..2a11ff8bda 100644 --- a/clients/aurorae/src/lib/auroraetab.cpp +++ b/clients/aurorae/src/lib/auroraetab.cpp @@ -40,6 +40,9 @@ AuroraeTab::AuroraeTab(AuroraeTheme* theme, const QString& caption, int index) , m_caption(caption) , m_index(index) , m_dblClicked(false) + , m_uid(-1) + , m_dragAllowed(true) + , m_clickInProgress(false) { m_effect = new QGraphicsDropShadowEffect(this); if (m_theme->themeConfig().useTextShadow()) { @@ -222,16 +225,29 @@ void AuroraeTab::buttonSizesChanged() updateGeometry(); } +void AuroraeTab::setUniqueTabId(long int id) +{ + m_uid = id; + if (m_clickInProgress) { + m_dragAllowed = true; + } +} + void AuroraeTab::mousePressEvent(QGraphicsSceneMouseEvent *event) { QGraphicsItem::mousePressEvent(event); event->accept(); + m_clickPos = event->pos(); + m_clickInProgress = true; + m_dragAllowed = false; emit mouseButtonPress(event, m_index); } void AuroraeTab::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { QGraphicsItem::mouseReleaseEvent(event); + m_dragAllowed = false; + m_clickInProgress = false; if (m_dblClicked && event->button() == Qt::LeftButton) { // eat event m_dblClicked = false; @@ -242,10 +258,33 @@ void AuroraeTab::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void AuroraeTab::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { + m_clickInProgress = false; if (event->button() == Qt::LeftButton) { m_dblClicked = true; emit mouseDblClicked(); } } +void AuroraeTab::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + AuroraeScene *s = static_cast(scene()); + if (s->tabCount() >= 1 && m_dragAllowed && + (event->pos() - m_clickPos).manhattanLength() >= KGlobalSettings::dndEventDelay()) { + QDrag *drag = new QDrag(event->widget()); + QMimeData *data = new QMimeData; + QString itemData = QString().setNum(m_uid) + '/' + QString().setNum(m_index); + data->setData(m_theme->tabDragMimeType(), itemData.toAscii()); + drag->setMimeData(data); + QPixmap pix(size().toSize()); + pix.fill(Qt::transparent); + QPainter painter(&pix); + s->render(&painter, pix.rect(), sceneBoundingRect()); + drag->setPixmap(pix); + drag->exec(); + if (!drag->target() && s->tabCount() > 1) { + emit tabRemoved(m_index); + } + } +} + } // namespace diff --git a/clients/aurorae/src/lib/auroraetab.h b/clients/aurorae/src/lib/auroraetab.h index 224e437095..81d20a688e 100644 --- a/clients/aurorae/src/lib/auroraetab.h +++ b/clients/aurorae/src/lib/auroraetab.h @@ -39,12 +39,13 @@ public: int index() const { return m_index; } + void setUniqueTabId(long int id); Q_SIGNALS: void mouseButtonPress(QGraphicsSceneMouseEvent *e, int index); void mouseButtonRelease(QGraphicsSceneMouseEvent *e, int index); void mouseDblClicked(); - void mouseMoved(Qt::MouseButton, Qt::MouseButtons); + void tabRemoved(int index); public Q_SLOTS: void activeChanged(); @@ -53,6 +54,7 @@ protected: virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); private Q_SLOTS: void buttonSizesChanged(); @@ -63,6 +65,10 @@ private: int m_index; QGraphicsDropShadowEffect *m_effect; bool m_dblClicked; + QPointF m_clickPos; + long int m_uid; + bool m_dragAllowed; + bool m_clickInProgress; }; } diff --git a/clients/aurorae/src/lib/auroraetheme.cpp b/clients/aurorae/src/lib/auroraetheme.cpp index 13b5e39df9..8b62865586 100644 --- a/clients/aurorae/src/lib/auroraetheme.cpp +++ b/clients/aurorae/src/lib/auroraetheme.cpp @@ -50,6 +50,7 @@ public: KDecorationDefines::BorderSize borderSize; bool showTooltips; KDecorationDefines::BorderSize buttonSize; + QString dragMimeType; }; AuroraeThemePrivate::AuroraeThemePrivate() @@ -429,6 +430,16 @@ void AuroraeTheme::setButtonSize(KDecorationDefines::BorderSize size) emit buttonSizesChanged(); } +void AuroraeTheme::setTabDragMimeType(const QString &mime) +{ + d->dragMimeType = mime; +} + +const QString &AuroraeTheme::tabDragMimeType() const +{ + return d->dragMimeType; +} + qreal AuroraeTheme::buttonSizeFactor() const { switch (d->buttonSize) { diff --git a/clients/aurorae/src/lib/auroraetheme.h b/clients/aurorae/src/lib/auroraetheme.h index 7169039368..70b662f662 100644 --- a/clients/aurorae/src/lib/auroraetheme.h +++ b/clients/aurorae/src/lib/auroraetheme.h @@ -121,6 +121,9 @@ public: DecorationPosition decorationPosition() const; + void setTabDragMimeType(const QString &mime); + const QString &tabDragMimeType() const; + // TODO: move to namespace static QLatin1String mapButtonToName(AuroraeButtonType type); static char mapButtonToChar(AuroraeButtonType type);