Drag&Drop support for window tabs in Aurorae.

svn path=/trunk/KDE/kdebase/workspace/; revision=1124608
This commit is contained in:
Martin Gräßlin 2010-05-09 16:34:58 +00:00
parent 253f0523c6
commit a9d772796c
8 changed files with 153 additions and 3 deletions

View file

@ -50,6 +50,7 @@ void AuroraeFactory::init()
m_theme->setBorderSize((KDecorationDefines::BorderSize)themeGroup.readEntry<int>("BorderSize", KDecorationDefines::BorderNormal));
m_theme->setButtonSize((KDecorationDefines::BorderSize)themeGroup.readEntry<int>("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"

View file

@ -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);

View file

@ -27,8 +27,10 @@
#include <QtCore/QPropertyAnimation>
#include <QtGui/QGraphicsLinearLayout>
#include <QtGui/QGraphicsSceneMouseEvent>
#include <QtGui/QGraphicsView>
#include <QtGui/QIcon>
#include <QtGui/QPainter>
#include <QtGui/QWidget>
// KDE
#include <KDE/Plasma/FrameSvg>
#include <KDE/Plasma/PaintUtils>
@ -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<QGraphicsLinearLayout*>(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; i<m_title->layout()->count(); ++i) {
if (static_cast<AuroraeTab*>(m_title->layout()->itemAt(i))->index() == index) {
static_cast<AuroraeTab*>(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<QByteArray> 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<AuroraeTab*>(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;

View file

@ -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();

View file

@ -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<AuroraeScene*>(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

View file

@ -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;
};
}

View file

@ -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) {

View file

@ -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);