[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