[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: extragear/utils/yakuake
From: Eike Hein <hein () kde ! org>
Date: 2009-03-18 18:30:54
Message-ID: 1237401054.005575.29331.nullmailer () svn ! kde ! org
[Download RAW message or body]
SVN commit 941035 by hein:
Add support for moving tabs on the tab bar by drag and drop. Patch
by Juan Carlos Torres.
M +1 -0 ChangeLog
M +2 -0 app/main.cpp
M +280 -52 app/tabbar.cpp
M +17 -1 app/tabbar.h
--- trunk/extragear/utils/yakuake/ChangeLog #941034:941035
@@ -7,6 +7,7 @@
* Added an option to open the application window after program start.
* Slightly improved options layout on the Behavior page of the configura-
tion dialog.
+* Added support for moving tabs on the tab bar by drag and drop.
Changes in 2.9.4:
--- trunk/extragear/utils/yakuake/app/main.cpp #941034:941035
@@ -59,6 +59,8 @@
ki18nc("@info:credit", "Project Founder, Default skin (Inactive)"));
aboutData.addCredit(ki18nc("@info:credit", "Daniel 'suslik' D."),
ki18nc("@info:credit", "Plastik skin"), "dd@accentsolution.com");
+ aboutData.addCredit(ki18nc("@info:credit", "Juan Carlos Torres"),
+ ki18nc("@info:credit", "Tab bar drag and drop support"), \
"carlosdgtorres@gmail.com");
KCmdLineArgs::init(argc, argv, &aboutData);
--- trunk/extragear/utils/yakuake/app/tabbar.cpp #941034:941035
@@ -33,7 +33,11 @@
#include <QToolButton>
#include <QWheelEvent>
+#include <QMimeData>
+#include <QDrag>
+#include <QLabel>
+
TabBar::TabBar(MainWindow* mainWindow) : QWidget(mainWindow)
{
QDBusConnection::sessionBus().registerObject("/yakuake/tabs", this, \
QDBusConnection::ExportScriptableSlots); @@ -46,6 +50,8 @@
m_mousePressed = false;
m_mousePressedIndex = -1;
+
+ m_dropIndicator = 0;
m_mainWindow = mainWindow;
m_skin = mainWindow->skin();
@@ -78,6 +84,8 @@
connect(m_lineEdit, SIGNAL(editingFinished()), m_lineEdit, SLOT(hide()));
connect(m_lineEdit, SIGNAL(returnPressed()), this, SLOT(renameTab()));
+
+ setAcceptDrops(true);
}
TabBar::~TabBar()
@@ -179,63 +187,16 @@
QPainter painter(this);
painter.setPen(m_skin->tabBarTextColor());
- QString title;
- int sessionId;
- bool selected;
int x = m_skin->tabBarPosition().x();
int y = m_skin->tabBarPosition().y();
- QFont font = KGlobalSettings::generalFont();
- int textWidth = 0;
m_tabWidths.clear();
-
+
QRect tabsClipRect(x, y, m_closeTabButton->x() - x, height() - y);
painter.setClipRect(tabsClipRect);
for (int index = 0; index < m_tabs.size(); ++index)
{
- sessionId = m_tabs.at(index);
- selected = (sessionId == m_selectedSessionId);
- title = m_tabTitles[sessionId];
-
- if (selected)
- {
- painter.drawPixmap(x, y, m_skin->tabBarSelectedLeftCornerImage());
- x += m_skin->tabBarSelectedLeftCornerImage().width();
- }
- else if (index != m_tabs.indexOf(m_selectedSessionId) + 1)
- {
- painter.drawPixmap(x, y, m_skin->tabBarSeparatorImage());
- x += m_skin->tabBarSeparatorImage().width();
- }
-
- if (selected) font.setBold(true);
- else font.setBold(false);
-
- painter.setFont(font);
-
- QFontMetrics fontMetrics(font);
- textWidth = fontMetrics.width(title) + 10;
-
- if (selected)
- painter.drawTiledPixmap(x, y, textWidth, height(), \
m_skin->tabBarSelectedBackgroundImage());
- else
- painter.drawTiledPixmap(x, y, textWidth, height(), \
m_skin->tabBarUnselectedBackgroundImage());
-
- painter.drawText(x, y, textWidth + 1, height() + 2, Qt::AlignHCenter | \
Qt::AlignVCenter, title);
-
- x += textWidth;
-
- if (selected)
- {
- painter.drawPixmap(x, m_skin->tabBarPosition().y(), \
m_skin->tabBarSelectedRightCornerImage());
- x += m_skin->tabBarSelectedRightCornerImage().width();
- }
- else if (index != m_tabs.indexOf(m_selectedSessionId) - 1)
- {
- painter.drawPixmap(x, m_skin->tabBarPosition().y(), \
m_skin->tabBarSeparatorImage());
- x += m_skin->tabBarSeparatorImage().width();
- }
-
+ x = drawButton(x, y, index, painter);
m_tabWidths << x;
}
@@ -268,6 +229,60 @@
painter.end();
}
+int TabBar::drawButton(int x, int y, int index, QPainter& painter)
+{
+ QString title;
+ int sessionId;
+ bool selected;
+ QFont font = KGlobalSettings::generalFont();
+ int textWidth = 0;
+
+ sessionId = m_tabs.at(index);
+ selected = (sessionId == m_selectedSessionId);
+ title = m_tabTitles[sessionId];
+
+ if (selected)
+ {
+ painter.drawPixmap(x, y, m_skin->tabBarSelectedLeftCornerImage());
+ x += m_skin->tabBarSelectedLeftCornerImage().width();
+ }
+ else if (index != m_tabs.indexOf(m_selectedSessionId) + 1)
+ {
+ painter.drawPixmap(x, y, m_skin->tabBarSeparatorImage());
+ x += m_skin->tabBarSeparatorImage().width();
+ }
+
+ if (selected) font.setBold(true);
+ else font.setBold(false);
+
+ painter.setFont(font);
+
+ QFontMetrics fontMetrics(font);
+ textWidth = fontMetrics.width(title) + 10;
+
+ if (selected)
+ painter.drawTiledPixmap(x, y, textWidth, height(), \
m_skin->tabBarSelectedBackgroundImage()); + else
+ painter.drawTiledPixmap(x, y, textWidth, height(), \
m_skin->tabBarUnselectedBackgroundImage()); +
+ painter.drawText(x, y, textWidth + 1, height() + 2, Qt::AlignHCenter | \
Qt::AlignVCenter, title); +
+ x += textWidth;
+
+ if (selected)
+ {
+ painter.drawPixmap(x, m_skin->tabBarPosition().y(), \
m_skin->tabBarSelectedRightCornerImage()); + x += \
m_skin->tabBarSelectedRightCornerImage().width(); + }
+ else if (index != m_tabs.indexOf(m_selectedSessionId) - 1)
+ {
+ painter.drawPixmap(x, m_skin->tabBarPosition().y(), \
m_skin->tabBarSeparatorImage()); + x += \
m_skin->tabBarSeparatorImage().width(); + }
+
+ return x;
+}
+
int TabBar::tabAt(int x)
{
for (int index = 0; index < m_tabWidths.size(); ++index)
@@ -305,10 +320,14 @@
if (index == -1) return;
- if (event->button() == Qt::LeftButton && index != \
m_tabs.indexOf(m_selectedSessionId)) + if (event->button() == Qt::LeftButton)
{
- m_mousePressed = true;
- m_mousePressedIndex = index;
+ m_startPos = event->pos();
+ if (index != m_tabs.indexOf(m_selectedSessionId))
+ {
+ m_mousePressed = true;
+ m_mousePressedIndex = index;
+ }
}
QWidget::mousePressEvent(event);
@@ -333,6 +352,103 @@
QWidget::mouseReleaseEvent(event);
}
+void TabBar::mouseMoveEvent(QMouseEvent* event)
+{
+ if (event->buttons() & Qt::LeftButton)
+ {
+ int distance = (event->pos() - m_startPos).manhattanLength();
+ if (distance >= KGlobalSettings::dndEventDelay())
+ {
+ int index = tabAt(event->x());
+ if (index >= 0)
+ startDrag(index);
+ }
+ }
+
+ QWidget::mouseMoveEvent(event);
+}
+
+void TabBar::dragEnterEvent(QDragEnterEvent* event)
+{
+ TabBar* eventSource = qobject_cast<TabBar*>(event->source());
+
+ if (eventSource)
+ {
+ event->setDropAction(Qt::MoveAction);
+ event->acceptProposedAction();
+ }
+ else
+ {
+ drawDropIndicator(-1);
+ event->ignore();
+ }
+
+ return;
+}
+
+void TabBar::dragMoveEvent(QDragMoveEvent* event)
+{
+ TabBar* eventSource = qobject_cast<TabBar*>(event->source());
+
+ if (eventSource && event->pos().x() > m_skin->tabBarPosition().x() && \
event->pos().x() < m_closeTabButton->x()) + {
+ int index = dropIndex(event->pos());
+
+ if (index == -1)
+ index = m_tabs.size();
+
+ drawDropIndicator(index, isSameTab(event));
+
+ event->setDropAction(Qt::MoveAction);
+ event->accept();
+ }
+ else
+ {
+ drawDropIndicator(-1);
+ event->ignore();
+ }
+
+ return;
+}
+
+void TabBar::dragLeaveEvent(QDragLeaveEvent* event)
+{
+ drawDropIndicator(-1);
+ event->ignore();
+
+ return;
+}
+
+void TabBar::dropEvent(QDropEvent* event)
+{
+ drawDropIndicator(-1);
+
+ int x = event->pos().x();
+
+ if (isSameTab(event) || x < m_skin->tabBarPosition().x() || x > \
m_closeTabButton->x()) + event->ignore();
+ else
+ {
+ int targetIndex = dropIndex(event->pos());
+ int sourceSessionId = event->mimeData()->text().toInt();
+ int sourceIndex = m_tabs.indexOf(sourceSessionId);
+
+ if (targetIndex == -1)
+ targetIndex = m_tabs.size() - 1;
+ else if (targetIndex < 0)
+ targetIndex = 0;
+ else if (sourceIndex < targetIndex)
+ --targetIndex;
+
+ m_tabs.move(sourceIndex, targetIndex);
+ selectTab(sourceSessionId);
+
+ event->accept();
+ }
+
+ return;
+}
+
void TabBar::mouseDoubleClickEvent(QMouseEvent* event)
{
if (QWhatsThis::inWhatsThisMode()) return;
@@ -357,6 +473,8 @@
void TabBar::leaveEvent(QEvent* event)
{
m_mousePressed = false;
+ drawDropIndicator(-1);
+ event->ignore();
QWidget::leaveEvent(event);
}
@@ -517,6 +635,7 @@
int TabBar::sessionAtTab(int index)
{
+
for (int i = 0; i < m_tabs.size(); ++i)
{
if (i == index) return m_tabs.at(i);
@@ -571,3 +690,112 @@
return i18nc("@title:tab", "Shell No. <numid>%1</numid>", id+1);
}
}
+
+void TabBar::startDrag(int index)
+{
+ int sessionId = sessionAtTab(index);
+
+ // if (sessionId < 0) return;
+
+ int x = index ? m_tabWidths.at(index - 1) : m_skin->tabBarPosition().x();
+ int tabWidth = m_tabWidths.at(index) - x;
+ QString title = tabTitle(sessionId);
+
+ QPixmap tab(tabWidth, height());
+ tab.fill(Qt::transparent);
+
+ QPainter painter(&tab);
+ painter.initFrom(this);
+ painter.setPen(m_skin->tabBarTextColor());
+ drawButton(0, 0, index, painter);
+ painter.end();
+
+ QMimeData* mimeData = new QMimeData;
+ mimeData->setText(QVariant(sessionId).toString());
+
+ QDrag* drag = new QDrag(this);
+ drag->setMimeData(mimeData);
+ drag->setPixmap(tab);
+ drag->exec(Qt::MoveAction);
+
+ return;
+}
+
+void TabBar::drawDropIndicator(int index, bool disabled)
+{
+ const int arrowSize = 16;
+
+ if (!m_dropIndicator)
+ {
+ m_dropIndicator = new QLabel(parentWidget());
+ m_dropIndicator->resize(arrowSize, arrowSize);
+ }
+
+ QIcon::Mode drawMode = disabled ? QIcon::Disabled : QIcon::Normal;
+ m_dropIndicator->setPixmap(KIcon("arrow-down").pixmap(arrowSize, arrowSize, \
drawMode)); +
+ if (index < 0)
+ {
+ m_dropIndicator->hide();
+ return;
+ }
+
+ int temp_index;
+ if (index == m_tabs.size())
+ temp_index = index - 1;
+ else
+ temp_index = index;
+
+ int x = temp_index ? m_tabWidths.at(temp_index - 1) : \
m_skin->tabBarPosition().x(); + int tabWidth = m_tabWidths.at(temp_index) - x;
+ int y = m_skin->tabBarPosition().y();
+
+ m_dropRect = QRect(x, y - height(), tabWidth, height() - y);
+ QPoint pos;
+
+ if (index < m_tabs.size())
+ pos = m_dropRect.topLeft();
+ else
+ pos = m_dropRect.topRight();
+
+ pos.rx() -= arrowSize/2;
+
+ m_dropIndicator->move(mapTo(parentWidget(),pos));
+ m_dropIndicator->show();
+
+ return;
+}
+
+int TabBar::dropIndex(const QPoint pos)
+{
+ int index = tabAt(pos.x());
+ if (index < 0)
+ return index;
+
+ int x = index ? m_tabWidths.at(index - 1) : m_skin->tabBarPosition().x();
+ int tabWidth = m_tabWidths.at(index) - x;
+ int y = m_skin->tabBarPosition().y();
+ m_dropRect = QRect(x, y - height(), tabWidth, height() - y);
+
+ if ((pos.x()-m_dropRect.left()) > (m_dropRect.width()/2))
+ ++index;
+
+ if (index == m_tabs.size())
+ return -1;
+
+ return index;
+}
+
+bool TabBar::isSameTab(const QDropEvent* event)
+{
+ int index = dropIndex(event->pos());
+ int sourceSessionId = event->mimeData()->text().toInt();
+ int sourceIndex = m_tabs.indexOf(sourceSessionId);
+
+ bool isLastTab = (sourceIndex == m_tabs.size()-1) && (index == -1);
+
+ if ((sourceIndex == index) || (sourceIndex == index-1) || isLastTab)
+ return true;
+ else
+ return false;
+}
--- trunk/extragear/utils/yakuake/app/tabbar.h #941034:941035
@@ -27,7 +27,6 @@
#include <QHash>
#include <QWidget>
-
class MainWindow;
class Skin;
@@ -37,6 +36,7 @@
class KPushButton;
class QToolButton;
+class QLabel;
class TabBar : public QWidget
@@ -84,6 +84,11 @@
virtual void keyPressEvent(QKeyEvent*);
virtual void mousePressEvent(QMouseEvent*);
virtual void mouseReleaseEvent(QMouseEvent*);
+ virtual void mouseMoveEvent(QMouseEvent*);
+ virtual void dragMoveEvent(QDragMoveEvent*);
+ virtual void dragEnterEvent(QDragEnterEvent*);
+ virtual void dragLeaveEvent(QDragLeaveEvent*);
+ virtual void dropEvent(QDropEvent*);
virtual void mouseDoubleClickEvent(QMouseEvent*);
virtual void contextMenuEvent(QContextMenuEvent*);
virtual void leaveEvent(QEvent*);
@@ -102,6 +107,13 @@
int tabAt(int x);
void updateMoveActions(int index);
+
+ int drawButton(int x, int y, int index, QPainter& painter);
+
+ void startDrag(int index);
+ void drawDropIndicator(int index, bool disabled = false);
+ int dropIndex(const QPoint pos);
+ bool isSameTab(const QDropEvent*);
MainWindow* m_mainWindow;
Skin* m_skin;
@@ -123,6 +135,10 @@
int m_mousePressed;
int m_mousePressedIndex;
+
+ QPoint m_startPos;
+ QLabel* m_dropIndicator;
+ QRect m_dropRect;
};
#endif
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic