]> git.lyx.org Git - lyx.git/commitdiff
* drag'n'drop for tabs
authorStefan Schimanski <sts@lyx.org>
Sat, 15 Mar 2008 02:13:01 +0000 (02:13 +0000)
committerStefan Schimanski <sts@lyx.org>
Sat, 15 Mar 2008 02:13:01 +0000 (02:13 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23750 a592a061-630c-0410-9148-cb99ea01b6c8

src/frontends/qt4/GuiWorkArea.cpp
src/frontends/qt4/GuiWorkArea.h

index 392224eef0d1c2d4c397d68cbad020b708321af6..5c6dd6787bb5ff1d5437d6f3f5d7b8490153aa78 100644 (file)
@@ -55,7 +55,6 @@
 #include <QPalette>
 #include <QPixmapCache>
 #include <QScrollBar>
-#include <QTabBar>
 #include <QTimer>
 #include <QToolButton>
 #include <QToolTip>
@@ -1196,12 +1195,18 @@ TabWorkArea::TabWorkArea(QWidget * parent)
        QObject::connect(closeBufferButton, SIGNAL(clicked()),
                this, SLOT(closeCurrentBuffer()));
        setCornerWidget(closeBufferButton, Qt::TopRightCorner);
+       
+       // setup drag'n'drop
+       QTabBar* tb = new DragTabBar;
+       connect(tb, SIGNAL(tabMoveRequested(int, int)),
+               this, SLOT(moveTab(int, int)));
+       setTabBar(tb);
 
        // make us responsible for the context menu of the tabbar
-       tabBar()->setContextMenuPolicy(Qt::CustomContextMenu);
-       connect(tabBar(), SIGNAL(customContextMenuRequested(const QPoint &)),
+       tb->setContextMenuPolicy(Qt::CustomContextMenu);
+       connect(tb, SIGNAL(customContextMenuRequested(const QPoint &)),
                this, SLOT(showContextMenu(const QPoint &)));
-
+       
        setUsesScrollButtons(true);
 }
 
@@ -1376,7 +1381,7 @@ void TabWorkArea::updateTabText(GuiWorkArea * wa)
 void TabWorkArea::showContextMenu(const QPoint & pos)
 {
        // which tab?
-       clicked_tab_ = tabBar()->tabAt(pos);
+       clicked_tab_ = static_cast<DragTabBar *>(tabBar())->tabAt(pos);
        if (clicked_tab_ != -1) {
                // show tab popup
                QMenu popup;
@@ -1391,6 +1396,113 @@ void TabWorkArea::showContextMenu(const QPoint & pos)
 }
 
 
+void TabWorkArea::moveTab(int fromIndex, int toIndex)
+{
+       QWidget * w = widget(fromIndex);
+       QIcon icon = tabIcon(fromIndex);
+       QString text = tabText(fromIndex);
+
+       setCurrentIndex(fromIndex);
+       removeTab(fromIndex);
+       insertTab(toIndex, w, icon, text);
+       setCurrentIndex(toIndex);
+}
+       
+
+DragTabBar::DragTabBar(QWidget* parent)
+       : QTabBar(parent)
+{
+       setAcceptDrops(true);
+}
+
+
+#if QT_VERSION < 0x040300
+int DragTabBar::tabAt(QPoint const & position) const
+{
+       const int max = count();
+       for (int i = 0; i < max; ++i) {
+               if (tabRect(i).contains(position))
+                       return i;
+       }
+       return -1;
+}
+#endif
+
+
+void DragTabBar::mousePressEvent(QMouseEvent * event)
+{
+       if (event->button() == Qt::LeftButton)
+               dragStartPos_ = event->pos();
+       QTabBar::mousePressEvent(event);
+}
+
+
+void DragTabBar::mouseMoveEvent(QMouseEvent * event)
+{
+       // If the left button isn't pressed anymore then return
+       if (!(event->buttons() & Qt::LeftButton))
+               return;
+       
+       // If the distance is too small then return
+       if ((event->pos() - dragStartPos_).manhattanLength()
+           < QApplication::startDragDistance())
+               return;
+
+       // did we hit something after all?
+       int tab = tabAt(dragStartPos_);
+       if (tab == -1)
+               return;
+       
+       // simulate button release to remove highlight from button
+       int i = currentIndex();
+       QMouseEvent me(QEvent::MouseButtonRelease, dragStartPos_,
+               event->button(), event->buttons(), 0);
+       QTabBar::mouseReleaseEvent(&me);
+       setCurrentIndex(i);
+       
+       // initiate Drag
+       QDrag * drag = new QDrag(this);
+       QMimeData * mimeData = new QMimeData;
+       // a crude way to distinguish tab-reodering drops from other ones
+       mimeData->setData("action", "tab-reordering") ;
+       drag->setMimeData(mimeData);
+       
+#if QT_VERSION >= 0x040300
+       // FIXME: gives garbage for tab != 0.
+       // get tab pixmap as cursor
+       QRect r = tabRect(tab);
+       QPixmap pixmap(r.size());
+       render(&pixmap, r.topLeft());
+       drag->setPixmap(pixmap);
+#endif
+       
+       drag->exec();
+}
+
+
+void DragTabBar::dragEnterEvent(QDragEnterEvent * event)
+{
+       // Only accept if it's an tab-reordering request
+       QMimeData const * m = event->mimeData();
+       QStringList formats = m->formats();
+       if (formats.contains("action") 
+           && m->data("action") == "tab-reordering")
+               event->acceptProposedAction();
+}
+
+
+void DragTabBar::dropEvent(QDropEvent * event)
+{
+       int fromIndex = tabAt(dragStartPos_);
+       int toIndex = tabAt(event->pos());
+       
+       // Tell interested objects that 
+       if (fromIndex != toIndex)
+               tabMoveRequested(fromIndex, toIndex);
+       event->acceptProposedAction();
+}
+
+
 } // namespace frontend
 } // namespace lyx
 
