2017-03-23 17:23:53 +08:00
|
|
|
/*******************************************************************************
|
2017-06-10 04:04:02 +08:00
|
|
|
** Qt Advanced Docking System
|
2017-03-23 17:23:53 +08:00
|
|
|
** Copyright (C) 2017 Uwe Kindler
|
2017-06-10 04:04:02 +08:00
|
|
|
**
|
|
|
|
** This library is free software; you can redistribute it and/or
|
|
|
|
** modify it under the terms of the GNU Lesser General Public
|
|
|
|
** License as published by the Free Software Foundation; either
|
|
|
|
** version 2.1 of the License, or (at your option) any later version.
|
|
|
|
**
|
|
|
|
** This library is distributed in the hope that it will be useful,
|
2017-03-23 17:23:53 +08:00
|
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2017-06-10 04:04:02 +08:00
|
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
** Lesser General Public License for more details.
|
|
|
|
**
|
|
|
|
** You should have received a copy of the GNU Lesser General Public
|
|
|
|
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
2017-03-23 17:23:53 +08:00
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
/// \file DockAreaWidget.cpp
|
|
|
|
/// \author Uwe Kindler
|
|
|
|
/// \date 24.02.2017
|
|
|
|
/// \brief Implementation of CDockAreaWidget class
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
// INCLUDES
|
|
|
|
//============================================================================
|
2018-08-24 19:41:58 +08:00
|
|
|
#include <DockWidgetTab.h>
|
2017-03-23 17:23:53 +08:00
|
|
|
#include "DockAreaWidget.h"
|
|
|
|
|
|
|
|
#include <QStackedLayout>
|
|
|
|
#include <QScrollBar>
|
|
|
|
#include <QScrollArea>
|
|
|
|
#include <QWheelEvent>
|
|
|
|
#include <QStyle>
|
|
|
|
#include <QPushButton>
|
|
|
|
#include <QDebug>
|
|
|
|
#include <QMenu>
|
|
|
|
#include <QSplitter>
|
2017-12-30 01:18:16 +08:00
|
|
|
#include <QXmlStreamWriter>
|
2018-09-07 17:10:14 +08:00
|
|
|
#include <QVector>
|
2017-03-23 17:23:53 +08:00
|
|
|
|
|
|
|
|
|
|
|
#include "DockContainerWidget.h"
|
|
|
|
#include "DockWidget.h"
|
|
|
|
#include "FloatingDockContainer.h"
|
|
|
|
#include "DockManager.h"
|
|
|
|
#include "DockOverlay.h"
|
2018-08-24 19:41:58 +08:00
|
|
|
#include "DockAreaTabBar.h"
|
2017-03-23 17:23:53 +08:00
|
|
|
|
2018-09-07 17:10:14 +08:00
|
|
|
#include <iostream>
|
|
|
|
|
2017-03-23 17:23:53 +08:00
|
|
|
|
|
|
|
namespace ads
|
|
|
|
{
|
|
|
|
static const char* const INDEX_PROPERTY = "index";
|
|
|
|
static const char* const ACTION_PROPERTY = "action";
|
2018-09-07 17:10:14 +08:00
|
|
|
static const char* const DOCKWIDGET_PROPERTY = "dockwidget";
|
2017-03-23 17:23:53 +08:00
|
|
|
static const int APPEND = -1;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Private data class of CDockAreaWidget class (pimpl)
|
|
|
|
*/
|
|
|
|
struct DockAreaWidgetPrivate
|
|
|
|
{
|
|
|
|
CDockAreaWidget* _this;
|
|
|
|
QBoxLayout* Layout;
|
|
|
|
QFrame* TitleBar;
|
|
|
|
QBoxLayout* TopLayout;
|
|
|
|
QStackedLayout* ContentsLayout;
|
2018-08-24 19:41:58 +08:00
|
|
|
CDockAreaTabBar* TabBar;
|
2017-03-23 17:23:53 +08:00
|
|
|
QWidget* TabsContainerWidget;
|
|
|
|
QBoxLayout* TabsLayout;
|
|
|
|
QPushButton* TabsMenuButton;
|
|
|
|
QPushButton* CloseButton;
|
|
|
|
int TabsLayoutInitCount;
|
|
|
|
CDockManager* DockManager = nullptr;
|
2018-09-07 17:10:14 +08:00
|
|
|
QVector<CDockWidget*> OpenDockWidgets;
|
|
|
|
bool MenuOutdated = true;
|
2017-03-23 17:23:53 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Private data constructor
|
|
|
|
*/
|
|
|
|
DockAreaWidgetPrivate(CDockAreaWidget* _public);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates the layout for top area with tabs and close button
|
|
|
|
*/
|
|
|
|
void createTabBar();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the dock widget with the given index
|
|
|
|
*/
|
|
|
|
CDockWidget* dockWidgetAt(int index)
|
|
|
|
{
|
|
|
|
return dynamic_cast<CDockWidget*>(ContentsLayout->widget(index));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convenience function to ease title widget access by index
|
|
|
|
*/
|
2018-08-24 19:41:58 +08:00
|
|
|
CDockWidgetTab* titleWidgetAt(int index)
|
2017-03-23 17:23:53 +08:00
|
|
|
{
|
2018-09-07 17:10:14 +08:00
|
|
|
return dockWidgetAt(index)->tabWidget();
|
2017-03-23 17:23:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a tabs menu entry for the given dock widget
|
|
|
|
* If menu is 0, a menu entry is added to the menu of the TabsMenuButton
|
|
|
|
* member. If menu is a valid menu pointer, the entry will be added to
|
|
|
|
* the given menu
|
|
|
|
*/
|
|
|
|
void addTabsMenuEntry(CDockWidget* DockWidget, int Index = -1, QMenu* menu = 0);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the tab action of the given dock widget
|
|
|
|
*/
|
|
|
|
QAction* dockWidgetTabAction(CDockWidget* DockWidget) const
|
|
|
|
{
|
|
|
|
return qvariant_cast<QAction*>(DockWidget->property(ACTION_PROPERTY));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the index of the given dock widget
|
|
|
|
*/
|
|
|
|
int dockWidgetIndex(CDockWidget* DockWidget) const
|
|
|
|
{
|
|
|
|
return DockWidget->property(INDEX_PROPERTY).toInt();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update the tabs menu if dock widget order changed or if dock widget has
|
|
|
|
* been removed
|
|
|
|
*/
|
2018-09-07 17:10:14 +08:00
|
|
|
void markTabsMenuOutdated();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the tabs menu if it is outdated
|
|
|
|
*/
|
2017-03-23 17:23:53 +08:00
|
|
|
void updateTabsMenu();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the tab bar visibility depending on the number of dock widgets
|
|
|
|
* in this area
|
|
|
|
*/
|
|
|
|
void updateTabBar();
|
|
|
|
};
|
|
|
|
// struct DockAreaWidgetPrivate
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
DockAreaWidgetPrivate::DockAreaWidgetPrivate(CDockAreaWidget* _public) :
|
|
|
|
_this(_public)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void DockAreaWidgetPrivate::createTabBar()
|
|
|
|
{
|
|
|
|
TitleBar = new QFrame(_this);
|
|
|
|
TitleBar->setObjectName("dockAreaTitleBar");
|
|
|
|
TopLayout = new QBoxLayout(QBoxLayout::LeftToRight);
|
|
|
|
TopLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
TopLayout->setSpacing(0);
|
|
|
|
TitleBar->setLayout(TopLayout);
|
|
|
|
Layout->addWidget(TitleBar);
|
|
|
|
|
2018-08-24 19:41:58 +08:00
|
|
|
TabBar = new CDockAreaTabBar(_this);
|
|
|
|
TopLayout->addWidget(TabBar, 1);
|
2017-03-23 17:23:53 +08:00
|
|
|
|
|
|
|
TabsContainerWidget = new QWidget();
|
|
|
|
TabsContainerWidget->setObjectName("tabsContainerWidget");
|
2018-08-24 19:41:58 +08:00
|
|
|
TabBar->setWidget(TabsContainerWidget);
|
2017-03-23 17:23:53 +08:00
|
|
|
|
|
|
|
TabsLayout = new QBoxLayout(QBoxLayout::LeftToRight);
|
|
|
|
TabsLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
TabsLayout->setSpacing(0);
|
|
|
|
TabsLayout->addStretch(1);
|
|
|
|
TabsContainerWidget->setLayout(TabsLayout);
|
|
|
|
|
|
|
|
TabsMenuButton = new QPushButton();
|
|
|
|
TabsMenuButton->setObjectName("tabsMenuButton");
|
|
|
|
TabsMenuButton->setFlat(true);
|
|
|
|
TabsMenuButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarUnshadeButton));
|
|
|
|
TabsMenuButton->setMaximumWidth(TabsMenuButton->iconSize().width());
|
2018-09-07 17:10:14 +08:00
|
|
|
QMenu* TabsMenu = new QMenu(TabsMenuButton);
|
|
|
|
_this->connect(TabsMenu, SIGNAL(aboutToShow()), SLOT(onTabsMenuAboutToShow()));
|
|
|
|
TabsMenuButton->setMenu(TabsMenu);
|
2017-03-23 17:23:53 +08:00
|
|
|
TopLayout->addWidget(TabsMenuButton, 0);
|
2018-08-28 19:25:44 +08:00
|
|
|
TabsMenuButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
2017-03-23 17:23:53 +08:00
|
|
|
_this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)),
|
|
|
|
SLOT(onTabsMenuActionTriggered(QAction*)));
|
|
|
|
|
|
|
|
CloseButton = new QPushButton();
|
|
|
|
CloseButton->setObjectName("closeButton");
|
|
|
|
CloseButton->setFlat(true);
|
|
|
|
CloseButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
|
|
|
|
CloseButton->setToolTip(_this->tr("Close"));
|
|
|
|
CloseButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
|
|
TopLayout->addWidget(CloseButton, 0);
|
|
|
|
_this->connect(CloseButton, SIGNAL(clicked()), SLOT(onCloseButtonClicked()));
|
|
|
|
|
|
|
|
TabsLayoutInitCount = TabsLayout->count();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void DockAreaWidgetPrivate::updateTabBar()
|
|
|
|
{
|
|
|
|
CDockContainerWidget* Container = _this->dockContainer();
|
|
|
|
if (!Container)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Container->isFloating() && (Container->dockAreaCount() == 1) && (_this->count() == 1))
|
|
|
|
{
|
|
|
|
TitleBar->setVisible(false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TitleBar->setVisible(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void DockAreaWidgetPrivate::addTabsMenuEntry(CDockWidget* DockWidget,
|
|
|
|
int Index, QMenu* menu)
|
|
|
|
{
|
|
|
|
menu = menu ? menu : TabsMenuButton->menu();
|
|
|
|
QAction* Action;
|
|
|
|
if (Index >= 0 && Index < menu->actions().count())
|
|
|
|
{
|
2018-08-27 21:40:01 +08:00
|
|
|
Action = new QAction(DockWidget->icon(), DockWidget->windowTitle());
|
2017-03-23 17:23:53 +08:00
|
|
|
menu->insertAction(menu->actions().at(Index), Action);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-08-27 21:40:01 +08:00
|
|
|
Action = menu->addAction(DockWidget->icon(), DockWidget->windowTitle());
|
2017-03-23 17:23:53 +08:00
|
|
|
}
|
2018-09-07 17:10:14 +08:00
|
|
|
Action->setProperty(DOCKWIDGET_PROPERTY, QVariant::fromValue(DockWidget));
|
2017-03-23 17:23:53 +08:00
|
|
|
QVariant vAction = QVariant::fromValue(Action);
|
|
|
|
DockWidget->setProperty(ACTION_PROPERTY, vAction);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-07 17:10:14 +08:00
|
|
|
//============================================================================
|
|
|
|
void DockAreaWidgetPrivate::markTabsMenuOutdated()
|
|
|
|
{
|
|
|
|
MenuOutdated = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-23 17:23:53 +08:00
|
|
|
//============================================================================
|
|
|
|
void DockAreaWidgetPrivate::updateTabsMenu()
|
|
|
|
{
|
2018-09-07 17:10:14 +08:00
|
|
|
if (!MenuOutdated)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-23 17:23:53 +08:00
|
|
|
QMenu* menu = TabsMenuButton->menu();
|
|
|
|
menu->clear();
|
|
|
|
for (int i = 0; i < ContentsLayout->count(); ++i)
|
|
|
|
{
|
2018-09-07 17:10:14 +08:00
|
|
|
if (dockWidgetAt(i)->isClosed())
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2017-03-23 17:23:53 +08:00
|
|
|
addTabsMenuEntry(dockWidgetAt(i), APPEND, menu);
|
|
|
|
}
|
2018-09-07 17:10:14 +08:00
|
|
|
|
|
|
|
MenuOutdated = false;
|
2017-03-23 17:23:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent) :
|
|
|
|
QFrame(parent),
|
|
|
|
d(new DockAreaWidgetPrivate(this))
|
|
|
|
{
|
|
|
|
d->DockManager = DockManager;
|
|
|
|
d->Layout = new QBoxLayout(QBoxLayout::TopToBottom);
|
|
|
|
d->Layout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
d->Layout->setSpacing(0);
|
|
|
|
setLayout(d->Layout);
|
|
|
|
|
|
|
|
d->createTabBar();
|
|
|
|
|
|
|
|
d->ContentsLayout = new QStackedLayout();
|
|
|
|
d->ContentsLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
d->ContentsLayout->setSpacing(0);
|
|
|
|
d->Layout->addLayout(d->ContentsLayout, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CDockAreaWidget::~CDockAreaWidget()
|
|
|
|
{
|
2017-03-28 18:01:27 +08:00
|
|
|
qDebug() << "~CDockAreaWidget()";
|
2017-03-23 17:23:53 +08:00
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CDockManager* CDockAreaWidget::dockManager() const
|
|
|
|
{
|
|
|
|
return d->DockManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CDockContainerWidget* CDockAreaWidget::dockContainer() const
|
|
|
|
{
|
|
|
|
QWidget* Parent = parentWidget();
|
|
|
|
while (Parent)
|
|
|
|
{
|
|
|
|
CDockContainerWidget* Container = dynamic_cast<CDockContainerWidget*>(Parent);
|
|
|
|
if (Container)
|
|
|
|
{
|
|
|
|
return Container;
|
|
|
|
}
|
|
|
|
Parent = Parent->parentWidget();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::addDockWidget(CDockWidget* DockWidget)
|
|
|
|
{
|
|
|
|
insertDockWidget(d->ContentsLayout->count(), DockWidget);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
|
|
|
|
bool Activate)
|
|
|
|
{
|
|
|
|
d->ContentsLayout->insertWidget(index, DockWidget);
|
2018-09-07 17:10:14 +08:00
|
|
|
DockWidget->tabWidget()->setDockAreaWidget(this);
|
|
|
|
auto TabWidget = DockWidget->tabWidget();
|
|
|
|
d->TabsLayout->insertWidget(index, TabWidget);
|
|
|
|
TabWidget->show();
|
|
|
|
connect(TabWidget, SIGNAL(clicked()), this, SLOT(onDockWidgetTitleClicked()));
|
2017-03-23 17:23:53 +08:00
|
|
|
DockWidget->setProperty(INDEX_PROPERTY, index);
|
|
|
|
if (Activate)
|
|
|
|
{
|
|
|
|
setCurrentIndex(index);
|
|
|
|
}
|
|
|
|
DockWidget->setDockArea(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
|
|
|
|
{
|
2017-03-28 18:01:27 +08:00
|
|
|
qDebug() << "CDockAreaWidget::removeDockWidget";
|
2018-09-07 17:10:14 +08:00
|
|
|
auto NextDockWidget = nextOpenDockWidget(DockWidget);
|
|
|
|
|
2017-03-23 17:23:53 +08:00
|
|
|
d->ContentsLayout->removeWidget(DockWidget);
|
2018-09-07 17:10:14 +08:00
|
|
|
auto TitleBar = DockWidget->tabWidget();
|
2017-03-23 17:23:53 +08:00
|
|
|
TitleBar->hide();
|
|
|
|
d->TabsLayout->removeWidget(TitleBar);
|
|
|
|
disconnect(TitleBar, SIGNAL(clicked()), this, SLOT(onDockWidgetTitleClicked()));
|
2018-09-07 17:10:14 +08:00
|
|
|
if (NextDockWidget)
|
|
|
|
{
|
|
|
|
setCurrentDockWidget(NextDockWidget);
|
|
|
|
d->markTabsMenuOutdated();
|
|
|
|
}
|
2017-03-23 17:23:53 +08:00
|
|
|
|
2017-03-28 14:48:44 +08:00
|
|
|
CDockContainerWidget* DockContainer = dockContainer();
|
2017-03-23 17:23:53 +08:00
|
|
|
if (d->ContentsLayout->isEmpty())
|
|
|
|
{
|
2017-03-28 18:01:27 +08:00
|
|
|
qDebug() << "Dock Area empty";
|
2017-03-23 17:23:53 +08:00
|
|
|
dockContainer()->removeDockArea(this);
|
2017-03-28 14:48:44 +08:00
|
|
|
this->deleteLater();;
|
2017-03-23 17:23:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
d->updateTabBar();
|
|
|
|
DockWidget->setDockArea(nullptr);
|
2017-03-28 14:48:44 +08:00
|
|
|
DockContainer->dumpLayout();
|
2017-03-23 17:23:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::onDockWidgetTitleClicked()
|
|
|
|
{
|
2018-08-24 19:41:58 +08:00
|
|
|
CDockWidgetTab* TitleWidget = qobject_cast<CDockWidgetTab*>(sender());
|
2017-03-23 17:23:53 +08:00
|
|
|
if (!TitleWidget)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int index = d->TabsLayout->indexOf(TitleWidget);
|
|
|
|
setCurrentIndex(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::onCloseButtonClicked()
|
|
|
|
{
|
|
|
|
currentDockWidget()->toggleView(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CDockWidget* CDockAreaWidget::currentDockWidget() const
|
|
|
|
{
|
|
|
|
return dockWidget(currentIndex());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::setCurrentDockWidget(CDockWidget* DockWidget)
|
|
|
|
{
|
|
|
|
int Index = tabIndex(DockWidget);
|
|
|
|
if (Index < 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setCurrentIndex(Index);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::setCurrentIndex(int index)
|
|
|
|
{
|
|
|
|
if (index < 0 || index > (d->TabsLayout->count() - 1))
|
|
|
|
{
|
|
|
|
qWarning() << Q_FUNC_INFO << "Invalid index" << index;
|
|
|
|
return;
|
2018-08-10 19:48:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
emit currentChanging(index);
|
2017-03-23 17:23:53 +08:00
|
|
|
|
|
|
|
// Set active TAB and update all other tabs to be inactive
|
|
|
|
for (int i = 0; i < d->TabsLayout->count(); ++i)
|
|
|
|
{
|
|
|
|
QLayoutItem* item = d->TabsLayout->itemAt(i);
|
|
|
|
if (!item->widget())
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-08-24 19:41:58 +08:00
|
|
|
auto TitleWidget = dynamic_cast<CDockWidgetTab*>(item->widget());
|
2017-03-23 17:23:53 +08:00
|
|
|
if (!TitleWidget)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == index)
|
|
|
|
{
|
|
|
|
TitleWidget->show();
|
|
|
|
TitleWidget->setActiveTab(true);
|
2018-08-24 19:41:58 +08:00
|
|
|
d->TabBar->ensureWidgetVisible(TitleWidget);
|
2017-03-23 17:23:53 +08:00
|
|
|
auto Features = TitleWidget->dockWidget()->features();
|
|
|
|
d->CloseButton->setVisible(Features.testFlag(CDockWidget::DockWidgetClosable));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TitleWidget->setActiveTab(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
d->ContentsLayout->setCurrentIndex(index);
|
|
|
|
d->ContentsLayout->currentWidget()->show();
|
|
|
|
emit currentChanged(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
int CDockAreaWidget::currentIndex() const
|
|
|
|
{
|
|
|
|
return d->ContentsLayout->currentIndex();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
QRect CDockAreaWidget::titleAreaGeometry() const
|
|
|
|
{
|
|
|
|
return d->TopLayout->geometry();
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
QRect CDockAreaWidget::contentAreaGeometry() const
|
|
|
|
{
|
|
|
|
return d->ContentsLayout->geometry();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
int CDockAreaWidget::tabIndex(CDockWidget* DockWidget)
|
|
|
|
{
|
|
|
|
return d->ContentsLayout->indexOf(DockWidget);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
QList<CDockWidget*> CDockAreaWidget::dockWidgets() const
|
|
|
|
{
|
|
|
|
QList<CDockWidget*> DockWidgetList;
|
|
|
|
for (int i = 0; i < d->ContentsLayout->count(); ++i)
|
|
|
|
{
|
|
|
|
DockWidgetList.append(dockWidget(i));
|
|
|
|
}
|
|
|
|
return DockWidgetList;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
QList<CDockWidget*> CDockAreaWidget::openedDockWidgets() const
|
|
|
|
{
|
|
|
|
QList<CDockWidget*> DockWidgetList;
|
|
|
|
for (int i = 0; i < d->ContentsLayout->count(); ++i)
|
|
|
|
{
|
|
|
|
CDockWidget* DockWidget = dockWidget(i);
|
|
|
|
if (!DockWidget->isClosed())
|
|
|
|
{
|
|
|
|
DockWidgetList.append(dockWidget(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return DockWidgetList;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
int CDockAreaWidget::indexOfContentByTitlePos(const QPoint& p, QWidget* exclude) const
|
|
|
|
{
|
|
|
|
for (int i = 0; i < d->ContentsLayout->count(); ++i)
|
|
|
|
{
|
|
|
|
auto TitleWidget = d->titleWidgetAt(i);
|
|
|
|
if (TitleWidget->geometry().contains(p) && (!exclude || TitleWidget != exclude))
|
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
int CDockAreaWidget::count() const
|
|
|
|
{
|
|
|
|
return d->ContentsLayout->count();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CDockWidget* CDockAreaWidget::dockWidget(int Index) const
|
|
|
|
{
|
|
|
|
return dynamic_cast<CDockWidget*>(d->ContentsLayout->widget(Index));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex)
|
|
|
|
{
|
|
|
|
if (fromIndex >= d->ContentsLayout->count() || fromIndex < 0
|
|
|
|
|| toIndex >= d->ContentsLayout->count() || toIndex < 0 || fromIndex == toIndex)
|
|
|
|
{
|
|
|
|
qDebug() << "Invalid index for tab movement" << fromIndex << toIndex;
|
|
|
|
d->TabsLayout->update();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CDockWidget* DockWidget = dockWidget(fromIndex);
|
|
|
|
|
|
|
|
// reorder tabs menu action to match new order of contents
|
|
|
|
auto Menu = d->TabsMenuButton->menu();
|
|
|
|
auto TabsAction = d->dockWidgetTabAction(DockWidget);
|
|
|
|
Menu->removeAction(TabsAction);
|
|
|
|
if (toIndex >= Menu->actions().count())
|
|
|
|
{
|
|
|
|
Menu->addAction(TabsAction);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Menu->insertAction(Menu->actions().at(toIndex), TabsAction);
|
|
|
|
}
|
|
|
|
|
|
|
|
// now reorder contents and title bars
|
|
|
|
QLayoutItem* liFrom = nullptr;
|
|
|
|
liFrom = d->TabsLayout->takeAt(fromIndex);
|
|
|
|
d->TabsLayout->insertItem(toIndex, liFrom);
|
|
|
|
liFrom = d->ContentsLayout->takeAt(fromIndex);
|
|
|
|
d->ContentsLayout->insertWidget(toIndex, liFrom->widget());
|
|
|
|
delete liFrom;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-07 17:10:14 +08:00
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::toggleDockWidgetView(CDockWidget* DockWidget, bool Open)
|
|
|
|
{
|
|
|
|
Q_UNUSED(DockWidget);
|
|
|
|
Q_UNUSED(Open);
|
|
|
|
d->markTabsMenuOutdated();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-23 17:23:53 +08:00
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::onTabsMenuActionTriggered(QAction* Action)
|
|
|
|
{
|
2018-09-07 17:10:14 +08:00
|
|
|
QVariant vDockWidget = Action->property(DOCKWIDGET_PROPERTY);
|
|
|
|
CDockWidget* DockWidget = vDockWidget.value<CDockWidget*>();
|
|
|
|
setCurrentDockWidget(DockWidget);
|
2017-03-23 17:23:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::updateDockArea()
|
|
|
|
{
|
|
|
|
d->updateTabBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-23 22:57:15 +08:00
|
|
|
//============================================================================
|
2017-12-30 01:18:16 +08:00
|
|
|
void CDockAreaWidget::saveState(QXmlStreamWriter& s) const
|
2017-03-23 22:57:15 +08:00
|
|
|
{
|
2017-12-30 01:18:16 +08:00
|
|
|
s.writeStartElement("DockAreaWidget");
|
|
|
|
s.writeAttribute("Tabs", QString::number(d->ContentsLayout->count()));
|
|
|
|
s.writeAttribute("CurrentIndex", QString::number(d->ContentsLayout->currentIndex()));
|
2017-03-28 18:01:27 +08:00
|
|
|
qDebug() << "CDockAreaWidget::saveState TabCount: " << d->ContentsLayout->count()
|
|
|
|
<< " CurrentIndex: " << d->ContentsLayout->currentIndex();
|
2017-03-23 22:57:15 +08:00
|
|
|
for (int i = 0; i < d->ContentsLayout->count(); ++i)
|
|
|
|
{
|
2017-12-30 01:18:16 +08:00
|
|
|
dockWidget(i)->saveState(s);
|
2017-03-23 22:57:15 +08:00
|
|
|
}
|
2017-12-30 01:18:16 +08:00
|
|
|
s.writeEndElement();
|
2017-03-23 22:57:15 +08:00
|
|
|
}
|
|
|
|
|
2018-09-07 17:10:14 +08:00
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CDockWidget* CDockAreaWidget::nextOpenDockWidget(CDockWidget* DockWidget) const
|
|
|
|
{
|
|
|
|
auto OpenDockWidgets = openedDockWidgets();
|
|
|
|
if (OpenDockWidgets.count() > 1)
|
|
|
|
{
|
|
|
|
CDockWidget* NextDockWidget;
|
|
|
|
if (OpenDockWidgets.last() == DockWidget)
|
|
|
|
{
|
|
|
|
NextDockWidget = OpenDockWidgets[OpenDockWidgets.count() - 2];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int NextIndex = OpenDockWidgets.indexOf(DockWidget) + 1;
|
|
|
|
NextDockWidget = OpenDockWidgets[NextIndex];
|
|
|
|
}
|
|
|
|
|
|
|
|
return NextDockWidget;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::onTabsMenuAboutToShow()
|
|
|
|
{
|
|
|
|
std::cout << "CDockAreaWidget::onTabsMenuAboutToShow()" << std::endl;
|
|
|
|
d->updateTabsMenu();
|
|
|
|
}
|
|
|
|
|
2017-03-23 17:23:53 +08:00
|
|
|
} // namespace ads
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// EOF DockAreaWidget.cpp
|