00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "qxttabbar.h"
00026 #include <QDragMoveEvent>
00027 #include <QApplication>
00028 #include <QTabWidget>
00029 #include <QMimeData>
00030 #include <QIcon>
00031
00032 class QxtTabBarPrivate : public QxtPrivate<QxtTabBar>
00033 {
00034 public:
00035 QXT_DECLARE_PUBLIC(QxtTabBar);
00036
00037 QxtTabBarPrivate();
00038
00039 enum MovementAction
00040 {
00041 PressAction,
00042 MoveAction,
00043 DragAction,
00044 DropAction,
00045 };
00046
00047 int tabAt(const QPoint& position, MovementAction action) const;
00048 bool contains(const QRect& rect, const QPoint& position, MovementAction action) const;
00049
00050 bool shouldMove(const QPoint& pos, int fromIndex, int toIndex, MovementAction action) const;
00051 bool moveTab(const QPoint& pos, int fromIndex, int toIndex, MovementAction action);
00052
00053 struct Tab
00054 {
00055 QIcon icon;
00056 QVariant data;
00057 QString text;
00058 QColor textColor;
00059 QString toolTip;
00060 QString whatsThis;
00061 };
00062 Tab saveTab(int index) const;
00063 void restoreTab(int index, const Tab& tab);
00064
00065 int movingTab;
00066 QPoint pressPoint;
00067 QxtTabBar::TabMovementMode mode;
00068 };
00069
00070 QxtTabBarPrivate::QxtTabBarPrivate() : movingTab(-1), mode(QxtTabBar::NoMovement)
00071 {
00072 }
00073
00074 int QxtTabBarPrivate::tabAt(const QPoint& position, MovementAction action) const
00075 {
00076 const int count = qxt_p().count();
00077 for (int i = 0; i < count; ++i)
00078 {
00079 if (contains(qxt_p().tabRect(i), position, action))
00080 {
00081 return i;
00082 }
00083 }
00084 return -1;
00085 }
00086
00087 bool QxtTabBarPrivate::contains(const QRect& rect, const QPoint& position, MovementAction action) const
00088 {
00089 if (action != PressAction)
00090 {
00091 switch (qxt_p().shape())
00092 {
00093 case QTabBar::RoundedNorth:
00094 case QTabBar::RoundedSouth:
00095 case QTabBar::TriangularNorth:
00096 case QTabBar::TriangularSouth:
00097 return position.x() >= rect.x() && position.x() <= rect.x() + rect.width();
00098
00099 case QTabBar::RoundedWest:
00100 case QTabBar::RoundedEast:
00101 case QTabBar::TriangularWest:
00102 case QTabBar::TriangularEast:
00103 return position.y() >= rect.y() && position.y() <= rect.y() + rect.height();
00104
00105 default:
00106 qWarning("QTabBarPrivate: unknown QTabBar::Shape %i", qxt_p().shape());
00107 return false;
00108 }
00109 }
00110 else
00111 {
00112 return rect.contains(position);
00113 }
00114 }
00115
00116 bool QxtTabBarPrivate::shouldMove(const QPoint& pos, int fromIndex, int toIndex, MovementAction action) const
00117 {
00118 if (fromIndex == -1 || toIndex == -1 || fromIndex == toIndex)
00119 return false;
00120
00121 QRect sourceRect = qxt_p().tabRect(fromIndex);
00122 QRect targetRect = qxt_p().tabRect(toIndex);
00123
00124 QRect finalRect;
00125 if (action == DropAction)
00126 {
00127 finalRect = targetRect;
00128 }
00129 else
00130 {
00131 finalRect = sourceRect;
00132 switch (qxt_p().shape())
00133 {
00134 case QTabBar::RoundedNorth:
00135 case QTabBar::RoundedSouth:
00136 case QTabBar::TriangularNorth:
00137 case QTabBar::TriangularSouth:
00138 if (qxt_p().layoutDirection() == Qt::LeftToRight && sourceRect.x() < targetRect.x())
00139 finalRect.moveRight(targetRect.right());
00140 else
00141 finalRect.moveLeft(targetRect.left());
00142 break;
00143
00144 case QTabBar::RoundedWest:
00145 case QTabBar::RoundedEast:
00146 case QTabBar::TriangularWest:
00147 case QTabBar::TriangularEast:
00148 if (sourceRect.y() < targetRect.y())
00149 finalRect.moveBottom(targetRect.bottom());
00150 else
00151 finalRect.moveTop(targetRect.top());
00152 break;
00153
00154 default:
00155 qWarning("QTabBarPrivate: unknown QTabBar::Shape %i", qxt_p().shape());
00156 return false;
00157 }
00158 }
00159
00160 return contains(finalRect, pos, action);
00161 }
00162
00163 bool QxtTabBarPrivate::moveTab(const QPoint& pos, int fromIndex, int toIndex, MovementAction action)
00164 {
00165 QxtTabBar* tabBar = &qxt_p();
00166
00167 if (shouldMove(pos, fromIndex, toIndex, action))
00168 {
00169 Tab tab = saveTab(fromIndex);
00170
00171
00172 QTabWidget* tabWidget = qobject_cast<QTabWidget*>(tabBar->parent());
00173 if (tabWidget)
00174 {
00175 QWidget* widget = tabWidget->widget(fromIndex);
00176 tabWidget->removeTab(fromIndex);
00177 tabWidget->insertTab(toIndex, widget, "");
00178 tabWidget->setCurrentIndex(toIndex);
00179 }
00180 else
00181 {
00182 tabBar->removeTab(fromIndex);
00183 tabBar->insertTab(toIndex, "");
00184 tabBar->setCurrentIndex(toIndex);
00185 }
00186
00187 restoreTab(toIndex, tab);
00188 return true;
00189 }
00190
00191 return false;
00192 }
00193
00194 QxtTabBarPrivate::Tab QxtTabBarPrivate::saveTab(int index) const
00195 {
00196 Tab tab;
00197 const QTabBar* tabBar = &qxt_p();
00198 tab.icon = tabBar->tabIcon(index);
00199 tab.data = tabBar->tabData(index);
00200 tab.text = tabBar->tabText(index);
00201 tab.textColor = tabBar->tabTextColor(index);
00202 tab.toolTip = tabBar->tabToolTip(index);
00203 tab.whatsThis = tabBar->tabWhatsThis(index);
00204 return tab;
00205 }
00206
00207 void QxtTabBarPrivate::restoreTab(int index, const Tab& tab)
00208 {
00209 QTabBar* tabBar = &qxt_p();
00210 tabBar->setTabIcon(index, tab.icon);
00211 tabBar->setTabData(index, tab.data);
00212 tabBar->setTabText(index, tab.text);
00213 tabBar->setTabTextColor(index, tab.textColor);
00214 tabBar->setTabToolTip(index, tab.toolTip);
00215 tabBar->setTabWhatsThis(index, tab.whatsThis);
00216 }
00217
00243 QxtTabBar::QxtTabBar(QWidget* parent)
00244 : QTabBar(parent)
00245 {
00246 QXT_INIT_PRIVATE(QxtTabBar);
00247 }
00248
00249 QxtTabBar::~QxtTabBar() {}
00250
00260 QxtTabBar::TabMovementMode QxtTabBar::tabMovementMode() const
00261 {
00262 return qxt_d().mode;
00263 }
00264
00265 void QxtTabBar::setTabMovementMode(TabMovementMode mode)
00266 {
00267 qxt_d().mode = mode;
00268 if (mode == DragDropMovement)
00269 setAcceptDrops(true);
00270 }
00271
00275 void QxtTabBar::mousePressEvent(QMouseEvent* event)
00276 {
00277 QTabBar::mousePressEvent(event);
00278 if (event->button() == Qt::LeftButton)
00279 {
00280 qxt_d().movingTab = qxt_d().tabAt(event->pos(), QxtTabBarPrivate::PressAction);
00281 qxt_d().pressPoint = event->pos();
00282 }
00283 }
00284
00288 void QxtTabBar::mouseMoveEvent(QMouseEvent* event)
00289 {
00290 QTabBar::mouseMoveEvent(event);
00291
00292 if (qxt_d().movingTab == -1)
00293 return;
00294
00295 if (qxt_d().mode == InPlaceMovement)
00296 {
00297 int hoverTab = qxt_d().tabAt(event->pos(), QxtTabBarPrivate::MoveAction);
00298 if (qxt_d().moveTab(event->pos(), qxt_d().movingTab, hoverTab, QxtTabBarPrivate::MoveAction))
00299 {
00300 emit tabMoved(qxt_d().movingTab, hoverTab);
00301 qxt_d().movingTab = hoverTab;
00302 event->accept();
00303 }
00304 }
00305 else if (qxt_d().mode == DragDropMovement)
00306 {
00307 if ((event->pos() - qxt_d().pressPoint).manhattanLength()
00308 >= QApplication::startDragDistance())
00309 {
00310 QDrag* drag = new QDrag(this);
00311 QMimeData* mimeData = new QMimeData;
00312
00313
00314 mimeData->setData("action", "tabMovement");
00315 drag->setMimeData(mimeData);
00316 drag->start();
00317 }
00318 }
00319 }
00320
00324 void QxtTabBar::mouseReleaseEvent(QMouseEvent* event)
00325 {
00326 QTabBar::mouseReleaseEvent(event);
00327 qxt_d().movingTab = -1;
00328 }
00329
00333 void QxtTabBar::dragEnterEvent(QDragEnterEvent* event)
00334 {
00335
00336 const QMimeData* mimeData = event->mimeData();
00337 QStringList formats = mimeData->formats();
00338 if (formats.contains("action") && (mimeData->data("action") == "tabMovement"))
00339 event->acceptProposedAction();
00340 else
00341 QTabBar::dragEnterEvent(event);
00342 }
00343
00344 void QxtTabBar::dragMoveEvent(QDragMoveEvent* event)
00345 {
00346
00347 const QMimeData* mimeData = event->mimeData();
00348 QStringList formats = mimeData->formats();
00349 if (formats.contains("action") && (mimeData->data("action") == "tabMovement"))
00350 event->acceptProposedAction();
00351 else
00352 QTabBar::dragMoveEvent(event);
00353 }
00354
00358 void QxtTabBar::dropEvent(QDropEvent* event)
00359 {
00360
00361 const QMimeData* mimeData = event->mimeData();
00362 QStringList formats = mimeData->formats();
00363 if (formats.contains("action") && (mimeData->data("action") == "tabMovement"))
00364 {
00365 int dropTab = qxt_d().tabAt(event->pos(), QxtTabBarPrivate::DropAction);
00366 if (qxt_d().moveTab(event->pos(), qxt_d().movingTab, dropTab, QxtTabBarPrivate::DropAction))
00367 {
00368 emit tabMoved(qxt_d().movingTab, dropTab);
00369 qxt_d().movingTab = -1;
00370 event->acceptProposedAction();
00371 }
00372 }
00373 else
00374 {
00375 QTabBar::dropEvent(event);
00376 }
00377 }