index 034bef285b6be7e0c6d5be56434214bacbb7da45..e380561df5f1e500d339db620450aa4afd44cbf6 100644 (file)
@@ -26,6 +26,7 @@
 #include <QMouseEvent>
 #include <QPixmap>
 #include <QResizeEvent>
+#include <QTabBar>
 #include <QTabWidget>
 #include <QTimer>
 
@@ -262,8 +263,6 @@ Q_SIGNALS:
        void lastWorkAreaRemoved();
 
 public Q_SLOTS:
-       ///
-       void on_currentTabChanged(int index);
        /// close current buffer, or the one given by \c clicked_tab_
        void closeCurrentBuffer();
        /// close current tab, or the one given by \c clicked_tab_
@@ -272,13 +271,51 @@ public Q_SLOTS:
        void updateTabText(GuiWorkArea *);
        
 private Q_SLOTS:
+       ///
+       void on_currentTabChanged(int index);
        ///
        void showContextMenu(const QPoint & pos);
+       ///
+       void moveTab(int fromIndex, int toIndex);
 
 private:
        int clicked_tab_;
 }; // TabWorkArea
 
+
+class DragTabBar : public QTabBar
+{
+       Q_OBJECT
+public:
+       ///
+       DragTabBar(QWidget * parent=0);
+
+#if QT_VERSION < 0x040300
+       ///
+       int tabAt(QPoint const & position) const;
+#endif
+
+protected:
+       ///
+       void mousePressEvent(QMouseEvent * event);
+       ///
+       void mouseMoveEvent(QMouseEvent * event);
+       ///
+       void dragEnterEvent(QDragEnterEvent * event);
+       ///
+       void dropEvent(QDropEvent * event);
+
+private:
+       ///
+       QPoint dragStartPos_;
+       ///
+       int dragCurrentIndex_;
+
+Q_SIGNALS:
+       ///
+       void tabMoveRequested(int fromIndex, int toIndex);
+};
+
 } // namespace frontend
 } // namespace lyx