* drag'n'drop for tabs

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23750 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Stefan Schimanski 2008-03-15 02:13:01 +00:00
parent a98f82c292
commit cb45bc6a22
2 changed files with 156 additions and 7 deletions

View 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

View 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