mirror of
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
synced 2024-11-15 13:15:43 +08:00
Implements tab-movement, changing the order of tabs by dragging with mouse.
This commit is contained in:
parent
863d3233ad
commit
bc14d9255f
@ -42,6 +42,7 @@ static void deleteEmptySplitter(ContainerWidget* container)
|
||||
SectionTitleWidget::SectionTitleWidget(SectionContent::RefPtr content, QWidget* parent) :
|
||||
QFrame(parent),
|
||||
_content(content),
|
||||
_tabMoving(false),
|
||||
_activeTab(false)
|
||||
{
|
||||
auto l = new QBoxLayout(QBoxLayout::LeftToRight);
|
||||
@ -83,10 +84,7 @@ void SectionTitleWidget::mousePressEvent(QMouseEvent* ev)
|
||||
void SectionTitleWidget::mouseReleaseEvent(QMouseEvent* ev)
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO << ev->pos();
|
||||
if (!_dragStartPos.isNull())
|
||||
{
|
||||
emit clicked();
|
||||
}
|
||||
SectionWidget* section = NULL;
|
||||
|
||||
// Drop contents of FloatingWidget into SectionWidget.
|
||||
if (_fw)
|
||||
@ -153,9 +151,28 @@ void SectionTitleWidget::mouseReleaseEvent(QMouseEvent* ev)
|
||||
}
|
||||
}
|
||||
}
|
||||
// End of tab moving, change order now
|
||||
else if (_tabMoving
|
||||
&& (section = findParentSectionWidget(this)) != NULL)
|
||||
{
|
||||
qDebug() << "Stop tab move";
|
||||
|
||||
// Find tab under mouse
|
||||
QPoint pos = ev->globalPos();
|
||||
pos = section->mapFromGlobal(pos);
|
||||
const int fromIndex = section->indexOfContent(_content);
|
||||
const int toIndex = section->indexOfContentByTitlePos(pos, this);
|
||||
qDebug() << "from" << fromIndex << "to" << toIndex;
|
||||
section->moveContent(fromIndex, toIndex);
|
||||
section->layout()->update();
|
||||
}
|
||||
|
||||
if (!_dragStartPos.isNull())
|
||||
emit clicked();
|
||||
|
||||
// Reset
|
||||
_dragStartPos = QPoint();
|
||||
_tabMoving = false;
|
||||
hideDropOverlay();
|
||||
QFrame::mouseReleaseEvent(ev);
|
||||
}
|
||||
@ -207,15 +224,11 @@ void SectionTitleWidget::mouseMoveEvent(QMouseEvent* ev)
|
||||
ev->accept();
|
||||
return;
|
||||
}
|
||||
// Begin to drag title inside the title area to switch its position inside the SectionWidget.
|
||||
else if (!_dragStartPos.isNull() && (ev->buttons() & Qt::LeftButton)
|
||||
&& (section = findParentSectionWidget(this)) != NULL && section->titleAreaGeometry().contains(section->mapFromGlobal(ev->globalPos())))
|
||||
{
|
||||
// qDebug() << "Move inside title area" << ev->pos();
|
||||
}
|
||||
// Begin to drag/float the SectionContent.
|
||||
else if (!_dragStartPos.isNull() && (ev->buttons() & Qt::LeftButton) && (ev->globalPos() - _dragStartPos).manhattanLength() >= QApplication::startDragDistance()
|
||||
&& (section = findParentSectionWidget(this)) != NULL)
|
||||
else if (!_fw && !_dragStartPos.isNull() && (ev->buttons() & Qt::LeftButton)
|
||||
//&& (ev->globalPos() - _dragStartPos).manhattanLength() >= QApplication::startDragDistance()
|
||||
&& (section = findParentSectionWidget(this)) != NULL
|
||||
&& !section->titleAreaGeometry().contains(section->mapFromGlobal(ev->globalPos())))
|
||||
{
|
||||
// Create floating widget.
|
||||
auto data = section->take(_content->uid(), false);
|
||||
@ -241,6 +254,27 @@ void SectionTitleWidget::mouseMoveEvent(QMouseEvent* ev)
|
||||
ev->accept();
|
||||
return;
|
||||
}
|
||||
// Handle movement of this tab
|
||||
else if (_tabMoving
|
||||
&& (section = findParentSectionWidget(this)) != NULL)
|
||||
{
|
||||
int left, top, right, bottom;
|
||||
getContentsMargins(&left, &top, &right, &bottom);
|
||||
QPoint moveToPos = mapToParent(ev->pos()) - _dragStartPos;
|
||||
moveToPos.setY(0 + top);
|
||||
move(moveToPos);
|
||||
ev->accept();
|
||||
}
|
||||
// Begin to drag title inside the title area to switch its position inside the SectionWidget.
|
||||
else if (!_dragStartPos.isNull() && (ev->buttons() & Qt::LeftButton)
|
||||
&& (section = findParentSectionWidget(this)) != NULL
|
||||
&& section->titleAreaGeometry().contains(section->mapFromGlobal(ev->globalPos())))
|
||||
{
|
||||
// Raise current title-widget above other tabs
|
||||
_tabMoving = true;
|
||||
raise();
|
||||
ev->accept();
|
||||
}
|
||||
QFrame::mouseMoveEvent(ev);
|
||||
}
|
||||
|
||||
|
@ -19,9 +19,15 @@ class SectionTitleWidget : public QFrame
|
||||
friend class SectionWidget;
|
||||
|
||||
SectionContent::RefPtr _content;
|
||||
|
||||
// Drag & Drop (Floating)
|
||||
QPointer<FloatingWidget> _fw;
|
||||
QPoint _dragStartPos;
|
||||
|
||||
// Drag & Drop (Title/Tabs)
|
||||
bool _tabMoving;
|
||||
|
||||
// Property values
|
||||
bool _activeTab;
|
||||
|
||||
public:
|
||||
|
@ -189,9 +189,52 @@ InternalContentData SectionWidget::take(int uid, bool del)
|
||||
return data;
|
||||
}
|
||||
|
||||
int SectionWidget::indexOfContent(SectionContent::RefPtr c) const
|
||||
{
|
||||
return _contents.indexOf(c);
|
||||
}
|
||||
|
||||
int SectionWidget::indexOfContentByTitlePos(const QPoint& p, QWidget* exclude) const
|
||||
{
|
||||
int index = -1;
|
||||
for (int i = 0; i < _sectionTitles.size(); ++i)
|
||||
{
|
||||
if (_sectionTitles[i]->geometry().contains(p) && (exclude == NULL || _sectionTitles[i] != exclude))
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
void SectionWidget::moveContent(int from, int to)
|
||||
{
|
||||
if (from >= _contents.size() || from < 0 || to >= _contents.size() || to < 0 || from == to)
|
||||
{
|
||||
qCritical() << "Invalid index for tab movement" << from << to;
|
||||
return;
|
||||
}
|
||||
|
||||
SectionContent::RefPtr sc = _contents.at(from);
|
||||
_contents.move(from, to);
|
||||
_sectionTitles.move(from, to);
|
||||
_sectionContents.move(from, to);
|
||||
|
||||
QLayoutItem* liFrom = NULL;
|
||||
|
||||
liFrom = _tabsLayout->takeAt(from);
|
||||
_tabsLayout->insertItem(to, liFrom);
|
||||
|
||||
liFrom = _contentsLayout->takeAt(from);
|
||||
_contentsLayout->insertWidget(to, liFrom->widget());
|
||||
delete liFrom;
|
||||
}
|
||||
|
||||
void SectionWidget::setCurrentIndex(int index)
|
||||
{
|
||||
// Set active TAB.
|
||||
qDebug() << Q_FUNC_INFO << index;
|
||||
for (int i = 0; i < _tabsLayout->count(); ++i)
|
||||
{
|
||||
auto item = _tabsLayout->itemAt(i);
|
||||
|
@ -39,6 +39,10 @@ public:
|
||||
void addContent(SectionContent::RefPtr c);
|
||||
void addContent(const InternalContentData& data, bool autoActivate);
|
||||
InternalContentData take(int uid, bool del = true);
|
||||
int indexOfContent(SectionContent::RefPtr c) const;
|
||||
int indexOfContentByTitlePos(const QPoint& pos, QWidget* exclude = NULL) const;
|
||||
|
||||
void moveContent(int from, int to);
|
||||
|
||||
public slots:
|
||||
void setCurrentIndex(int index);
|
||||
|
@ -39,27 +39,27 @@ int main(int argc, char *argv[])
|
||||
Q_INIT_RESOURCE(ads);
|
||||
|
||||
// Development style.
|
||||
// a.setStyleSheet(""
|
||||
// " QSplitter::handle { border: 1px solid #000000; background: #000000; } "
|
||||
// " ads--ContainerWidget { border: 1px solid #ff0000; background: #FFE6E6; } "
|
||||
// " ads--SectionWidget { border: 1px solid #00ff00; background: #E6FFE6; } "
|
||||
// " ads--SectionTitleWidget { border: 1px solid #0000ff; background: #E6E6FF; } "
|
||||
// " ads--SectionTitleWidget[activeTab=\"true\"] { border: 1px solid #0000ff; background: #9696FF; } "
|
||||
// " ads--SectionContentWidget { border: 1px solid #FFFF00; background: #FFFFE6; } "
|
||||
// );
|
||||
a.setStyleSheet(""
|
||||
" QSplitter::handle { border: 1px solid #000000; background: #000000; } "
|
||||
" ads--ContainerWidget { border: 1px solid #ff0000; background: #FFE6E6; padding: 6px; } "
|
||||
" ads--SectionWidget { border: 1px solid #00ff00; background: #E6FFE6; padding: 6px; } "
|
||||
" ads--SectionTitleWidget { border: 1px solid #0000ff; background: #E6E6FF; padding: 6px; } "
|
||||
" ads--SectionTitleWidget[activeTab=\"true\"] { border: 1px solid #0000ff; background: #9696FF; padding: 6px; } "
|
||||
" ads--SectionContentWidget { border: 1px solid #FFFF00; background: #FFFFE6; padding: 6px; } "
|
||||
);
|
||||
|
||||
// PARTsolutions style.
|
||||
a.setStyleSheet(""
|
||||
" QSplitter::handle:vertical { image: url(:/img/splitter-horizontal.png); } "
|
||||
" QSplitter::handle:horizontal { image: url(:/img/splitter-vertical.png); } "
|
||||
" ads--ContainerWidget { border: 0; background: #9ab6ca; } "
|
||||
" ads--SectionWidget { border-width: 1px; border-color: #ffffff; border-style: solid; background: #7c9eb3; padding: 0; margin: 0; } "
|
||||
" ads--SectionTitleWidget { border-right: 1px solid #E7F3F8; background: #7c9eb3; } "
|
||||
" ads--SectionTitleWidget[activeTab=\"true\"] { border: 1px solid #E7F3F8; background: #E7F3F8; } "
|
||||
" ads--SectionTitleWidget IconTitleWidget QLabel { color: #000000; } "
|
||||
" ads--SectionContentWidget { border: 0px solid #E7F3F8; background: #ffffff; } "
|
||||
" ads--FloatingWidget QPushButton { background: #E7F3F8; } "
|
||||
);
|
||||
// a.setStyleSheet(""
|
||||
// " QSplitter::handle:vertical { image: url(:/img/splitter-horizontal.png); } "
|
||||
// " QSplitter::handle:horizontal { image: url(:/img/splitter-vertical.png); } "
|
||||
// " ads--ContainerWidget { border: 0; background: #9ab6ca; } "
|
||||
// " ads--SectionWidget { border-width: 1px; border-color: #ffffff; border-style: solid; background: #7c9eb3; padding: 0; margin: 0; } "
|
||||
// " ads--SectionTitleWidget { border-right: 1px solid #E7F3F8; background: #7c9eb3; } "
|
||||
// " ads--SectionTitleWidget[activeTab=\"true\"] { border: 1px solid #E7F3F8; background: #E7F3F8; } "
|
||||
// " ads--SectionTitleWidget IconTitleWidget QLabel { color: #000000; } "
|
||||
// " ads--SectionContentWidget { border: 0px solid #E7F3F8; background: #ffffff; } "
|
||||
// " ads--FloatingWidget QPushButton { background: #E7F3F8; } "
|
||||
// );
|
||||
|
||||
MainWindow mw;
|
||||
resizeWidgetPerCent(&mw, 60, 80);
|
||||
|
Loading…
Reference in New Issue
Block a user