19class DockTabBarPrivate
28 DockPanel *m_panel =
nullptr;
29 QWidget *m_tabsContainerWidget;
30 QBoxLayout *m_tabsLayout;
31 int m_currentIndex = -1;
34DockTabBarPrivate::DockTabBarPrivate()
38void DockTabBarPrivate::init()
42 m_tabsContainerWidget =
new QWidget();
43 m_tabsContainerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
44 m_tabsContainerWidget->setObjectName(
"tabsContainerWidget");
45 m_tabsLayout =
new QBoxLayout(QBoxLayout::LeftToRight);
46 m_tabsLayout->setContentsMargins(0, 0, 0, 0);
47 m_tabsLayout->setSpacing(0);
48 m_tabsLayout->addStretch(1);
49 m_tabsContainerWidget->setLayout(m_tabsLayout);
50 q->setWidget(m_tabsContainerWidget);
57void DockTabBarPrivate::updateTabs()
61 for (
int i = 0; i < q->count(); ++i) {
66 if (i == m_currentIndex) {
79 tab->setActive(
false);
92 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
93 setFrameStyle(QFrame::NoFrame);
94 setWidgetResizable(
true);
95 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
96 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
97 setFocusPolicy(Qt::NoFocus);
113 d->m_tabsLayout->insertWidget(index,
tab);
119 tab->installEventFilter(
this);
121 if (index <= d->m_currentIndex) {
123 }
else if (d->m_currentIndex == -1) {
136 int removeIndex = d->m_tabsLayout->indexOf(
tab);
138 newCurrentIndex = -1;
140 if (newCurrentIndex > removeIndex) {
142 }
else if (newCurrentIndex == removeIndex) {
143 newCurrentIndex = -1;
145 for (
int i = (removeIndex + 1); i <
count(); ++i) {
146 if (this->
tab(i)->isVisibleTo(
this)) {
147 newCurrentIndex = i - 1;
154 if (newCurrentIndex < 0) {
155 for (
int i = (removeIndex - 1); i >= 0; --i) {
156 if (this->
tab(i)->isVisibleTo(
this)) {
165 d->m_tabsLayout->removeWidget(
tab);
166 tab->disconnect(
this);
167 tab->removeEventFilter(
this);
169 if (newCurrentIndex != d->m_currentIndex) {
182 return d->m_tabsLayout->count() - 1;
191 return d->m_currentIndex;
200 if (d->m_currentIndex < 0 || d->m_currentIndex >= d->m_tabsLayout->count()) {
203 return qobject_cast<DockTab *>(d->m_tabsLayout->itemAt(d->m_currentIndex)->widget());
209 if (index < 0 || index >=
count()) {
213 return qobject_cast<DockTab *>(d->m_tabsLayout->itemAt(index)->widget());
228 if (!t || pos.x() < t->geometry().x()) {
233 for (
int i = 0; i < cnt; ++i) {
234 if (
tab(i)->geometry().contains(pos)) {
244 int index =
tabAt(pos);
248 return (index < 0) ? 0 : index;
259 if (index < 0 || index >=
count()) {
263 return !
tab(index)->isHidden();
290 return d->m_tabsContainerWidget->sizeHint();
300 return d->m_tabsContainerWidget->width() > width();
306 if (index == d->m_currentIndex) {
309 if (index < -1 || index > (
count() - 1)) {
310 qWarning() << Q_FUNC_INFO <<
"Invalid index" << index;
314 d->m_currentIndex = index;
326 if (index < 0 || index >=
count()) {
330 auto tab = this->
tab(index);
331 if (
tab->isHidden()) {
340 DockTab *
tab = qobject_cast<DockTab *>(sender());
344 int index = d->m_tabsLayout->indexOf(
tab);
355 DockTab *
tab = qobject_cast<DockTab *>(sender());
356 int index = d->m_tabsLayout->indexOf(
tab);
362 auto senderTab = qobject_cast<DockTab *>(sender());
363 for (
int i = 0; i <
count(); ++i) {
364 auto otherTab = this->
tab(i);
365 if (otherTab->isClosable() && !otherTab->isHidden() && otherTab != senderTab) {
375 if (otherTab->dockWidget()->isClosed()) {
385 DockTab *movingTab = qobject_cast<DockTab *>(sender());
390 int fromIndex = d->m_tabsLayout->indexOf(movingTab);
391 auto mousePos = mapFromGlobal(globalPos);
392 mousePos.rx() = qMax(0, mousePos.x());
393 mousePos.rx() = qMin(width(), mousePos.x());
396 for (
int i = 0; i <
count(); ++i) {
398 auto tabGeometry = dropTab->geometry();
399 tabGeometry.setTopLeft(d->m_tabsContainerWidget->mapToParent(tabGeometry.topLeft()));
400 tabGeometry.setBottomRight(d->m_tabsContainerWidget->mapToParent(tabGeometry.bottomRight()));
401 if (dropTab == movingTab || !dropTab->isVisibleTo(
this) || !tabGeometry.contains(mousePos)) {
405 toIndex = d->m_tabsLayout->indexOf(dropTab);
406 if (toIndex == fromIndex) {
413 d->m_tabsLayout->removeWidget(movingTab);
414 d->m_tabsLayout->insertWidget(toIndex, movingTab);
415 Q_EMIT
tabMoved(fromIndex, toIndex);
419 d->m_tabsLayout->update();
426 bool result = Super::eventFilter(watched, event);
427 DockTab *
tab = qobject_cast<DockTab *>(watched);
432 switch (event->type()) {
444 case QEvent::LayoutRequest:
466 const int direction =
event->angleDelta().y();
468 horizontalScrollBar()->setValue(horizontalScrollBar()->value() + 20);
470 horizontalScrollBar()->setValue(horizontalScrollBar()->value() - 20);
DockPanel manages multiple instances of DockWidgets.
Custom tabbar implementation for tab area that is shown on top of a dock panel widget.
void tabMoved(int from, int to)
void tabOpened(int index)
void onTabCloseRequested()
void setCurrentIndex(int index)
void insertTab(int index, DockTab *tab)
Inserts the given dock tab at the given position.
void currentChanged(int index)
virtual void wheelEvent(QWheelEvent *event) override
void tabInserted(int index)
DockTab * tab(int index) const
bool isTabOpen(int index) const
This function returns true if the tab is open, that means if it is visible to the user.
void removeTab(DockTab *tab)
void removingTab(int index)
void tabCloseRequested(int index)
int tabInsertIndexAt(const QPoint &pos) const
int tabAt(const QPoint &pos) const
Returns the tab at the given pos.
void currentChanging(int index)
void onCloseOtherTabsRequested()
void tabBarClicked(int index)
void tabClosed(int index)
int currentIndex() const
Returns the current index or -1 if no tab is selected
void closeTab(int index)
This function will close the tab given in index param.
DockTab * currentTab() const
Returns the current tab or a nullptr if no tab is selected.
virtual QSize minimumSizeHint() const override
Overrides the minimumSizeHint() function of QScrollArea The minimumSizeHint() is bigger than the size...
void onTabWidgetMoved(const QPoint &globalPos)
virtual QSize sizeHint() const override
The function provides a sizeHint that matches the height of the internal viewport.
virtual bool eventFilter(QObject *watched, QEvent *event) override
bool areTabsOverflowing() const
This function returns true, if the tabs need more space than the size of the tab bar.
void elidedChanged(bool elided)
Qx::DockDragState dragState() const
#define QX_DOCK_PRINT(s)
Copyleft (C) 2024 maminjie canpool@163.com SPDX-License-Identifier: MulanPSL-2.0
@ DockTabDefaultInsertIndex
#define QX_INIT_PRIVATE(Class)
#define QX_DECLARE_PUBLIC(Class)
#define QX_FINI_PRIVATE()
#define QX_DOCK_END_NAMESPACE
#define QX_DOCK_BEGIN_NAMESPACE