2017-02-27 21:15:20 +08:00
|
|
|
/*******************************************************************************
|
|
|
|
** QtAdcancedDockingSystem
|
|
|
|
** Copyright (C) 2017 Uwe Kindler
|
|
|
|
**
|
|
|
|
** This program is free software: you can redistribute it and/or modify
|
|
|
|
** it under the terms of the GNU General Public License as published by
|
|
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
|
|
** (at your option) any later version.
|
|
|
|
**
|
|
|
|
** This program is distributed in the hope that it will be useful,
|
|
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
** GNU General Public License for more details.
|
|
|
|
**
|
|
|
|
** You should have received a copy of the GNU General Public License
|
|
|
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
2017-02-25 05:44:02 +08:00
|
|
|
//============================================================================
|
|
|
|
/// \file DockAreaWidget.cpp
|
|
|
|
/// \author Uwe Kindler
|
|
|
|
/// \date 24.02.2017
|
|
|
|
/// \brief Implementation of CDockAreaWidget class
|
|
|
|
//============================================================================
|
|
|
|
|
2017-02-27 21:15:20 +08:00
|
|
|
|
2017-02-25 05:44:02 +08:00
|
|
|
//============================================================================
|
|
|
|
// INCLUDES
|
|
|
|
//============================================================================
|
|
|
|
#include "DockAreaWidget.h"
|
|
|
|
|
2017-02-27 01:13:56 +08:00
|
|
|
#include <QStackedLayout>
|
2017-02-27 21:15:20 +08:00
|
|
|
#include <QScrollBar>
|
|
|
|
#include <QScrollArea>
|
|
|
|
#include <QWheelEvent>
|
|
|
|
#include <QStyle>
|
|
|
|
#include <QPushButton>
|
|
|
|
#include <QDebug>
|
2017-02-28 22:23:02 +08:00
|
|
|
#include <QMenu>
|
2017-02-27 01:13:56 +08:00
|
|
|
|
2017-02-25 05:44:02 +08:00
|
|
|
#include "DockContainerWidget.h"
|
2017-02-27 01:13:56 +08:00
|
|
|
#include "DockWidget.h"
|
2017-02-27 21:15:20 +08:00
|
|
|
#include "DockWidgetTitleBar.h"
|
2017-03-01 21:36:46 +08:00
|
|
|
#include "FloatingDockContainer.h"
|
2017-03-02 18:43:48 +08:00
|
|
|
#include "DockManager.h"
|
|
|
|
#include "DockOverlay.h"
|
2017-02-27 21:15:20 +08:00
|
|
|
|
|
|
|
#include <iostream>
|
2017-02-25 05:44:02 +08:00
|
|
|
|
|
|
|
namespace ads
|
|
|
|
{
|
2017-02-28 22:23:02 +08:00
|
|
|
static const char* const INDEX_PROPERTY = "index";
|
|
|
|
static const char* const ACTION_PROPERTY = "action";
|
2017-03-03 20:42:41 +08:00
|
|
|
static const int APPEND = -1;
|
2017-02-28 22:23:02 +08:00
|
|
|
|
2017-02-27 21:15:20 +08:00
|
|
|
/**
|
|
|
|
* Custom scroll bar implementation for dock area tab bar
|
2017-03-01 21:36:46 +08:00
|
|
|
* This scroll area enables floating of a whole dock area including all
|
|
|
|
* dock widgets
|
2017-02-27 21:15:20 +08:00
|
|
|
*/
|
|
|
|
class CTabsScrollArea : public QScrollArea
|
|
|
|
{
|
2017-03-01 21:36:46 +08:00
|
|
|
private:
|
|
|
|
QPoint m_DragStartMousePos;
|
2017-03-03 20:42:41 +08:00
|
|
|
CDockAreaWidget* m_DockArea;
|
|
|
|
CFloatingDockContainer* m_FloatingWidget = nullptr;
|
2017-03-01 21:36:46 +08:00
|
|
|
|
2017-02-27 21:15:20 +08:00
|
|
|
public:
|
2017-03-01 21:36:46 +08:00
|
|
|
CTabsScrollArea(CDockAreaWidget* parent)
|
|
|
|
: QScrollArea(parent),
|
2017-03-03 20:42:41 +08:00
|
|
|
m_DockArea(parent)
|
2017-02-27 21:15:20 +08:00
|
|
|
{
|
|
|
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
|
|
|
|
setFrameStyle(QFrame::NoFrame);
|
|
|
|
setWidgetResizable(true);
|
|
|
|
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
|
|
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
2017-03-01 23:13:37 +08:00
|
|
|
virtual void wheelEvent(QWheelEvent* Event) override
|
2017-02-27 21:15:20 +08:00
|
|
|
{
|
2017-03-03 20:42:41 +08:00
|
|
|
std::cout << "CTabsScrollArea::wheelEvent" << std::endl;
|
2017-02-27 21:15:20 +08:00
|
|
|
Event->accept();
|
|
|
|
const int direction = Event->angleDelta().y();
|
|
|
|
if (direction < 0)
|
|
|
|
{
|
|
|
|
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + 20);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - 20);
|
|
|
|
}
|
|
|
|
}
|
2017-03-01 21:36:46 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores mouse position to detect dragging
|
|
|
|
*/
|
2017-03-01 23:13:37 +08:00
|
|
|
virtual void mousePressEvent(QMouseEvent* ev) override
|
2017-03-01 21:36:46 +08:00
|
|
|
{
|
|
|
|
if (ev->button() == Qt::LeftButton)
|
|
|
|
{
|
|
|
|
ev->accept();
|
|
|
|
m_DragStartMousePos = ev->pos();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
QScrollArea::mousePressEvent(ev);
|
|
|
|
}
|
|
|
|
|
2017-03-03 20:42:41 +08:00
|
|
|
/**
|
|
|
|
* Stores mouse position to detect dragging
|
|
|
|
*/
|
|
|
|
virtual void mouseReleaseEvent(QMouseEvent* ev) override
|
|
|
|
{
|
|
|
|
if (ev->button() == Qt::LeftButton)
|
|
|
|
{
|
|
|
|
std::cout << "CTabsScrollArea::mouseReleaseEvent" << std::endl;
|
|
|
|
ev->accept();
|
|
|
|
m_FloatingWidget = nullptr;
|
|
|
|
m_DragStartMousePos = QPoint();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
QScrollArea::mouseReleaseEvent(ev);
|
|
|
|
}
|
|
|
|
|
2017-03-01 21:36:46 +08:00
|
|
|
/**
|
2017-03-02 18:43:48 +08:00
|
|
|
* Starts floating the complete docking area including all dock widgets,
|
|
|
|
* if it is not the last dock area in a floating widget
|
2017-03-01 21:36:46 +08:00
|
|
|
*/
|
2017-03-01 23:13:37 +08:00
|
|
|
virtual void mouseMoveEvent(QMouseEvent* ev) override
|
2017-03-01 21:36:46 +08:00
|
|
|
{
|
|
|
|
QScrollArea::mouseMoveEvent(ev);
|
|
|
|
if (ev->buttons() != Qt::LeftButton)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2017-03-02 18:43:48 +08:00
|
|
|
|
2017-03-03 20:42:41 +08:00
|
|
|
if (m_FloatingWidget)
|
|
|
|
{
|
|
|
|
m_FloatingWidget->moveFloating();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-02 18:43:48 +08:00
|
|
|
// If this is the last dock area in a dock container it does not make
|
|
|
|
// sense to move it to a new floating widget and leave this one
|
|
|
|
// empty
|
2017-03-03 20:42:41 +08:00
|
|
|
if (m_DockArea->dockContainer()->isFloating() && m_DockArea->dockContainer()->dockAreaCount() == 1)
|
2017-03-02 18:43:48 +08:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-01 21:36:46 +08:00
|
|
|
if (!this->geometry().contains(ev->pos()))
|
|
|
|
{
|
2017-03-02 18:43:48 +08:00
|
|
|
std::cout << "CTabsScrollArea::startFloating" << std::endl;
|
2017-03-03 20:42:41 +08:00
|
|
|
startFloating(m_DragStartMousePos);
|
|
|
|
auto Overlay = m_DockArea->dockManager()->containerOverlay();
|
2017-03-02 18:43:48 +08:00
|
|
|
Overlay->setAllowedAreas(OuterDockAreas);
|
2017-03-01 21:36:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2017-03-01 23:13:37 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Double clicking the title bar also starts floating of the complete area
|
|
|
|
*/
|
|
|
|
virtual void mouseDoubleClickEvent(QMouseEvent *event) override
|
|
|
|
{
|
2017-03-03 20:42:41 +08:00
|
|
|
startFloating(event->pos());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts floating
|
|
|
|
*/
|
|
|
|
void startFloating(const QPoint& Pos)
|
|
|
|
{
|
|
|
|
QSize Size = m_DockArea->size();
|
|
|
|
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(m_DockArea);
|
|
|
|
FloatingWidget->startFloating(Pos, Size);
|
|
|
|
m_FloatingWidget = FloatingWidget;
|
2017-03-01 23:13:37 +08:00
|
|
|
}
|
2017-02-27 21:15:20 +08:00
|
|
|
}; // class CTabsScrollArea
|
|
|
|
|
|
|
|
|
2017-02-25 05:44:02 +08:00
|
|
|
/**
|
|
|
|
* Private data class of CDockAreaWidget class (pimpl)
|
|
|
|
*/
|
|
|
|
struct DockAreaWidgetPrivate
|
|
|
|
{
|
|
|
|
CDockAreaWidget* _this;
|
2017-02-27 21:15:20 +08:00
|
|
|
QBoxLayout* Layout;
|
2017-03-02 18:43:48 +08:00
|
|
|
QFrame* TitleBar;
|
2017-02-27 21:15:20 +08:00
|
|
|
QBoxLayout* TopLayout;
|
|
|
|
QStackedLayout* ContentsLayout;
|
|
|
|
QScrollArea* TabsScrollArea;
|
|
|
|
QWidget* TabsContainerWidget;
|
|
|
|
QBoxLayout* TabsLayout;
|
|
|
|
QPushButton* TabsMenuButton;
|
|
|
|
QPushButton* CloseButton;
|
|
|
|
int TabsLayoutInitCount;
|
2017-03-01 21:09:56 +08:00
|
|
|
CDockManager* DockManager = nullptr;
|
2017-02-25 05:44:02 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Private data constructor
|
|
|
|
*/
|
|
|
|
DockAreaWidgetPrivate(CDockAreaWidget* _public);
|
2017-02-27 21:15:20 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates the layout for top area with tabs and close button
|
|
|
|
*/
|
|
|
|
void createTabBar();
|
2017-02-28 22:23:02 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
CDockWidgetTitleBar* titleWidgetAt(int index)
|
|
|
|
{
|
|
|
|
return dockWidgetAt(index)->titleBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a tabs menu entry for the given dock widget
|
2017-03-01 21:09:56 +08:00
|
|
|
* 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
|
2017-02-28 22:23:02 +08:00
|
|
|
*/
|
2017-03-03 20:42:41 +08:00
|
|
|
void addTabsMenuEntry(CDockWidget* DockWidget, int Index = -1, QMenu* menu = 0);
|
2017-02-28 22:23:02 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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();
|
|
|
|
}
|
2017-03-01 21:09:56 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Update the tabs menu if dock widget order changed or if dock widget has
|
|
|
|
* been removed
|
|
|
|
*/
|
|
|
|
void updateTabsMenu();
|
2017-03-02 18:43:48 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the tab bar visibility depending on the number of dock widgets
|
|
|
|
* in this area
|
|
|
|
*/
|
|
|
|
void updateTabBar();
|
2017-02-25 05:44:02 +08:00
|
|
|
};
|
|
|
|
// struct DockAreaWidgetPrivate
|
|
|
|
|
2017-02-27 21:15:20 +08:00
|
|
|
|
2017-02-25 05:44:02 +08:00
|
|
|
//============================================================================
|
|
|
|
DockAreaWidgetPrivate::DockAreaWidgetPrivate(CDockAreaWidget* _public) :
|
|
|
|
_this(_public)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-02-27 21:15:20 +08:00
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void DockAreaWidgetPrivate::createTabBar()
|
|
|
|
{
|
2017-03-02 18:43:48 +08:00
|
|
|
TitleBar = new QFrame(_this);
|
2017-03-03 22:47:03 +08:00
|
|
|
TitleBar->setObjectName("dockAreaTitleBar");
|
2017-02-27 21:15:20 +08:00
|
|
|
TopLayout = new QBoxLayout(QBoxLayout::LeftToRight);
|
|
|
|
TopLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
TopLayout->setSpacing(0);
|
2017-03-02 18:43:48 +08:00
|
|
|
TitleBar->setLayout(TopLayout);
|
|
|
|
Layout->addWidget(TitleBar);
|
2017-02-27 21:15:20 +08:00
|
|
|
|
|
|
|
TabsScrollArea = new CTabsScrollArea(_this);
|
|
|
|
TopLayout->addWidget(TabsScrollArea, 1);
|
|
|
|
|
|
|
|
TabsContainerWidget = new QWidget();
|
|
|
|
TabsContainerWidget->setObjectName("tabsContainerWidget");
|
|
|
|
TabsScrollArea->setWidget(TabsContainerWidget);
|
|
|
|
|
|
|
|
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());
|
2017-02-28 22:23:02 +08:00
|
|
|
TabsMenuButton->setMenu(new QMenu(TabsMenuButton));
|
2017-02-27 21:15:20 +08:00
|
|
|
TopLayout->addWidget(TabsMenuButton, 0);
|
2017-02-28 22:23:02 +08:00
|
|
|
_this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)),
|
|
|
|
SLOT(onTabsMenuActionTriggered(QAction*)));
|
2017-02-27 21:15:20 +08:00
|
|
|
|
|
|
|
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);
|
2017-03-12 04:38:31 +08:00
|
|
|
_this->connect(CloseButton, SIGNAL(clicked()), SLOT(onCloseButtonClicked()));
|
2017-02-27 21:15:20 +08:00
|
|
|
|
|
|
|
TabsLayoutInitCount = TabsLayout->count();
|
|
|
|
}
|
|
|
|
|
2017-02-28 22:23:02 +08:00
|
|
|
|
2017-03-02 18:43:48 +08:00
|
|
|
//============================================================================
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-28 22:23:02 +08:00
|
|
|
//============================================================================
|
2017-03-01 21:09:56 +08:00
|
|
|
void DockAreaWidgetPrivate::addTabsMenuEntry(CDockWidget* DockWidget,
|
2017-03-03 20:42:41 +08:00
|
|
|
int Index, QMenu* menu)
|
2017-02-28 22:23:02 +08:00
|
|
|
{
|
2017-03-01 21:09:56 +08:00
|
|
|
menu = menu ? menu : TabsMenuButton->menu();
|
2017-03-03 20:42:41 +08:00
|
|
|
QAction* Action;
|
|
|
|
if (Index >= 0 && Index < menu->actions().count())
|
|
|
|
{
|
|
|
|
Action = new QAction(DockWidget->windowTitle());
|
|
|
|
menu->insertAction(menu->actions().at(Index), Action);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Action = menu->addAction(DockWidget->windowTitle());
|
|
|
|
}
|
2017-02-28 22:23:02 +08:00
|
|
|
QVariant vAction = QVariant::fromValue(Action);
|
|
|
|
DockWidget->setProperty(ACTION_PROPERTY, vAction);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-01 21:09:56 +08:00
|
|
|
//============================================================================
|
|
|
|
void DockAreaWidgetPrivate::updateTabsMenu()
|
|
|
|
{
|
|
|
|
QMenu* menu = TabsMenuButton->menu();
|
|
|
|
menu->clear();
|
|
|
|
for (int i = 0; i < ContentsLayout->count(); ++i)
|
|
|
|
{
|
|
|
|
CDockWidget* DockWidget = dockWidgetAt(i);
|
2017-03-03 20:42:41 +08:00
|
|
|
addTabsMenuEntry(dockWidgetAt(i), APPEND, menu);
|
2017-03-01 21:09:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-25 05:44:02 +08:00
|
|
|
//============================================================================
|
|
|
|
CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent) :
|
|
|
|
QFrame(parent),
|
|
|
|
d(new DockAreaWidgetPrivate(this))
|
|
|
|
{
|
2017-03-01 21:09:56 +08:00
|
|
|
d->DockManager = DockManager;
|
2017-02-27 21:15:20 +08:00
|
|
|
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);
|
2017-02-25 05:44:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CDockAreaWidget::~CDockAreaWidget()
|
|
|
|
{
|
2017-03-01 21:09:56 +08:00
|
|
|
std::cout << "~CDockAreaWidget()" << std::endl;
|
2017-02-25 05:44:02 +08:00
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
2017-03-01 21:09:56 +08:00
|
|
|
CDockManager* CDockAreaWidget::dockManager() const
|
|
|
|
{
|
|
|
|
return d->DockManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CDockContainerWidget* CDockAreaWidget::dockContainer() const
|
2017-02-25 05:44:02 +08:00
|
|
|
{
|
|
|
|
QWidget* Parent = parentWidget();
|
|
|
|
while (Parent)
|
|
|
|
{
|
|
|
|
CDockContainerWidget* Container = dynamic_cast<CDockContainerWidget*>(Parent);
|
|
|
|
if (Container)
|
|
|
|
{
|
|
|
|
return Container;
|
|
|
|
}
|
|
|
|
Parent = Parent->parentWidget();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2017-02-27 01:13:56 +08:00
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::addDockWidget(CDockWidget* DockWidget)
|
|
|
|
{
|
2017-03-03 20:42:41 +08:00
|
|
|
insertDockWidget(d->ContentsLayout->count(), DockWidget);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
|
|
|
|
bool Activate)
|
|
|
|
{
|
|
|
|
d->ContentsLayout->insertWidget(index, DockWidget);
|
2017-02-28 22:23:02 +08:00
|
|
|
DockWidget->titleBar()->setDockAreaWidget(this);
|
2017-02-27 21:15:20 +08:00
|
|
|
auto TitleBar = DockWidget->titleBar();
|
2017-03-03 20:42:41 +08:00
|
|
|
d->TabsLayout->insertWidget(index, TitleBar);
|
2017-03-12 04:38:31 +08:00
|
|
|
TitleBar->show();
|
2017-02-27 21:15:20 +08:00
|
|
|
connect(TitleBar, SIGNAL(clicked()), this, SLOT(onDockWidgetTitleClicked()));
|
2017-03-03 20:42:41 +08:00
|
|
|
DockWidget->setProperty(INDEX_PROPERTY, index);
|
|
|
|
if (Activate)
|
2017-02-27 21:15:20 +08:00
|
|
|
{
|
2017-03-03 20:42:41 +08:00
|
|
|
setCurrentIndex(index);
|
2017-02-27 21:15:20 +08:00
|
|
|
}
|
2017-03-03 20:42:41 +08:00
|
|
|
d->addTabsMenuEntry(DockWidget, index);
|
2017-03-12 04:38:31 +08:00
|
|
|
DockWidget->setDockArea(this);
|
2017-02-27 21:15:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-01 21:09:56 +08:00
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
|
|
|
|
{
|
|
|
|
std::cout << "CDockAreaWidget::removeDockWidget" << std::endl;
|
|
|
|
d->ContentsLayout->removeWidget(DockWidget);
|
|
|
|
auto TitleBar = DockWidget->titleBar();
|
2017-03-12 04:38:31 +08:00
|
|
|
TitleBar->hide();
|
2017-03-01 21:09:56 +08:00
|
|
|
d->TabsLayout->removeWidget(TitleBar);
|
|
|
|
disconnect(TitleBar, SIGNAL(clicked()), this, SLOT(onDockWidgetTitleClicked()));
|
2017-03-03 20:42:41 +08:00
|
|
|
setCurrentIndex(d->ContentsLayout->currentIndex());
|
2017-03-01 21:09:56 +08:00
|
|
|
d->updateTabsMenu();
|
|
|
|
|
|
|
|
if (d->ContentsLayout->isEmpty())
|
|
|
|
{
|
|
|
|
std::cout << "Dock Area empty" << std::endl;
|
|
|
|
dockContainer()->removeDockArea(this);
|
|
|
|
this->deleteLater();
|
|
|
|
}
|
2017-03-02 18:43:48 +08:00
|
|
|
|
|
|
|
d->updateTabBar();
|
2017-03-12 04:38:31 +08:00
|
|
|
DockWidget->setDockArea(nullptr);
|
2017-03-01 21:09:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-27 21:15:20 +08:00
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::onDockWidgetTitleClicked()
|
|
|
|
{
|
|
|
|
CDockWidgetTitleBar* TitleWidget = qobject_cast<CDockWidgetTitleBar*>(sender());
|
|
|
|
if (!TitleWidget)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int index = d->TabsLayout->indexOf(TitleWidget);
|
|
|
|
setCurrentIndex(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-12 04:38:31 +08:00
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::onCloseButtonClicked()
|
|
|
|
{
|
|
|
|
currentDockWidget()->toggleView(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CDockWidget* CDockAreaWidget::currentDockWidget() const
|
|
|
|
{
|
|
|
|
return dockWidget(currentIndex());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-27 21:15:20 +08:00
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::setCurrentIndex(int index)
|
|
|
|
{
|
|
|
|
if (index < 0 || index > (d->TabsLayout->count() - 1))
|
|
|
|
{
|
|
|
|
qWarning() << Q_FUNC_INFO << "Invalid index" << index;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto TitleWidget = dynamic_cast<CDockWidgetTitleBar*>(item->widget());
|
|
|
|
if (!TitleWidget)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == index)
|
|
|
|
{
|
|
|
|
TitleWidget->setActiveTab(true);
|
|
|
|
d->TabsScrollArea->ensureWidgetVisible(TitleWidget);
|
|
|
|
auto Features = TitleWidget->dockWidget()->features();
|
2017-02-28 22:23:02 +08:00
|
|
|
d->CloseButton->setVisible(Features.testFlag(CDockWidget::DockWidgetClosable));
|
2017-02-27 21:15:20 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TitleWidget->setActiveTab(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
d->ContentsLayout->setCurrentIndex(index);
|
2017-03-13 04:41:50 +08:00
|
|
|
emit currentChanged(index);
|
2017-02-27 01:13:56 +08:00
|
|
|
}
|
2017-02-28 22:23:02 +08:00
|
|
|
|
|
|
|
|
2017-03-03 20:42:41 +08:00
|
|
|
//============================================================================
|
|
|
|
int CDockAreaWidget::currentIndex() const
|
|
|
|
{
|
|
|
|
return d->ContentsLayout->currentIndex();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-28 22:23:02 +08:00
|
|
|
//============================================================================
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::onTabsMenuActionTriggered(QAction* Action)
|
|
|
|
{
|
|
|
|
int Index = d->TabsMenuButton->menu()->actions().indexOf(Action);
|
|
|
|
setCurrentIndex(Index);
|
|
|
|
}
|
2017-03-02 18:43:48 +08:00
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CDockAreaWidget::updateDockArea()
|
|
|
|
{
|
|
|
|
d->updateTabBar();
|
|
|
|
}
|
|
|
|
|
2017-02-25 05:44:02 +08:00
|
|
|
} // namespace ads
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// EOF DockAreaWidget.cpp
|