fix can not scale size and remoce avddock code
This commit is contained in:
parent
be8b4fde94
commit
2e7030de3c
@ -24,7 +24,7 @@
|
|||||||
5.关联文件时候更改文件的按键不太明显。
|
5.关联文件时候更改文件的按键不太明显。
|
||||||
解决方案
|
解决方案
|
||||||
a、属性控件文件选择按钮不明显 (解决)
|
a、属性控件文件选择按钮不明显 (解决)
|
||||||
b、属性控件中间的分割线能左右移动
|
b、属性控件中间的分割线能左右移动 (解决)
|
||||||
|
|
||||||
6.提供的轨迹文件是如何输入到dyt界面的,我们需要知道。
|
6.提供的轨迹文件是如何输入到dyt界面的,我们需要知道。
|
||||||
解决方案
|
解决方案
|
||||||
|
@ -857,31 +857,6 @@
|
|||||||
<source>the appliaction is crash</source>
|
<source>the appliaction is crash</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<location filename="../ui/AdvDock/DockAreaTitleBar.cpp" line="158"/>
|
|
||||||
<source>List all tabs</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/AdvDock/DockAreaTitleBar.cpp" line="171"/>
|
|
||||||
<source>Detach Group</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/AdvDock/DockAreaTitleBar.cpp" line="187"/>
|
|
||||||
<source>Close Active Tab</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/AdvDock/DockAreaTitleBar.cpp" line="191"/>
|
|
||||||
<source>Close Group</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/AdvDock/DockWidgetTab.cpp" line="196"/>
|
|
||||||
<source>Close Tab</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<location filename="../scene/ui/QueryElevationWidget.cpp" line="65"/>
|
<location filename="../scene/ui/QueryElevationWidget.cpp" line="65"/>
|
||||||
<source>longitude:</source>
|
<source>longitude:</source>
|
||||||
@ -1816,50 +1791,6 @@
|
|||||||
<translation>保存空间目录</translation>
|
<translation>保存空间目录</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>ads::CDockAreaTitleBar</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/AdvDock/DockAreaTitleBar.cpp" line="373"/>
|
|
||||||
<source>Detach Area</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/AdvDock/DockAreaTitleBar.cpp" line="376"/>
|
|
||||||
<source>Close Area</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/AdvDock/DockAreaTitleBar.cpp" line="378"/>
|
|
||||||
<source>Close Other Areas</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>ads::CDockManager</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/AdvDock/DockManager.cpp" line="420"/>
|
|
||||||
<source>Show View</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>ads::CDockWidgetTab</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/AdvDock/DockWidgetTab.cpp" line="428"/>
|
|
||||||
<source>Detach</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/AdvDock/DockWidgetTab.cpp" line="431"/>
|
|
||||||
<source>Close</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/AdvDock/DockWidgetTab.cpp" line="433"/>
|
|
||||||
<source>Close Others</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>osgQOpenGLWidget</name>
|
<name>osgQOpenGLWidget</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -1,647 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockAreaTabBar.cpp
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 24.08.2018
|
|
||||||
/// \brief Implementation of CDockAreaTabBar class
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include "FloatingDragPreview.h"
|
|
||||||
#include "DockAreaTabBar.h"
|
|
||||||
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <QScrollBar>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QBoxLayout>
|
|
||||||
#include <QApplication>
|
|
||||||
|
|
||||||
#include "FloatingDockContainer.h"
|
|
||||||
#include "DockAreaWidget.h"
|
|
||||||
#include "DockOverlay.h"
|
|
||||||
#include "DockManager.h"
|
|
||||||
#include "DockWidget.h"
|
|
||||||
#include "DockWidgetTab.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Private data class of CDockAreaTabBar class (pimpl)
|
|
||||||
*/
|
|
||||||
struct DockAreaTabBarPrivate
|
|
||||||
{
|
|
||||||
CDockAreaTabBar* _this;
|
|
||||||
QPoint DragStartMousePos;
|
|
||||||
CDockAreaWidget* DockArea;
|
|
||||||
IFloatingWidget* FloatingWidget = nullptr;
|
|
||||||
QWidget* TabsContainerWidget;
|
|
||||||
QBoxLayout* TabsLayout;
|
|
||||||
int CurrentIndex = -1;
|
|
||||||
eDragState DragState = DraggingInactive;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data constructor
|
|
||||||
*/
|
|
||||||
DockAreaTabBarPrivate(CDockAreaTabBar* _public);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update tabs after current index changed or when tabs are removed.
|
|
||||||
* The function reassigns the stylesheet to update the tabs
|
|
||||||
*/
|
|
||||||
void updateTabs();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test function for current drag state
|
|
||||||
*/
|
|
||||||
bool isDraggingState(eDragState dragState) const
|
|
||||||
{
|
|
||||||
return this->DragState == dragState;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// struct DockAreaTabBarPrivate
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
DockAreaTabBarPrivate::DockAreaTabBarPrivate(CDockAreaTabBar* _public) :
|
|
||||||
_this(_public)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockAreaTabBarPrivate::updateTabs()
|
|
||||||
{
|
|
||||||
// Set active TAB and update all other tabs to be inactive
|
|
||||||
for (int i = 0; i < _this->count(); ++i)
|
|
||||||
{
|
|
||||||
auto TabWidget = _this->tab(i);
|
|
||||||
if (!TabWidget)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == CurrentIndex)
|
|
||||||
{
|
|
||||||
TabWidget->show();
|
|
||||||
TabWidget->setActiveTab(true);
|
|
||||||
_this->ensureWidgetVisible(TabWidget);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TabWidget->setActiveTab(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockAreaTabBar::CDockAreaTabBar(CDockAreaWidget* parent) :
|
|
||||||
QScrollArea(parent),
|
|
||||||
d(new DockAreaTabBarPrivate(this))
|
|
||||||
{
|
|
||||||
d->DockArea = parent;
|
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
|
||||||
setFrameStyle(QFrame::NoFrame);
|
|
||||||
setWidgetResizable(true);
|
|
||||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
||||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
||||||
|
|
||||||
d->TabsContainerWidget = new QWidget();
|
|
||||||
d->TabsContainerWidget->setObjectName("tabsContainerWidget");
|
|
||||||
setWidget(d->TabsContainerWidget);
|
|
||||||
|
|
||||||
d->TabsLayout = new QBoxLayout(QBoxLayout::LeftToRight);
|
|
||||||
d->TabsLayout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
d->TabsLayout->setSpacing(0);
|
|
||||||
d->TabsLayout->addStretch(1);
|
|
||||||
d->TabsContainerWidget->setLayout(d->TabsLayout);
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockAreaTabBar::~CDockAreaTabBar()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaTabBar::wheelEvent(QWheelEvent* Event)
|
|
||||||
{
|
|
||||||
Event->accept();
|
|
||||||
const int direction = Event->angleDelta().y();
|
|
||||||
if (direction < 0)
|
|
||||||
{
|
|
||||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + 20);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - 20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaTabBar::mousePressEvent(QMouseEvent* ev)
|
|
||||||
{
|
|
||||||
if (ev->button() == Qt::LeftButton)
|
|
||||||
{
|
|
||||||
ev->accept();
|
|
||||||
d->DragStartMousePos = ev->pos();
|
|
||||||
d->DragState = DraggingMousePressed;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Super::mousePressEvent(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaTabBar::mouseReleaseEvent(QMouseEvent* ev)
|
|
||||||
{
|
|
||||||
if (ev->button() == Qt::LeftButton)
|
|
||||||
{
|
|
||||||
ADS_PRINT("CDockAreaTabBar::mouseReleaseEvent");
|
|
||||||
ev->accept();
|
|
||||||
auto CurrentDragState = d->DragState;
|
|
||||||
d->DragStartMousePos = QPoint();
|
|
||||||
d->DragState = DraggingInactive;
|
|
||||||
if (DraggingFloatingWidget == CurrentDragState)
|
|
||||||
{
|
|
||||||
d->FloatingWidget->finishDragging();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Super::mouseReleaseEvent(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaTabBar::mouseMoveEvent(QMouseEvent* ev)
|
|
||||||
{
|
|
||||||
Super::mouseMoveEvent(ev);
|
|
||||||
if (!(ev->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive))
|
|
||||||
{
|
|
||||||
d->DragState = DraggingInactive;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// move floating window
|
|
||||||
if (d->isDraggingState(DraggingFloatingWidget))
|
|
||||||
{
|
|
||||||
d->FloatingWidget->moveFloating();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
if (d->DockArea->dockContainer()->isFloating()
|
|
||||||
&& d->DockArea->dockContainer()->visibleDockAreaCount() == 1)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If one single dock widget in this area is not floatable then the whole
|
|
||||||
// area is not floatable
|
|
||||||
if (!d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DragDistance = (d->DragStartMousePos - ev->pos()).manhattanLength();
|
|
||||||
if (DragDistance >= CDockManager::startDragDistance())
|
|
||||||
{
|
|
||||||
ADS_PRINT("CTabsScrollArea::startFloating");
|
|
||||||
startFloating(d->DragStartMousePos);
|
|
||||||
auto Overlay = d->DockArea->dockManager()->containerOverlay();
|
|
||||||
Overlay->setAllowedAreas(OuterDockAreas);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaTabBar::mouseDoubleClickEvent(QMouseEvent *event)
|
|
||||||
{
|
|
||||||
// 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
|
|
||||||
if (d->DockArea->dockContainer()->isFloating() && d->DockArea->dockContainer()->dockAreaCount() == 1)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
makeAreaFloating(event->pos(), DraggingInactive);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
IFloatingWidget* CDockAreaTabBar::makeAreaFloating(const QPoint& Offset, eDragState DragState)
|
|
||||||
{
|
|
||||||
QSize Size = d->DockArea->size();
|
|
||||||
d->DragState = DragState;
|
|
||||||
bool OpaqueUndocking = CDockManager::configFlags().testFlag(CDockManager::OpaqueUndocking) ||
|
|
||||||
(DraggingFloatingWidget != DragState);
|
|
||||||
CFloatingDockContainer* FloatingDockContainer = nullptr;
|
|
||||||
IFloatingWidget* FloatingWidget;
|
|
||||||
if (OpaqueUndocking)
|
|
||||||
{
|
|
||||||
FloatingWidget = FloatingDockContainer = new CFloatingDockContainer(d->DockArea);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto w = new CFloatingDragPreview(d->DockArea);
|
|
||||||
connect(w, &CFloatingDragPreview::draggingCanceled, [=]()
|
|
||||||
{
|
|
||||||
d->DragState = DraggingInactive;
|
|
||||||
});
|
|
||||||
FloatingWidget = w;
|
|
||||||
}
|
|
||||||
|
|
||||||
FloatingWidget->startFloating(Offset, Size, DragState, nullptr);
|
|
||||||
if (FloatingDockContainer)
|
|
||||||
{
|
|
||||||
auto TopLevelDockWidget = FloatingDockContainer->topLevelDockWidget();
|
|
||||||
if (TopLevelDockWidget)
|
|
||||||
{
|
|
||||||
TopLevelDockWidget->emitTopLevelChanged(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FloatingWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaTabBar::startFloating(const QPoint& Offset)
|
|
||||||
{
|
|
||||||
d->FloatingWidget = makeAreaFloating(Offset, DraggingFloatingWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaTabBar::setCurrentIndex(int index)
|
|
||||||
{
|
|
||||||
if (index == d->CurrentIndex)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index < -1 || index > (count() - 1))
|
|
||||||
{
|
|
||||||
qWarning() << Q_FUNC_INFO << "Invalid index" << index;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit currentChanging(index);
|
|
||||||
d->CurrentIndex = index;
|
|
||||||
d->updateTabs();
|
|
||||||
emit currentChanged(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
int CDockAreaTabBar::count() const
|
|
||||||
{
|
|
||||||
// The tab bar contains a stretch item as last item
|
|
||||||
return d->TabsLayout->count() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
void CDockAreaTabBar::insertTab(int Index, CDockWidgetTab* Tab)
|
|
||||||
{
|
|
||||||
d->TabsLayout->insertWidget(Index, Tab);
|
|
||||||
connect(Tab, SIGNAL(clicked()), this, SLOT(onTabClicked()));
|
|
||||||
connect(Tab, SIGNAL(closeRequested()), this, SLOT(onTabCloseRequested()));
|
|
||||||
connect(Tab, SIGNAL(closeOtherTabsRequested()), this, SLOT(onCloseOtherTabsRequested()));
|
|
||||||
connect(Tab, SIGNAL(moved(const QPoint&)), this, SLOT(onTabWidgetMoved(const QPoint&)));
|
|
||||||
Tab->installEventFilter(this);
|
|
||||||
emit tabInserted(Index);
|
|
||||||
if (Index <= d->CurrentIndex)
|
|
||||||
{
|
|
||||||
setCurrentIndex(d->CurrentIndex + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
void CDockAreaTabBar::removeTab(CDockWidgetTab* Tab)
|
|
||||||
{
|
|
||||||
if (!count())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ADS_PRINT("CDockAreaTabBar::removeTab ");
|
|
||||||
int NewCurrentIndex = currentIndex();
|
|
||||||
int RemoveIndex = d->TabsLayout->indexOf(Tab);
|
|
||||||
if (count() == 1)
|
|
||||||
{
|
|
||||||
NewCurrentIndex = -1;
|
|
||||||
}
|
|
||||||
if (NewCurrentIndex > RemoveIndex)
|
|
||||||
{
|
|
||||||
NewCurrentIndex--;
|
|
||||||
}
|
|
||||||
else if (NewCurrentIndex == RemoveIndex)
|
|
||||||
{
|
|
||||||
NewCurrentIndex = -1;
|
|
||||||
// First we walk to the right to search for the next visible tab
|
|
||||||
for (int i = (RemoveIndex + 1); i < count(); ++i)
|
|
||||||
{
|
|
||||||
if (tab(i)->isVisibleTo(this))
|
|
||||||
{
|
|
||||||
NewCurrentIndex = i - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is no visible tab right to this tab then we walk to
|
|
||||||
// the left to find a visible tab
|
|
||||||
if (NewCurrentIndex < 0)
|
|
||||||
{
|
|
||||||
for (int i = (RemoveIndex - 1); i >= 0; --i)
|
|
||||||
{
|
|
||||||
if (tab(i)->isVisibleTo(this))
|
|
||||||
{
|
|
||||||
NewCurrentIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit removingTab(RemoveIndex);
|
|
||||||
d->TabsLayout->removeWidget(Tab);
|
|
||||||
Tab->disconnect(this);
|
|
||||||
Tab->removeEventFilter(this);
|
|
||||||
ADS_PRINT("NewCurrentIndex " << NewCurrentIndex);
|
|
||||||
if (NewCurrentIndex != d->CurrentIndex)
|
|
||||||
{
|
|
||||||
setCurrentIndex(NewCurrentIndex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d->updateTabs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
int CDockAreaTabBar::currentIndex() const
|
|
||||||
{
|
|
||||||
return d->CurrentIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
CDockWidgetTab* CDockAreaTabBar::currentTab() const
|
|
||||||
{
|
|
||||||
if (d->CurrentIndex < 0)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return qobject_cast<CDockWidgetTab*>(d->TabsLayout->itemAt(d->CurrentIndex)->widget());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
void CDockAreaTabBar::onTabClicked()
|
|
||||||
{
|
|
||||||
CDockWidgetTab* Tab = qobject_cast<CDockWidgetTab*>(sender());
|
|
||||||
if (!Tab)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int index = d->TabsLayout->indexOf(Tab);
|
|
||||||
if (index < 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setCurrentIndex(index);
|
|
||||||
emit tabBarClicked(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
void CDockAreaTabBar::onTabCloseRequested()
|
|
||||||
{
|
|
||||||
CDockWidgetTab* Tab = qobject_cast<CDockWidgetTab*>(sender());
|
|
||||||
int Index = d->TabsLayout->indexOf(Tab);
|
|
||||||
closeTab(Index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
void CDockAreaTabBar::onCloseOtherTabsRequested()
|
|
||||||
{
|
|
||||||
auto Sender = qobject_cast<CDockWidgetTab*>(sender());
|
|
||||||
for (int i = 0; i < count(); ++i)
|
|
||||||
{
|
|
||||||
auto Tab = tab(i);
|
|
||||||
if (Tab->isClosable() && !Tab->isHidden() && Tab != Sender)
|
|
||||||
{
|
|
||||||
// If the dock widget is deleted with the closeTab() call, its tab
|
|
||||||
// it will no longer be in the layout, and thus the index needs to
|
|
||||||
// be updated to not skip any tabs
|
|
||||||
int Offset = Tab->dockWidget()->features().testFlag(
|
|
||||||
CDockWidget::DockWidgetDeleteOnClose) ? 1 : 0;
|
|
||||||
closeTab(i);
|
|
||||||
|
|
||||||
// If the the dock widget blocks closing, i.e. if the flag
|
|
||||||
// CustomCloseHandling is set, and the dock widget is still open,
|
|
||||||
// then we do not need to correct the index
|
|
||||||
if (Tab->dockWidget()->isClosed())
|
|
||||||
{
|
|
||||||
i -= Offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
CDockWidgetTab* CDockAreaTabBar::tab(int Index) const
|
|
||||||
{
|
|
||||||
if (Index >= count() || Index < 0)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return qobject_cast<CDockWidgetTab*>(d->TabsLayout->itemAt(Index)->widget());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
void CDockAreaTabBar::onTabWidgetMoved(const QPoint& GlobalPos)
|
|
||||||
{
|
|
||||||
CDockWidgetTab* MovingTab = qobject_cast<CDockWidgetTab*>(sender());
|
|
||||||
if (!MovingTab)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fromIndex = d->TabsLayout->indexOf(MovingTab);
|
|
||||||
auto MousePos = mapFromGlobal(GlobalPos);
|
|
||||||
int toIndex = -1;
|
|
||||||
// Find tab under mouse
|
|
||||||
for (int i = 0; i < count(); ++i)
|
|
||||||
{
|
|
||||||
CDockWidgetTab* DropTab = tab(i);
|
|
||||||
if (DropTab == MovingTab || !DropTab->isVisibleTo(this)
|
|
||||||
|| !DropTab->geometry().contains(MousePos))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
toIndex = d->TabsLayout->indexOf(DropTab);
|
|
||||||
if (toIndex == fromIndex)
|
|
||||||
{
|
|
||||||
toIndex = -1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toIndex < 0)
|
|
||||||
{
|
|
||||||
toIndex = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now check if the mouse is behind the last tab
|
|
||||||
if (toIndex < 0)
|
|
||||||
{
|
|
||||||
if (MousePos.x() > tab(count() - 1)->geometry().right())
|
|
||||||
{
|
|
||||||
ADS_PRINT("after all tabs");
|
|
||||||
toIndex = count() - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
toIndex = fromIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
d->TabsLayout->removeWidget(MovingTab);
|
|
||||||
d->TabsLayout->insertWidget(toIndex, MovingTab);
|
|
||||||
if (toIndex >= 0)
|
|
||||||
{
|
|
||||||
ADS_PRINT("tabMoved from " << fromIndex << " to " << toIndex);
|
|
||||||
emit tabMoved(fromIndex, toIndex);
|
|
||||||
setCurrentIndex(toIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
void CDockAreaTabBar::closeTab(int Index)
|
|
||||||
{
|
|
||||||
if (Index < 0 || Index >= count())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Tab = tab(Index);
|
|
||||||
if (Tab->isHidden())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//Tab->hide();
|
|
||||||
emit tabCloseRequested(Index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
bool CDockAreaTabBar::eventFilter(QObject *watched, QEvent *event)
|
|
||||||
{
|
|
||||||
bool Result = Super::eventFilter(watched, event);
|
|
||||||
CDockWidgetTab* Tab = qobject_cast<CDockWidgetTab*>(watched);
|
|
||||||
if (!Tab)
|
|
||||||
{
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (event->type())
|
|
||||||
{
|
|
||||||
case QEvent::Hide:
|
|
||||||
emit tabClosed(d->TabsLayout->indexOf(Tab)); break;
|
|
||||||
case QEvent::Show:
|
|
||||||
emit tabOpened(d->TabsLayout->indexOf(Tab)); break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
bool CDockAreaTabBar::isTabOpen(int Index) const
|
|
||||||
{
|
|
||||||
if (Index < 0 || Index >= count())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !tab(Index)->isHidden();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
QSize CDockAreaTabBar::minimumSizeHint() const
|
|
||||||
{
|
|
||||||
QSize Size = sizeHint();
|
|
||||||
Size.setWidth(Super::minimumSizeHint().width());// this defines the minimum width of a dock area
|
|
||||||
return Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
QSize CDockAreaTabBar::sizeHint() const
|
|
||||||
{
|
|
||||||
QSize Size = Super::sizeHint();
|
|
||||||
Size.setHeight(d->TabsContainerWidget->sizeHint().height());
|
|
||||||
return Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
eDragState CDockAreaTabBar::dragState() const
|
|
||||||
{
|
|
||||||
return d->DragState;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// EOF DockAreaTabBar.cpp
|
|
@ -1,247 +0,0 @@
|
|||||||
#ifndef DockAreaTabBarH
|
|
||||||
#define DockAreaTabBarH
|
|
||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockAreaTabBar.h
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 24.08.2018
|
|
||||||
/// \brief Declaration of CDockAreaTabBar class
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include <QScrollArea>
|
|
||||||
|
|
||||||
#include "ads_globals.h"
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
class CDockAreaWidget;
|
|
||||||
class CDockWidgetTab;
|
|
||||||
struct DockAreaTabBarPrivate;
|
|
||||||
class CDockAreaTitleBar;
|
|
||||||
class CFloatingDockContainer;
|
|
||||||
class IFloatingWidget;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Custom tabbar implementation for tab area that is shown on top of a
|
|
||||||
* dock area widget.
|
|
||||||
* The tabbar displays the tab widgets of the contained dock widgets.
|
|
||||||
* We cannot use QTabBar here because it does a lot of fancy animations
|
|
||||||
* that will crash the application if a tab is removed while the animation
|
|
||||||
* has not finished. And we need to remove a tab, if the user drags a
|
|
||||||
* a dock widget out of a group of tabbed widgets
|
|
||||||
*/
|
|
||||||
class CDockAreaTabBar : public QScrollArea
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
private:
|
|
||||||
DockAreaTabBarPrivate* d; ///< private data (pimpl)
|
|
||||||
friend struct DockAreaTabBarPrivate;
|
|
||||||
friend class CDockAreaTitleBar;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onTabClicked();
|
|
||||||
void onTabCloseRequested();
|
|
||||||
void onCloseOtherTabsRequested();
|
|
||||||
void onTabWidgetMoved(const QPoint& GlobalPos);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void wheelEvent(QWheelEvent* Event) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores mouse position to detect dragging
|
|
||||||
*/
|
|
||||||
virtual void mousePressEvent(QMouseEvent* ev) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores mouse position to detect dragging
|
|
||||||
*/
|
|
||||||
virtual void mouseReleaseEvent(QMouseEvent* ev) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts floating the complete docking area including all dock widgets,
|
|
||||||
* if it is not the last dock area in a floating widget
|
|
||||||
*/
|
|
||||||
virtual void mouseMoveEvent(QMouseEvent* ev) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Double clicking the title bar also starts floating of the complete area
|
|
||||||
*/
|
|
||||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts floating
|
|
||||||
*/
|
|
||||||
void startFloating(const QPoint& Offset);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes the dock area floating
|
|
||||||
*/
|
|
||||||
IFloatingWidget* makeAreaFloating(const QPoint& Offset, eDragState DragState);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current drag state
|
|
||||||
*/
|
|
||||||
eDragState dragState() const;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
using Super = QScrollArea;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default Constructor
|
|
||||||
*/
|
|
||||||
CDockAreaTabBar(CDockAreaWidget* parent);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual Destructor
|
|
||||||
*/
|
|
||||||
virtual ~CDockAreaTabBar();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts the given dock widget tab at the given position.
|
|
||||||
* Inserting a new tab at an index less than or equal to the current index
|
|
||||||
* will increment the current index, but keep the current tab.
|
|
||||||
*/
|
|
||||||
void insertTab(int Index, CDockWidgetTab* Tab);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the given DockWidgetTab from the tabbar
|
|
||||||
*/
|
|
||||||
void removeTab(CDockWidgetTab* Tab);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of tabs in this tabbar
|
|
||||||
*/
|
|
||||||
int count() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current index or -1 if no tab is selected
|
|
||||||
*/
|
|
||||||
int currentIndex() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current tab or a nullptr if no tab is selected.
|
|
||||||
*/
|
|
||||||
CDockWidgetTab* currentTab() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the tab with the given index
|
|
||||||
*/
|
|
||||||
CDockWidgetTab* tab(int Index) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filters the tab widget events
|
|
||||||
*/
|
|
||||||
virtual bool eventFilter(QObject *watched, QEvent *event) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns true if the tab is open, that means if it is
|
|
||||||
* visible to the user. If the function returns false, the tab is
|
|
||||||
* closed
|
|
||||||
*/
|
|
||||||
bool isTabOpen(int Index) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overrides the minimumSizeHint() function of QScrollArea
|
|
||||||
* The minimumSizeHint() is bigger than the sizeHint () for the scroll
|
|
||||||
* area because even if the scrollbars are invisible, the required speace
|
|
||||||
* is reserved in the minimumSizeHint(). This override simply returns
|
|
||||||
* sizeHint();
|
|
||||||
*/
|
|
||||||
virtual QSize minimumSizeHint() const override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The function provides a sizeHint that matches the height of the
|
|
||||||
* internal viewport.
|
|
||||||
*/
|
|
||||||
virtual QSize sizeHint() const override;
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
/**
|
|
||||||
* This property sets the index of the tab bar's visible tab
|
|
||||||
*/
|
|
||||||
void setCurrentIndex(int Index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function will close the tab given in Index param.
|
|
||||||
* Closing a tab means, the tab will be hidden, it will not be removed
|
|
||||||
*/
|
|
||||||
void closeTab(int Index);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
/**
|
|
||||||
* This signal is emitted when the tab bar's current tab is about to be changed. The new
|
|
||||||
* current has the given index, or -1 if there isn't a new one.
|
|
||||||
*/
|
|
||||||
void currentChanging(int Index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted when the tab bar's current tab changes. The new
|
|
||||||
* current has the given index, or -1 if there isn't a new one
|
|
||||||
*/
|
|
||||||
void currentChanged(int Index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted when user clicks on a tab
|
|
||||||
*/
|
|
||||||
void tabBarClicked(int index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted when the close button on a tab is clicked.
|
|
||||||
* The index is the index that should be closed.
|
|
||||||
*/
|
|
||||||
void tabCloseRequested(int index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted if a tab has been closed
|
|
||||||
*/
|
|
||||||
void tabClosed(int index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted if a tab has been opened.
|
|
||||||
* A tab is opened if it has been made visible
|
|
||||||
*/
|
|
||||||
void tabOpened(int index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted when the tab has moved the tab at index position
|
|
||||||
* from to index position to.
|
|
||||||
*/
|
|
||||||
void tabMoved(int from, int to);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted, just before the tab with the given index is
|
|
||||||
* removed
|
|
||||||
*/
|
|
||||||
void removingTab(int index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted if a tab has been inserted
|
|
||||||
*/
|
|
||||||
void tabInserted(int index);
|
|
||||||
}; // class CDockAreaTabBar
|
|
||||||
} // namespace ads
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#endif // DockAreaTabBarH
|
|
||||||
|
|
@ -1,386 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockAreaTitleBar.cpp
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 12.10.2018
|
|
||||||
/// \brief Implementation of CDockAreaTitleBar class
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include "DockAreaTitleBar.h"
|
|
||||||
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QToolButton>
|
|
||||||
#include <QBoxLayout>
|
|
||||||
#include <QStyle>
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QScrollArea>
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
#include "ads_globals.h"
|
|
||||||
#include "FloatingDockContainer.h"
|
|
||||||
#include "DockAreaWidget.h"
|
|
||||||
#include "DockOverlay.h"
|
|
||||||
#include "DockManager.h"
|
|
||||||
#include "DockWidget.h"
|
|
||||||
#include "DockWidgetTab.h"
|
|
||||||
#include "DockAreaTabBar.h"
|
|
||||||
#include "IconProvider.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
using tTileBarButton = QToolButton;
|
|
||||||
/**
|
|
||||||
* Private data class of CDockAreaTitleBar class (pimpl)
|
|
||||||
*/
|
|
||||||
struct DockAreaTitleBarPrivate
|
|
||||||
{
|
|
||||||
CDockAreaTitleBar* _this;
|
|
||||||
tTileBarButton* TabsMenuButton;
|
|
||||||
tTileBarButton* UndockButton;
|
|
||||||
tTileBarButton* CloseButton;
|
|
||||||
QBoxLayout* TopLayout;
|
|
||||||
CDockAreaWidget* DockArea;
|
|
||||||
CDockAreaTabBar* TabBar;
|
|
||||||
bool MenuOutdated = true;
|
|
||||||
QMenu* TabsMenu;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data constructor
|
|
||||||
*/
|
|
||||||
DockAreaTitleBarPrivate(CDockAreaTitleBar* _public);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the title bar close and menu buttons
|
|
||||||
*/
|
|
||||||
void createButtons();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the internal TabBar
|
|
||||||
*/
|
|
||||||
void createTabBar();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience function for DockManager access
|
|
||||||
*/
|
|
||||||
CDockManager* dockManager() const
|
|
||||||
{
|
|
||||||
return DockArea->dockManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the given config flag is set
|
|
||||||
*/
|
|
||||||
bool testConfigFlag(CDockManager::eConfigFlag Flag) const
|
|
||||||
{
|
|
||||||
return CDockManager::configFlags().testFlag(Flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to set title bar button icons depending on operating
|
|
||||||
* system and to avoid duplicated code. On windows the standard icons
|
|
||||||
* are blurry since Qt 5.11 so we need to do some additional steps.
|
|
||||||
* If the global IconPovider of the dockmanager provides a custom
|
|
||||||
* Icon for the given CustomIconId, the this icon will be used.
|
|
||||||
*/
|
|
||||||
void setTitleBarButtonIcon(tTileBarButton* Button, QStyle::StandardPixmap StandarPixmap,
|
|
||||||
ads::eIcon CustomIconId)
|
|
||||||
{
|
|
||||||
// First we try to use custom icons if available
|
|
||||||
QIcon Icon = CDockManager::iconProvider().customIcon(CustomIconId);
|
|
||||||
if (!Icon.isNull())
|
|
||||||
{
|
|
||||||
Button->setIcon(Icon);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
Button->setIcon(_this->style()->standardIcon(StandarPixmap));
|
|
||||||
#else
|
|
||||||
QPixmap normalPixmap = _this->style()->standardPixmap(StandarPixmap, 0, Button);
|
|
||||||
Icon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled);
|
|
||||||
Icon.addPixmap(normalPixmap, QIcon::Normal);
|
|
||||||
Button->setIcon(Icon);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
};// struct DockAreaTitleBarPrivate
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
DockAreaTitleBarPrivate::DockAreaTitleBarPrivate(CDockAreaTitleBar* _public) :
|
|
||||||
_this(_public)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockAreaTitleBarPrivate::createButtons()
|
|
||||||
{
|
|
||||||
QSizePolicy ButtonSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
|
||||||
// Tabs menu button
|
|
||||||
TabsMenuButton = new tTileBarButton();
|
|
||||||
TabsMenuButton->setObjectName("tabsMenuButton");
|
|
||||||
TabsMenuButton->setAutoRaise(true);
|
|
||||||
TabsMenuButton->setPopupMode(QToolButton::InstantPopup);
|
|
||||||
setTitleBarButtonIcon(TabsMenuButton, QStyle::SP_TitleBarUnshadeButton, ads::DockAreaMenuIcon);
|
|
||||||
QMenu* TabsMenu = new QMenu(TabsMenuButton);
|
|
||||||
#ifndef QT_NO_TOOLTIP
|
|
||||||
TabsMenu->setToolTipsVisible(true);
|
|
||||||
#endif
|
|
||||||
_this->connect(TabsMenu, SIGNAL(aboutToShow()), SLOT(onTabsMenuAboutToShow()));
|
|
||||||
TabsMenuButton->setMenu(TabsMenu);
|
|
||||||
#ifndef QT_NO_TOOLTIP
|
|
||||||
TabsMenuButton->setToolTip(QObject::tr("List all tabs"));
|
|
||||||
#endif
|
|
||||||
TabsMenuButton->setSizePolicy(ButtonSizePolicy);
|
|
||||||
TopLayout->addWidget(TabsMenuButton, 0);
|
|
||||||
_this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)),
|
|
||||||
SLOT(onTabsMenuActionTriggered(QAction*)));
|
|
||||||
|
|
||||||
|
|
||||||
// Undock button
|
|
||||||
UndockButton = new tTileBarButton();
|
|
||||||
UndockButton->setObjectName("undockButton");
|
|
||||||
UndockButton->setAutoRaise(true);
|
|
||||||
#ifndef QT_NO_TOOLTIP
|
|
||||||
UndockButton->setToolTip(QObject::tr("Detach Group"));
|
|
||||||
#endif
|
|
||||||
setTitleBarButtonIcon(UndockButton, QStyle::SP_TitleBarNormalButton, ads::DockAreaUndockIcon);
|
|
||||||
UndockButton->setSizePolicy(ButtonSizePolicy);
|
|
||||||
TopLayout->addWidget(UndockButton, 0);
|
|
||||||
_this->connect(UndockButton, SIGNAL(clicked()), SLOT(onUndockButtonClicked()));
|
|
||||||
|
|
||||||
|
|
||||||
// Close button
|
|
||||||
CloseButton = new tTileBarButton();
|
|
||||||
CloseButton->setObjectName("closeButton");
|
|
||||||
CloseButton->setAutoRaise(true);
|
|
||||||
setTitleBarButtonIcon(CloseButton, QStyle::SP_TitleBarCloseButton, ads::DockAreaCloseIcon);
|
|
||||||
#ifndef QT_NO_TOOLTIP
|
|
||||||
if (testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
|
|
||||||
{
|
|
||||||
CloseButton->setToolTip(QObject::tr("Close Active Tab"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CloseButton->setToolTip(QObject::tr("Close Group"));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
CloseButton->setSizePolicy(ButtonSizePolicy);
|
|
||||||
CloseButton->setIconSize(QSize(16, 16));
|
|
||||||
if (testConfigFlag(CDockManager::DockAreaHasCloseButton))
|
|
||||||
{
|
|
||||||
TopLayout->addWidget(CloseButton, 0);
|
|
||||||
}
|
|
||||||
_this->connect(CloseButton, SIGNAL(clicked()), SLOT(onCloseButtonClicked()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockAreaTitleBarPrivate::createTabBar()
|
|
||||||
{
|
|
||||||
TabBar = new CDockAreaTabBar(DockArea);
|
|
||||||
TopLayout->addWidget(TabBar);
|
|
||||||
_this->connect(TabBar, SIGNAL(tabClosed(int)), SLOT(markTabsMenuOutdated()));
|
|
||||||
_this->connect(TabBar, SIGNAL(tabOpened(int)), SLOT(markTabsMenuOutdated()));
|
|
||||||
_this->connect(TabBar, SIGNAL(tabInserted(int)), SLOT(markTabsMenuOutdated()));
|
|
||||||
_this->connect(TabBar, SIGNAL(removingTab(int)), SLOT(markTabsMenuOutdated()));
|
|
||||||
_this->connect(TabBar, SIGNAL(tabMoved(int, int)), SLOT(markTabsMenuOutdated()));
|
|
||||||
_this->connect(TabBar, SIGNAL(currentChanged(int)), SLOT(onCurrentTabChanged(int)));
|
|
||||||
_this->connect(TabBar, SIGNAL(tabBarClicked(int)), SIGNAL(tabBarClicked(int)));
|
|
||||||
|
|
||||||
TabBar->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
||||||
_this->connect(TabBar, SIGNAL(customContextMenuRequested(const QPoint&)),
|
|
||||||
SLOT(showContextMenu(const QPoint&)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockAreaTitleBar::CDockAreaTitleBar(CDockAreaWidget* parent) :
|
|
||||||
QFrame(parent),
|
|
||||||
d(new DockAreaTitleBarPrivate(this))
|
|
||||||
{
|
|
||||||
d->DockArea = parent;
|
|
||||||
|
|
||||||
setObjectName("dockAreaTitleBar");
|
|
||||||
d->TopLayout = new QBoxLayout(QBoxLayout::LeftToRight);
|
|
||||||
d->TopLayout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
d->TopLayout->setSpacing(0);
|
|
||||||
setLayout(d->TopLayout);
|
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
|
||||||
|
|
||||||
d->createTabBar();
|
|
||||||
d->createButtons();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockAreaTitleBar::~CDockAreaTitleBar()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockAreaTabBar* CDockAreaTitleBar::tabBar() const
|
|
||||||
{
|
|
||||||
return d->TabBar;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaTitleBar::markTabsMenuOutdated()
|
|
||||||
{
|
|
||||||
d->MenuOutdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaTitleBar::onTabsMenuAboutToShow()
|
|
||||||
{
|
|
||||||
if (!d->MenuOutdated)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMenu* menu = d->TabsMenuButton->menu();
|
|
||||||
menu->clear();
|
|
||||||
for (int i = 0; i < d->TabBar->count(); ++i)
|
|
||||||
{
|
|
||||||
if (!d->TabBar->isTabOpen(i))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto Tab = d->TabBar->tab(i);
|
|
||||||
QAction* Action = menu->addAction(Tab->icon(), Tab->text());
|
|
||||||
#ifndef QT_NO_TOOLTIP
|
|
||||||
Action->setToolTip(Tab->toolTip());
|
|
||||||
#endif
|
|
||||||
Action->setData(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
d->MenuOutdated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaTitleBar::onCloseButtonClicked()
|
|
||||||
{
|
|
||||||
ADS_PRINT("CDockAreaTitleBar::onCloseButtonClicked");
|
|
||||||
if (d->testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
|
|
||||||
{
|
|
||||||
d->TabBar->closeTab(d->TabBar->currentIndex());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d->DockArea->closeArea();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaTitleBar::onUndockButtonClicked()
|
|
||||||
{
|
|
||||||
if (d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable))
|
|
||||||
{
|
|
||||||
d->TabBar->makeAreaFloating(mapFromGlobal(QCursor::pos()), DraggingInactive);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaTitleBar::onTabsMenuActionTriggered(QAction* Action)
|
|
||||||
{
|
|
||||||
int Index = Action->data().toInt();
|
|
||||||
d->TabBar->setCurrentIndex(Index);
|
|
||||||
emit tabBarClicked(Index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaTitleBar::onCurrentTabChanged(int Index)
|
|
||||||
{
|
|
||||||
if (Index < 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d->testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
|
|
||||||
{
|
|
||||||
CDockWidget* DockWidget = d->TabBar->tab(Index)->dockWidget();
|
|
||||||
d->CloseButton->setEnabled(DockWidget->features().testFlag(CDockWidget::DockWidgetClosable));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QAbstractButton* CDockAreaTitleBar::button(TitleBarButton which) const
|
|
||||||
{
|
|
||||||
switch (which)
|
|
||||||
{
|
|
||||||
case TitleBarButtonTabsMenu: return d->TabsMenuButton;
|
|
||||||
case TitleBarButtonUndock: return d->UndockButton;
|
|
||||||
case TitleBarButtonClose: return d->CloseButton;
|
|
||||||
default:
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaTitleBar::setVisible(bool Visible)
|
|
||||||
{
|
|
||||||
Super::setVisible(Visible);
|
|
||||||
markTabsMenuOutdated();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaTitleBar::showContextMenu(const QPoint& pos)
|
|
||||||
{
|
|
||||||
if (d->TabBar->dragState() == DraggingFloatingWidget)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMenu Menu(this);
|
|
||||||
auto Action = Menu.addAction(tr("Detach Area"), this, SLOT(onUndockButtonClicked()));
|
|
||||||
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable));
|
|
||||||
Menu.addSeparator();
|
|
||||||
Action = Menu.addAction(tr("Close Area"), this, SLOT(onCloseButtonClicked()));
|
|
||||||
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetClosable));
|
|
||||||
Menu.addAction(tr("Close Other Areas"), d->DockArea, SLOT(closeOtherAreas()));
|
|
||||||
Menu.exec(mapToGlobal(pos));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// EOF DockAreaTitleBar.cpp
|
|
@ -1,112 +0,0 @@
|
|||||||
#ifndef DockAreaTitleBarH
|
|
||||||
#define DockAreaTitleBarH
|
|
||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockAreaTitleBar.h
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 12.10.2018
|
|
||||||
/// \brief Declaration of CDockAreaTitleBar class
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include <QFrame>
|
|
||||||
|
|
||||||
#include "ads_globals.h"
|
|
||||||
|
|
||||||
class QAbstractButton;
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
class CDockAreaTabBar;
|
|
||||||
class CDockAreaWidget;
|
|
||||||
struct DockAreaTitleBarPrivate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Title bar of a dock area.
|
|
||||||
* The title bar contains a tabbar with all tabs for a dock widget group and
|
|
||||||
* with a tabs menu button, a undock button and a close button.
|
|
||||||
*/
|
|
||||||
class CDockAreaTitleBar : public QFrame
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
private:
|
|
||||||
DockAreaTitleBarPrivate* d; ///< private data (pimpl)
|
|
||||||
friend struct DockAreaTitleBarPrivate;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onTabsMenuAboutToShow();
|
|
||||||
void onCloseButtonClicked();
|
|
||||||
void onUndockButtonClicked();
|
|
||||||
void onTabsMenuActionTriggered(QAction* Action);
|
|
||||||
void onCurrentTabChanged(int Index);
|
|
||||||
void showContextMenu(const QPoint& pos);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
/**
|
|
||||||
* Call this slot to tell the title bar that it should update the tabs menu
|
|
||||||
* the next time it is shown.
|
|
||||||
*/
|
|
||||||
void markTabsMenuOutdated();
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
using Super = QFrame;
|
|
||||||
/**
|
|
||||||
* Default Constructor
|
|
||||||
*/
|
|
||||||
CDockAreaTitleBar(CDockAreaWidget* parent);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual Destructor
|
|
||||||
*/
|
|
||||||
virtual ~CDockAreaTitleBar();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the pointer to the tabBar()
|
|
||||||
*/
|
|
||||||
CDockAreaTabBar* tabBar() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the button corresponding to the given title bar button identifier
|
|
||||||
*/
|
|
||||||
QAbstractButton* button(TitleBarButton which) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Marks the tabs menu outdated before it calls its base class
|
|
||||||
* implementation
|
|
||||||
*/
|
|
||||||
virtual void setVisible(bool Visible) override;
|
|
||||||
|
|
||||||
|
|
||||||
signals:
|
|
||||||
/**
|
|
||||||
* This signal is emitted if a tab in the tab bar is clicked by the user
|
|
||||||
* or if the user clicks on a tab item in the title bar tab menu.
|
|
||||||
*/
|
|
||||||
void tabBarClicked(int index);
|
|
||||||
}; // class name
|
|
||||||
}
|
|
||||||
// namespace ads
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#endif // DockAreaTitleBarH
|
|
@ -1,846 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockAreaWidget.cpp
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 24.02.2017
|
|
||||||
/// \brief Implementation of CDockAreaWidget class
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include "DockWidgetTab.h"
|
|
||||||
#include "DockAreaWidget.h"
|
|
||||||
|
|
||||||
#include <QStackedLayout>
|
|
||||||
#include <QScrollBar>
|
|
||||||
#include <QScrollArea>
|
|
||||||
#include <QWheelEvent>
|
|
||||||
#include <QStyle>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QSplitter>
|
|
||||||
#include <QXmlStreamWriter>
|
|
||||||
#include <QVector>
|
|
||||||
#include <QList>
|
|
||||||
|
|
||||||
|
|
||||||
#include "DockContainerWidget.h"
|
|
||||||
#include "DockWidget.h"
|
|
||||||
#include "FloatingDockContainer.h"
|
|
||||||
#include "DockManager.h"
|
|
||||||
#include "DockOverlay.h"
|
|
||||||
#include "DockAreaTabBar.h"
|
|
||||||
#include "DockSplitter.h"
|
|
||||||
#include "DockAreaTitleBar.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
static const char* const INDEX_PROPERTY = "index";
|
|
||||||
static const char* const ACTION_PROPERTY = "action";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal dock area layout mimics stack layout but only inserts the current
|
|
||||||
* widget into the internal QLayout object.
|
|
||||||
* \warning Only the current widget has a parent. All other widgets
|
|
||||||
* do not have a parent. That means, a widget that is in this layout may
|
|
||||||
* return nullptr for its parent() function if it is not the current widget.
|
|
||||||
*/
|
|
||||||
class CDockAreaLayout
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
QBoxLayout* m_ParentLayout;
|
|
||||||
QList<QWidget*> m_Widgets;
|
|
||||||
int m_CurrentIndex = -1;
|
|
||||||
QWidget* m_CurrentWidget = nullptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Creates an instance with the given parent layout
|
|
||||||
*/
|
|
||||||
CDockAreaLayout(QBoxLayout* ParentLayout)
|
|
||||||
: m_ParentLayout(ParentLayout)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of widgets in this layout
|
|
||||||
*/
|
|
||||||
int count() const
|
|
||||||
{
|
|
||||||
return m_Widgets.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts the widget at the given index position into the internal widget
|
|
||||||
* list
|
|
||||||
*/
|
|
||||||
void insertWidget(int index, QWidget* Widget)
|
|
||||||
{
|
|
||||||
Widget->setParent(nullptr);
|
|
||||||
if (index < 0)
|
|
||||||
{
|
|
||||||
index = m_Widgets.count();
|
|
||||||
}
|
|
||||||
m_Widgets.insert(index, Widget);
|
|
||||||
if (m_CurrentIndex < 0)
|
|
||||||
{
|
|
||||||
setCurrentIndex(index);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (index <= m_CurrentIndex )
|
|
||||||
{
|
|
||||||
++m_CurrentIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the given widget from the layout
|
|
||||||
*/
|
|
||||||
void removeWidget(QWidget* Widget)
|
|
||||||
{
|
|
||||||
if (currentWidget() == Widget)
|
|
||||||
{
|
|
||||||
auto LayoutItem = m_ParentLayout->takeAt(1);
|
|
||||||
if (LayoutItem)
|
|
||||||
{
|
|
||||||
LayoutItem->widget()->setParent(nullptr);
|
|
||||||
}
|
|
||||||
m_CurrentWidget = nullptr;
|
|
||||||
m_CurrentIndex = -1;
|
|
||||||
}
|
|
||||||
m_Widgets.removeOne(Widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current selected widget
|
|
||||||
*/
|
|
||||||
QWidget* currentWidget() const
|
|
||||||
{
|
|
||||||
return m_CurrentWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Activates the widget with the give index.
|
|
||||||
*/
|
|
||||||
void setCurrentIndex(int index)
|
|
||||||
{
|
|
||||||
QWidget *prev = currentWidget();
|
|
||||||
QWidget *next = widget(index);
|
|
||||||
if (!next || (next == prev && !m_CurrentWidget))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool reenableUpdates = false;
|
|
||||||
QWidget *parent = m_ParentLayout->parentWidget();
|
|
||||||
|
|
||||||
if (parent && parent->updatesEnabled())
|
|
||||||
{
|
|
||||||
reenableUpdates = true;
|
|
||||||
parent->setUpdatesEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto LayoutItem = m_ParentLayout->takeAt(1);
|
|
||||||
if (LayoutItem)
|
|
||||||
{
|
|
||||||
LayoutItem->widget()->setParent(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_ParentLayout->addWidget(next);
|
|
||||||
if (prev)
|
|
||||||
{
|
|
||||||
prev->hide();
|
|
||||||
}
|
|
||||||
m_CurrentIndex = index;
|
|
||||||
m_CurrentWidget = next;
|
|
||||||
|
|
||||||
|
|
||||||
if (reenableUpdates)
|
|
||||||
{
|
|
||||||
parent->setUpdatesEnabled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the index of the current active widget
|
|
||||||
*/
|
|
||||||
int currentIndex() const
|
|
||||||
{
|
|
||||||
return m_CurrentIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if there are no widgets in the layout
|
|
||||||
*/
|
|
||||||
bool isEmpty() const
|
|
||||||
{
|
|
||||||
return m_Widgets.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the index of the given widget
|
|
||||||
*/
|
|
||||||
int indexOf(QWidget* w) const
|
|
||||||
{
|
|
||||||
return m_Widgets.indexOf(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the widget for the given index
|
|
||||||
*/
|
|
||||||
QWidget* widget(int index) const
|
|
||||||
{
|
|
||||||
return (index < m_Widgets.size()) ? m_Widgets.at(index) : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the geometry of the current active widget
|
|
||||||
*/
|
|
||||||
QRect geometry() const
|
|
||||||
{
|
|
||||||
return m_Widgets.empty() ? QRect() : currentWidget()->geometry();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
using DockAreaLayout = CDockAreaLayout;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data class of CDockAreaWidget class (pimpl)
|
|
||||||
*/
|
|
||||||
struct DockAreaWidgetPrivate
|
|
||||||
{
|
|
||||||
CDockAreaWidget* _this = nullptr;
|
|
||||||
QBoxLayout* Layout = nullptr;
|
|
||||||
DockAreaLayout* ContentsLayout = nullptr;
|
|
||||||
CDockAreaTitleBar* TitleBar = nullptr;
|
|
||||||
CDockManager* DockManager = nullptr;
|
|
||||||
bool UpdateTitleBarButtons = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data constructor
|
|
||||||
*/
|
|
||||||
DockAreaWidgetPrivate(CDockAreaWidget* _public);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the layout for top area with tabs and close button
|
|
||||||
*/
|
|
||||||
void createTitleBar();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
CDockWidgetTab* tabWidgetAt(int index)
|
|
||||||
{
|
|
||||||
return dockWidgetAt(index)->tabWidget();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience function for tabbar access
|
|
||||||
*/
|
|
||||||
CDockAreaTabBar* tabBar() const
|
|
||||||
{
|
|
||||||
return TitleBar->tabBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Udpates the enable state of the close and detach button
|
|
||||||
*/
|
|
||||||
void updateTitleBarButtonStates();
|
|
||||||
};
|
|
||||||
// struct DockAreaWidgetPrivate
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
DockAreaWidgetPrivate::DockAreaWidgetPrivate(CDockAreaWidget* _public) :
|
|
||||||
_this(_public)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockAreaWidgetPrivate::createTitleBar()
|
|
||||||
{
|
|
||||||
TitleBar = new CDockAreaTitleBar(_this);
|
|
||||||
Layout->addWidget(TitleBar);
|
|
||||||
QObject::connect(tabBar(), &CDockAreaTabBar::tabCloseRequested, _this, &CDockAreaWidget::onTabCloseRequested);
|
|
||||||
QObject::connect(TitleBar, &CDockAreaTitleBar::tabBarClicked, _this, &CDockAreaWidget::setCurrentIndex);
|
|
||||||
QObject::connect(tabBar(), &CDockAreaTabBar::tabMoved, _this, &CDockAreaWidget::reorderDockWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockAreaWidgetPrivate::updateTitleBarButtonStates()
|
|
||||||
{
|
|
||||||
if (_this->isHidden())
|
|
||||||
{
|
|
||||||
UpdateTitleBarButtons = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TitleBar->button(TitleBarButtonClose)->setEnabled(
|
|
||||||
_this->features().testFlag(CDockWidget::DockWidgetClosable));
|
|
||||||
TitleBar->button(TitleBarButtonUndock)->setEnabled(
|
|
||||||
_this->features().testFlag(CDockWidget::DockWidgetFloatable));
|
|
||||||
UpdateTitleBarButtons = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
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->createTitleBar();
|
|
||||||
d->ContentsLayout = new DockAreaLayout(d->Layout);
|
|
||||||
if (d->DockManager)
|
|
||||||
{
|
|
||||||
emit d->DockManager->dockAreaCreated(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockAreaWidget::~CDockAreaWidget()
|
|
||||||
{
|
|
||||||
ADS_PRINT("~CDockAreaWidget()");
|
|
||||||
delete d->ContentsLayout;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockManager* CDockAreaWidget::dockManager() const
|
|
||||||
{
|
|
||||||
return d->DockManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockContainerWidget* CDockAreaWidget::dockContainer() const
|
|
||||||
{
|
|
||||||
return internal::findParent<CDockContainerWidget*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::addDockWidget(CDockWidget* DockWidget)
|
|
||||||
{
|
|
||||||
insertDockWidget(d->ContentsLayout->count(), DockWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
|
|
||||||
bool Activate)
|
|
||||||
{
|
|
||||||
d->ContentsLayout->insertWidget(index, DockWidget);
|
|
||||||
DockWidget->tabWidget()->setDockAreaWidget(this);
|
|
||||||
auto TabWidget = DockWidget->tabWidget();
|
|
||||||
// Inserting the tab will change the current index which in turn will
|
|
||||||
// make the tab widget visible in the slot
|
|
||||||
d->tabBar()->blockSignals(true);
|
|
||||||
d->tabBar()->insertTab(index, TabWidget);
|
|
||||||
d->tabBar()->blockSignals(false);
|
|
||||||
TabWidget->setVisible(!DockWidget->isClosed());
|
|
||||||
DockWidget->setProperty(INDEX_PROPERTY, index);
|
|
||||||
if (Activate)
|
|
||||||
{
|
|
||||||
setCurrentIndex(index);
|
|
||||||
}
|
|
||||||
DockWidget->setDockArea(this);
|
|
||||||
d->updateTitleBarButtonStates();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
|
|
||||||
{
|
|
||||||
ADS_PRINT("CDockAreaWidget::removeDockWidget");
|
|
||||||
auto NextOpenDockWidget = nextOpenDockWidget(DockWidget);
|
|
||||||
|
|
||||||
d->ContentsLayout->removeWidget(DockWidget);
|
|
||||||
auto TabWidget = DockWidget->tabWidget();
|
|
||||||
TabWidget->hide();
|
|
||||||
d->tabBar()->removeTab(TabWidget);
|
|
||||||
CDockContainerWidget* DockContainer = dockContainer();
|
|
||||||
if (NextOpenDockWidget)
|
|
||||||
{
|
|
||||||
setCurrentDockWidget(NextOpenDockWidget);
|
|
||||||
}
|
|
||||||
else if (d->ContentsLayout->isEmpty() && DockContainer->dockAreaCount() > 1)
|
|
||||||
{
|
|
||||||
ADS_PRINT("Dock Area empty");
|
|
||||||
DockContainer->removeDockArea(this);
|
|
||||||
this->deleteLater();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// if contents layout is not empty but there are no more open dock
|
|
||||||
// widgets, then we need to hide the dock area because it does not
|
|
||||||
// contain any visible content
|
|
||||||
hideAreaWithNoVisibleContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
d->updateTitleBarButtonStates();
|
|
||||||
updateTitleBarVisibility();
|
|
||||||
auto TopLevelDockWidget = DockContainer->topLevelDockWidget();
|
|
||||||
if (TopLevelDockWidget)
|
|
||||||
{
|
|
||||||
TopLevelDockWidget->emitTopLevelChanged(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (ADS_DEBUG_LEVEL > 0)
|
|
||||||
DockContainer->dumpLayout();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::hideAreaWithNoVisibleContent()
|
|
||||||
{
|
|
||||||
this->toggleView(false);
|
|
||||||
|
|
||||||
// Hide empty parent splitters
|
|
||||||
auto Splitter = internal::findParent<CDockSplitter*>(this);
|
|
||||||
internal::hideEmptyParentSplitters(Splitter);
|
|
||||||
|
|
||||||
//Hide empty floating widget
|
|
||||||
CDockContainerWidget* Container = this->dockContainer();
|
|
||||||
if (!Container->isFloating())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateTitleBarVisibility();
|
|
||||||
auto TopLevelWidget = Container->topLevelDockWidget();
|
|
||||||
auto FloatingWidget = Container->floatingWidget();
|
|
||||||
if (TopLevelWidget)
|
|
||||||
{
|
|
||||||
FloatingWidget->updateWindowTitle();
|
|
||||||
CDockWidget::emitTopLevelEventForWidget(TopLevelWidget, true);
|
|
||||||
}
|
|
||||||
else if (Container->openedDockAreas().isEmpty())
|
|
||||||
{
|
|
||||||
FloatingWidget->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::onTabCloseRequested(int Index)
|
|
||||||
{
|
|
||||||
ADS_PRINT("CDockAreaWidget::onTabCloseRequested " << Index);
|
|
||||||
auto* DockWidget = dockWidget(Index);
|
|
||||||
if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
|
|
||||||
{
|
|
||||||
//DockWidget->deleteDockWidget();
|
|
||||||
DockWidget->closeDockWidgetInternal();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DockWidget->toggleView(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockWidget* CDockAreaWidget::currentDockWidget() const
|
|
||||||
{
|
|
||||||
int CurrentIndex = currentIndex();
|
|
||||||
if (CurrentIndex < 0)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dockWidget(CurrentIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::setCurrentDockWidget(CDockWidget* DockWidget)
|
|
||||||
{
|
|
||||||
if (dockManager()->isRestoringState())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
internalSetCurrentDockWidget(DockWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::internalSetCurrentDockWidget(CDockWidget* DockWidget)
|
|
||||||
{
|
|
||||||
int Index = index(DockWidget);
|
|
||||||
if (Index < 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setCurrentIndex(Index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::setCurrentIndex(int index)
|
|
||||||
{
|
|
||||||
auto TabBar = d->tabBar();
|
|
||||||
if (index < 0 || index > (TabBar->count() - 1))
|
|
||||||
{
|
|
||||||
qWarning() << Q_FUNC_INFO << "Invalid index" << index;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto cw = d->ContentsLayout->currentWidget();
|
|
||||||
auto nw = d->ContentsLayout->widget(index);
|
|
||||||
if (cw == nw && !nw->isHidden())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit currentChanging(index);
|
|
||||||
TabBar->setCurrentIndex(index);
|
|
||||||
d->ContentsLayout->setCurrentIndex(index);
|
|
||||||
d->ContentsLayout->currentWidget()->show();
|
|
||||||
emit currentChanged(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
int CDockAreaWidget::currentIndex() const
|
|
||||||
{
|
|
||||||
return d->ContentsLayout->currentIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QRect CDockAreaWidget::titleBarGeometry() const
|
|
||||||
{
|
|
||||||
return d->TitleBar->geometry();
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QRect CDockAreaWidget::contentAreaGeometry() const
|
|
||||||
{
|
|
||||||
return d->ContentsLayout->geometry();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
int CDockAreaWidget::index(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::openDockWidgetsCount() const
|
|
||||||
{
|
|
||||||
int Count = 0;
|
|
||||||
for (int i = 0; i < d->ContentsLayout->count(); ++i)
|
|
||||||
{
|
|
||||||
if (!dockWidget(i)->isClosed())
|
|
||||||
{
|
|
||||||
++Count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
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::indexOfFirstOpenDockWidget() const
|
|
||||||
{
|
|
||||||
for (int i = 0; i < d->ContentsLayout->count(); ++i)
|
|
||||||
{
|
|
||||||
if (!dockWidget(i)->isClosed())
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
int CDockAreaWidget::dockWidgetsCount() const
|
|
||||||
{
|
|
||||||
return d->ContentsLayout->count();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockWidget* CDockAreaWidget::dockWidget(int Index) const
|
|
||||||
{
|
|
||||||
return qobject_cast<CDockWidget*>(d->ContentsLayout->widget(Index));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex)
|
|
||||||
{
|
|
||||||
ADS_PRINT("CDockAreaWidget::reorderDockWidget");
|
|
||||||
if (fromIndex >= d->ContentsLayout->count() || fromIndex < 0
|
|
||||||
|| toIndex >= d->ContentsLayout->count() || toIndex < 0 || fromIndex == toIndex)
|
|
||||||
{
|
|
||||||
ADS_PRINT("Invalid index for tab movement" << fromIndex << toIndex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Widget = d->ContentsLayout->widget(fromIndex);
|
|
||||||
d->ContentsLayout->removeWidget(Widget);
|
|
||||||
d->ContentsLayout->insertWidget(toIndex, Widget);
|
|
||||||
setCurrentIndex(toIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::toggleDockWidgetView(CDockWidget* DockWidget, bool Open)
|
|
||||||
{
|
|
||||||
Q_UNUSED(DockWidget);
|
|
||||||
Q_UNUSED(Open);
|
|
||||||
updateTitleBarVisibility();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::updateTitleBarVisibility()
|
|
||||||
{
|
|
||||||
CDockContainerWidget* Container = dockContainer();
|
|
||||||
if (!Container)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d->TitleBar)
|
|
||||||
{
|
|
||||||
d->TitleBar->setVisible(!Container->isFloating() || !Container->hasTopLevelDockWidget());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::markTitleBarMenuOutdated()
|
|
||||||
{
|
|
||||||
if (d->TitleBar)
|
|
||||||
{
|
|
||||||
d->TitleBar->markTabsMenuOutdated();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::saveState(QXmlStreamWriter& s) const
|
|
||||||
{
|
|
||||||
s.writeStartElement("Area");
|
|
||||||
s.writeAttribute("Tabs", QString::number(d->ContentsLayout->count()));
|
|
||||||
auto CurrentDockWidget = currentDockWidget();
|
|
||||||
QString Name = CurrentDockWidget ? CurrentDockWidget->objectName() : "";
|
|
||||||
s.writeAttribute("Current", Name);
|
|
||||||
ADS_PRINT("CDockAreaWidget::saveState TabCount: " << d->ContentsLayout->count()
|
|
||||||
<< " Current: " << Name);
|
|
||||||
for (int i = 0; i < d->ContentsLayout->count(); ++i)
|
|
||||||
{
|
|
||||||
dockWidget(i)->saveState(s);
|
|
||||||
}
|
|
||||||
s.writeEndElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockWidget* CDockAreaWidget::nextOpenDockWidget(CDockWidget* DockWidget) const
|
|
||||||
{
|
|
||||||
auto OpenDockWidgets = openedDockWidgets();
|
|
||||||
if (OpenDockWidgets.count() > 1 || (OpenDockWidgets.count() == 1 && OpenDockWidgets[0] != DockWidget))
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockWidget::DockWidgetFeatures CDockAreaWidget::features(eBitwiseOperator Mode) const
|
|
||||||
{
|
|
||||||
if (BitwiseAnd == Mode)
|
|
||||||
{
|
|
||||||
CDockWidget::DockWidgetFeatures Features(CDockWidget::AllDockWidgetFeatures);
|
|
||||||
for (const auto DockWidget : dockWidgets())
|
|
||||||
{
|
|
||||||
Features &= DockWidget->features();
|
|
||||||
}
|
|
||||||
return Features;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CDockWidget::DockWidgetFeatures Features(CDockWidget::NoDockWidgetFeatures);
|
|
||||||
for (const auto DockWidget : dockWidgets())
|
|
||||||
{
|
|
||||||
Features |= DockWidget->features();
|
|
||||||
}
|
|
||||||
return Features;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::toggleView(bool Open)
|
|
||||||
{
|
|
||||||
setVisible(Open);
|
|
||||||
|
|
||||||
emit viewToggled(Open);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::setVisible(bool Visible)
|
|
||||||
{
|
|
||||||
Super::setVisible(Visible);
|
|
||||||
if (d->UpdateTitleBarButtons)
|
|
||||||
{
|
|
||||||
d->updateTitleBarButtonStates();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QAbstractButton* CDockAreaWidget::titleBarButton(TitleBarButton which) const
|
|
||||||
{
|
|
||||||
return d->TitleBar->button(which);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::closeArea()
|
|
||||||
{
|
|
||||||
// If there is only one single dock widget and this widget has the
|
|
||||||
// DeleteOnClose feature, then we delete the dock widget now
|
|
||||||
auto OpenDockWidgets = openedDockWidgets();
|
|
||||||
if (OpenDockWidgets.count() == 1 && OpenDockWidgets[0]->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
|
|
||||||
{
|
|
||||||
OpenDockWidgets[0]->closeDockWidgetInternal();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (auto DockWidget : openedDockWidgets())
|
|
||||||
{
|
|
||||||
DockWidget->toggleView(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockAreaWidget::closeOtherAreas()
|
|
||||||
{
|
|
||||||
dockContainer()->closeOtherAreas(this);
|
|
||||||
}
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// EOF DockAreaWidget.cpp
|
|
@ -1,303 +0,0 @@
|
|||||||
#ifndef DockAreaWidgetH
|
|
||||||
#define DockAreaWidgetH
|
|
||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockAreaWidget.h
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 24.02.2017
|
|
||||||
/// \brief Declaration of CDockAreaWidget class
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include <QFrame>
|
|
||||||
|
|
||||||
#include "DockWidget.h"
|
|
||||||
|
|
||||||
class QXmlStreamWriter;
|
|
||||||
class QAbstractButton;
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
struct DockAreaWidgetPrivate;
|
|
||||||
class CDockManager;
|
|
||||||
class CDockContainerWidget;
|
|
||||||
class DockContainerWidgetPrivate;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DockAreaWidget manages multiple instances of DockWidgets.
|
|
||||||
* It displays a title tab, which is clickable and will switch to
|
|
||||||
* the contents associated to the title when clicked.
|
|
||||||
*/
|
|
||||||
class CDockAreaWidget : public QFrame
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
private:
|
|
||||||
DockAreaWidgetPrivate* d; ///< private data (pimpl)
|
|
||||||
friend struct DockAreaWidgetPrivate;
|
|
||||||
friend class CDockContainerWidget;
|
|
||||||
friend class DockContainerWidgetPrivate;
|
|
||||||
friend class CDockWidgetTab;
|
|
||||||
friend struct DockWidgetPrivate;
|
|
||||||
friend class CDockWidget;
|
|
||||||
friend struct DockManagerPrivate;
|
|
||||||
friend class CDockManager;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onTabCloseRequested(int Index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reorder the index position of DockWidget at fromIndx to toIndex
|
|
||||||
* if a tab in the tabbar is dragged from one index to another one
|
|
||||||
*/
|
|
||||||
void reorderDockWidget(int fromIndex, int toIndex);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Inserts a dock widget into dock area.
|
|
||||||
* All dockwidgets in the dock area tabified in a stacked layout with tabs.
|
|
||||||
* The index indicates the index of the new dockwidget in the tabbar and
|
|
||||||
* in the stacked layout. If the Activate parameter is true, the new
|
|
||||||
* DockWidget will be the active one in the stacked layout
|
|
||||||
*/
|
|
||||||
void insertDockWidget(int index, CDockWidget* DockWidget, bool Activate = true);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a new dock widget to dock area.
|
|
||||||
* All dockwidgets in the dock area tabified in a stacked layout with tabs
|
|
||||||
*/
|
|
||||||
void addDockWidget(CDockWidget* DockWidget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the given dock widget from the dock area
|
|
||||||
*/
|
|
||||||
void removeDockWidget(CDockWidget* DockWidget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called from dock widget if it is opened or closed
|
|
||||||
*/
|
|
||||||
void toggleDockWidgetView(CDockWidget* DockWidget, bool Open);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a helper function to get the next open dock widget to activate
|
|
||||||
* if the given DockWidget will be closed or removed.
|
|
||||||
* The function returns the next widget that should be activated or
|
|
||||||
* nullptr in case there are no more open widgets in this area.
|
|
||||||
*/
|
|
||||||
CDockWidget* nextOpenDockWidget(CDockWidget* DockWidget) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the index of the given DockWidget in the internal layout
|
|
||||||
*/
|
|
||||||
int index(CDockWidget* DockWidget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call this function, if you already know, that the dock does not
|
|
||||||
* contain any visible content (any open dock widgets).
|
|
||||||
*/
|
|
||||||
void hideAreaWithNoVisibleContent();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the dock area layout and components visibility
|
|
||||||
*/
|
|
||||||
void updateTitleBarVisibility();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the internal private function for setting the current widget.
|
|
||||||
* This function is called by the public setCurrentDockWidget() function
|
|
||||||
* and by the dock manager when restoring the state
|
|
||||||
*/
|
|
||||||
void internalSetCurrentDockWidget(CDockWidget* DockWidget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Marks tabs menu to update
|
|
||||||
*/
|
|
||||||
void markTitleBarMenuOutdated();
|
|
||||||
|
|
||||||
protected slots:
|
|
||||||
void toggleView(bool Open);
|
|
||||||
|
|
||||||
public:
|
|
||||||
using Super = QFrame;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default Constructor
|
|
||||||
*/
|
|
||||||
CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual Destructor
|
|
||||||
*/
|
|
||||||
virtual ~CDockAreaWidget();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the dock manager object this dock area belongs to
|
|
||||||
*/
|
|
||||||
CDockManager* dockManager() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the dock container widget this dock area widget belongs to or 0
|
|
||||||
* if there is no
|
|
||||||
*/
|
|
||||||
CDockContainerWidget* dockContainer() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the rectangle of the title area
|
|
||||||
*/
|
|
||||||
QRect titleBarGeometry() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the rectangle of the content
|
|
||||||
*/
|
|
||||||
QRect contentAreaGeometry() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of dock widgets in this area
|
|
||||||
*/
|
|
||||||
int dockWidgetsCount() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of all dock widgets in this dock area.
|
|
||||||
* This list contains open and closed dock widgets.
|
|
||||||
*/
|
|
||||||
QList<CDockWidget*> dockWidgets() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of open dock widgets in this area
|
|
||||||
*/
|
|
||||||
int openDockWidgetsCount() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of dock widgets that are not closed.
|
|
||||||
*/
|
|
||||||
QList<CDockWidget*> openedDockWidgets() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a dock widget by its index
|
|
||||||
*/
|
|
||||||
CDockWidget* dockWidget(int Index) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the index of the current active dock widget or -1 if there
|
|
||||||
* are is no active dock widget (ie.e if all dock widgets are closed)
|
|
||||||
*/
|
|
||||||
int currentIndex() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the index of the first open dock widgets in the list of
|
|
||||||
* dock widgets.
|
|
||||||
* This function is here for performance reasons. Normally it would
|
|
||||||
* be possible to take the first dock widget from the list returned by
|
|
||||||
* openedDockWidgets() function. But that function enumerates all
|
|
||||||
* dock widgets while this functions stops after the first open dock widget.
|
|
||||||
* If there are no open dock widgets, the function returns -1.
|
|
||||||
*/
|
|
||||||
int indexOfFirstOpenDockWidget() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current active dock widget or a nullptr if there is no
|
|
||||||
* active dock widget (i.e. if all dock widgets are closed)
|
|
||||||
*/
|
|
||||||
CDockWidget* currentDockWidget() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the tab with the given dock widget
|
|
||||||
*/
|
|
||||||
void setCurrentDockWidget(CDockWidget* DockWidget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the state into the given stream
|
|
||||||
*/
|
|
||||||
void saveState(QXmlStreamWriter& Stream) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This functions returns the dock widget features of all dock widget in
|
|
||||||
* this area.
|
|
||||||
* A bitwise and is used to combine the flags of all dock widgets. That
|
|
||||||
* means, if only one single dock widget does not support a certain flag,
|
|
||||||
* the whole dock are does not support the flag. I.e. if one single
|
|
||||||
* dock widget in this area is not closable, the whole dock are is not
|
|
||||||
* closable.
|
|
||||||
*/
|
|
||||||
CDockWidget::DockWidgetFeatures features(eBitwiseOperator Mode = BitwiseAnd) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the title bar button corresponding to the given title bar
|
|
||||||
* button identifier
|
|
||||||
*/
|
|
||||||
QAbstractButton* titleBarButton(TitleBarButton which) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the close button if visibility changed
|
|
||||||
*/
|
|
||||||
virtual void setVisible(bool Visible) override;
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
/**
|
|
||||||
* This activates the tab for the given tab index.
|
|
||||||
* If the dock widget for the given tab is not visible, the this function
|
|
||||||
* call will make it visible.
|
|
||||||
*/
|
|
||||||
void setCurrentIndex(int index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the dock area and all dock widgets in this area
|
|
||||||
*/
|
|
||||||
void closeArea();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function closes all other areas except of this area
|
|
||||||
*/
|
|
||||||
void closeOtherAreas();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
/**
|
|
||||||
* This signal is emitted when user clicks on a tab at an index.
|
|
||||||
*/
|
|
||||||
void tabBarClicked(int index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted when the tab bar's current tab is about to be changed. The new
|
|
||||||
* current has the given index, or -1 if there isn't a new one.
|
|
||||||
* @param index
|
|
||||||
*/
|
|
||||||
void currentChanging(int index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted when the tab bar's current tab changes. The new
|
|
||||||
* current has the given index, or -1 if there isn't a new one
|
|
||||||
* @param index
|
|
||||||
*/
|
|
||||||
void currentChanged(int index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted if the visibility of this dock area is toggled
|
|
||||||
* via toggle view function
|
|
||||||
*/
|
|
||||||
void viewToggled(bool Open);
|
|
||||||
}; // class DockAreaWidget
|
|
||||||
}
|
|
||||||
// namespace ads
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#endif // DockAreaWidgetH
|
|
File diff suppressed because it is too large
Load Diff
@ -1,278 +0,0 @@
|
|||||||
#ifndef DockContainerWidgetH
|
|
||||||
#define DockContainerWidgetH
|
|
||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockContainerWidget.h
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 24.02.2017
|
|
||||||
/// \brief Declaration of CDockContainerWidget class
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include <QFrame>
|
|
||||||
|
|
||||||
#include "DockWidget.h"
|
|
||||||
|
|
||||||
class QXmlStreamWriter;
|
|
||||||
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
class DockContainerWidgetPrivate;
|
|
||||||
class CDockAreaWidget;
|
|
||||||
class CDockWidget;
|
|
||||||
class CDockManager;
|
|
||||||
struct DockManagerPrivate;
|
|
||||||
class CFloatingDockContainer;
|
|
||||||
struct FloatingDockContainerPrivate;
|
|
||||||
class CFloatingDragPreview;
|
|
||||||
struct FloatingDragPreviewPrivate;
|
|
||||||
class CDockingStateReader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Container that manages a number of dock areas with single dock widgets
|
|
||||||
* or tabyfied dock widgets in each area.
|
|
||||||
* Each window that support docking has a DockContainerWidget. That means
|
|
||||||
* the main application window and all floating windows are ore contain
|
|
||||||
* an DockContainerWidget.
|
|
||||||
*/
|
|
||||||
class CDockContainerWidget : public QFrame
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
private:
|
|
||||||
DockContainerWidgetPrivate* d; ///< private data (pimpl)
|
|
||||||
friend class DockContainerWidgetPrivate;
|
|
||||||
friend class CDockManager;
|
|
||||||
friend struct DockManagerPrivate;
|
|
||||||
friend class CDockAreaWidget;
|
|
||||||
friend struct DockAreaWidgetPrivate;
|
|
||||||
friend class CFloatingDockContainer;
|
|
||||||
friend struct FloatingDockContainerPrivate;
|
|
||||||
friend class CDockWidget;
|
|
||||||
friend class CFloatingDragPreview;
|
|
||||||
friend struct FloatingDragPreviewPrivate;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Handles activation events to update zOrderIndex
|
|
||||||
*/
|
|
||||||
virtual bool event(QEvent *e) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Access function for the internal root splitter
|
|
||||||
*/
|
|
||||||
QSplitter* rootSplitter() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function for creation of the root splitter
|
|
||||||
*/
|
|
||||||
void createRootSplitter();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Drop floating widget into the container
|
|
||||||
*/
|
|
||||||
void dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Drop a dock area or a dock widget given in widget parameter
|
|
||||||
*/
|
|
||||||
void dropWidget(QWidget* Widget, const QPoint& TargetPos);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the given dock area to this container widget
|
|
||||||
*/
|
|
||||||
void addDockArea(CDockAreaWidget* DockAreaWidget, DockWidgetArea area = CenterDockWidgetArea);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the given dock area from this container
|
|
||||||
*/
|
|
||||||
void removeDockArea(CDockAreaWidget* area);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the state into the given stream
|
|
||||||
*/
|
|
||||||
void saveState(QXmlStreamWriter& Stream) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restores the state from given stream.
|
|
||||||
* If Testing is true, the function only parses the data from the given
|
|
||||||
* stream but does not restore anything. You can use this check for
|
|
||||||
* faulty files before you start restoring the state
|
|
||||||
*/
|
|
||||||
bool restoreState(CDockingStateReader& Stream, bool Testing);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns the last added dock area widget for the given
|
|
||||||
* area identifier or 0 if no dock area widget has been added for the given
|
|
||||||
* area
|
|
||||||
*/
|
|
||||||
CDockAreaWidget* lastAddedDockAreaWidget(DockWidgetArea area) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns true if this dock area has only one single
|
|
||||||
* visible dock widget.
|
|
||||||
* A top level widget is a real floating widget. Only the isFloating()
|
|
||||||
* function of top level widgets may returns true.
|
|
||||||
*/
|
|
||||||
bool hasTopLevelDockWidget() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If hasSingleVisibleDockWidget() returns true, this function returns the
|
|
||||||
* one and only visible dock widget. Otherwise it returns a nullptr.
|
|
||||||
*/
|
|
||||||
CDockWidget* topLevelDockWidget() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the top level dock area.
|
|
||||||
*/
|
|
||||||
CDockAreaWidget* topLevelDockArea() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns a list of all dock widgets in this floating widget.
|
|
||||||
* It may be possible, depending on the implementation, that dock widgets,
|
|
||||||
* that are not visible to the user have no parent widget. Therefore simply
|
|
||||||
* calling findChildren() would not work here. Therefore this function
|
|
||||||
* iterates over all dock areas and creates a list that contains all
|
|
||||||
* dock widgets returned from all dock areas.
|
|
||||||
*/
|
|
||||||
QList<CDockWidget*> dockWidgets() const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Default Constructor
|
|
||||||
*/
|
|
||||||
CDockContainerWidget(CDockManager* DockManager, QWidget* parent = 0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual Destructor
|
|
||||||
*/
|
|
||||||
virtual ~CDockContainerWidget();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds dockwidget into the given area.
|
|
||||||
* If DockAreaWidget is not null, then the area parameter indicates the area
|
|
||||||
* into the DockAreaWidget. If DockAreaWidget is null, the Dockwidget will
|
|
||||||
* be dropped into the container.
|
|
||||||
* \return Returns the dock area widget that contains the new DockWidget
|
|
||||||
*/
|
|
||||||
CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
|
|
||||||
CDockAreaWidget* DockAreaWidget = nullptr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes dockwidget
|
|
||||||
*/
|
|
||||||
void removeDockWidget(CDockWidget* Dockwidget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current zOrderIndex
|
|
||||||
*/
|
|
||||||
virtual unsigned int zOrderIndex() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns true if this container widgets z order index is
|
|
||||||
* higher than the index of the container widget given in Other parameter
|
|
||||||
*/
|
|
||||||
bool isInFrontOf(CDockContainerWidget* Other) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the dock area at teh given global position or 0 if there is no
|
|
||||||
* dock area at this position
|
|
||||||
*/
|
|
||||||
CDockAreaWidget* dockAreaAt(const QPoint& GlobalPos) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the dock area at the given Index or 0 if the index is out of
|
|
||||||
* range
|
|
||||||
*/
|
|
||||||
CDockAreaWidget* dockArea(int Index) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the list of dock areas that are not closed
|
|
||||||
* If all dock widgets in a dock area are closed, the dock area will be closed
|
|
||||||
*/
|
|
||||||
QList<CDockAreaWidget*> openedDockAreas() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of dock areas in this container
|
|
||||||
*/
|
|
||||||
int dockAreaCount() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of visible dock areas
|
|
||||||
*/
|
|
||||||
int visibleDockAreaCount() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns true, if this container is in a floating widget
|
|
||||||
*/
|
|
||||||
bool isFloating() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dumps the layout for debugging purposes
|
|
||||||
*/
|
|
||||||
void dumpLayout();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This functions returns the dock widget features of all dock widget in
|
|
||||||
* this container.
|
|
||||||
* A bitwise and is used to combine the flags of all dock widgets. That
|
|
||||||
* means, if only dock widget does not support a certain flag, the whole
|
|
||||||
* dock are does not support the flag.
|
|
||||||
*/
|
|
||||||
CDockWidget::DockWidgetFeatures features() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If this dock container is in a floating widget, this function returns
|
|
||||||
* the floating widget.
|
|
||||||
* Else, it returns a nullptr.
|
|
||||||
*/
|
|
||||||
CFloatingDockContainer* floatingWidget() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call this function to close all dock areas except the KeepOpenArea
|
|
||||||
*/
|
|
||||||
void closeOtherAreas(CDockAreaWidget* KeepOpenArea);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
/**
|
|
||||||
* This signal is emitted if one or multiple dock areas has been added to
|
|
||||||
* the internal list of dock areas.
|
|
||||||
* If multiple dock areas are inserted, this signal is emitted only once
|
|
||||||
*/
|
|
||||||
void dockAreasAdded();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted if one or multiple dock areas has been removed
|
|
||||||
*/
|
|
||||||
void dockAreasRemoved();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted if a dock area is opened or closed via
|
|
||||||
* toggleView() function
|
|
||||||
*/
|
|
||||||
void dockAreaViewToggled(CDockAreaWidget* DockArea, bool Open);
|
|
||||||
}; // class DockContainerWidget
|
|
||||||
} // namespace ads
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#endif // DockContainerWidgetH
|
|
@ -1,852 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockManager.cpp
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 26.02.2017
|
|
||||||
/// \brief Implementation of CDockManager class
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include "DockWidgetTab.h"
|
|
||||||
#include "DockManager.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <QMainWindow>
|
|
||||||
#include <QList>
|
|
||||||
#include <QMap>
|
|
||||||
#include <QVariant>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QAction>
|
|
||||||
#include <QXmlStreamWriter>
|
|
||||||
#include <QSettings>
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QApplication>
|
|
||||||
|
|
||||||
#include "FloatingDockContainer.h"
|
|
||||||
#include "DockOverlay.h"
|
|
||||||
#include "DockWidget.h"
|
|
||||||
#include "ads_globals.h"
|
|
||||||
#include "DockAreaWidget.h"
|
|
||||||
#include "IconProvider.h"
|
|
||||||
#include "DockingStateReader.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
static CDockManager::ConfigFlags StaticConfigFlags = CDockManager::DefaultConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data class of CDockManager class (pimpl)
|
|
||||||
*/
|
|
||||||
struct DockManagerPrivate
|
|
||||||
{
|
|
||||||
CDockManager* _this;
|
|
||||||
QList<CFloatingDockContainer*> FloatingWidgets;
|
|
||||||
QList<CDockContainerWidget*> Containers;
|
|
||||||
CDockOverlay* ContainerOverlay;
|
|
||||||
CDockOverlay* DockAreaOverlay;
|
|
||||||
QMap<QString, CDockWidget*> DockWidgetsMap;
|
|
||||||
QMap<QString, QByteArray> Perspectives;
|
|
||||||
QMap<QString, QMenu*> ViewMenuGroups;
|
|
||||||
QMenu* ViewMenu;
|
|
||||||
CDockManager::eViewMenuInsertionOrder MenuInsertionOrder = CDockManager::MenuAlphabeticallySorted;
|
|
||||||
bool RestoringState = false;
|
|
||||||
QVector<CFloatingDockContainer*> UninitializedFloatingWidgets;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data constructor
|
|
||||||
*/
|
|
||||||
DockManagerPrivate(CDockManager* _public);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the given data stream is a valid docking system state
|
|
||||||
* file.
|
|
||||||
*/
|
|
||||||
bool checkFormat(const QByteArray &state, int version);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restores the state
|
|
||||||
*/
|
|
||||||
bool restoreStateFromXml(const QByteArray &state, int version, bool Testing = internal::Restore);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restore state
|
|
||||||
*/
|
|
||||||
bool restoreState(const QByteArray &state, int version);
|
|
||||||
|
|
||||||
void restoreDockWidgetsOpenState();
|
|
||||||
void restoreDockAreasIndices();
|
|
||||||
void emitTopLevelEvents();
|
|
||||||
|
|
||||||
void hideFloatingWidgets()
|
|
||||||
{
|
|
||||||
// Hide updates of floating widgets from user
|
|
||||||
for (auto FloatingWidget : FloatingWidgets)
|
|
||||||
{
|
|
||||||
FloatingWidget->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void markDockWidgetsDirty()
|
|
||||||
{
|
|
||||||
for (auto DockWidget : DockWidgetsMap)
|
|
||||||
{
|
|
||||||
DockWidget->setProperty("dirty", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restores the container with the given index
|
|
||||||
*/
|
|
||||||
bool restoreContainer(int Index, CDockingStateReader& stream, bool Testing);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the stylesheet
|
|
||||||
*/
|
|
||||||
void loadStylesheet();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds action to menu - optionally in sorted order
|
|
||||||
*/
|
|
||||||
void addActionToMenu(QAction* Action, QMenu* Menu, bool InsertSorted);
|
|
||||||
};
|
|
||||||
// struct DockManagerPrivate
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
DockManagerPrivate::DockManagerPrivate(CDockManager* _public) :
|
|
||||||
_this(_public)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockManagerPrivate::loadStylesheet()
|
|
||||||
{
|
|
||||||
QString Result;
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
QFile StyleSheetFile(":ads/stylesheets/default_linux.css");
|
|
||||||
#else
|
|
||||||
QFile StyleSheetFile(":ads/stylesheets/default.css");
|
|
||||||
#endif
|
|
||||||
StyleSheetFile.open(QIODevice::ReadOnly);
|
|
||||||
QTextStream StyleSheetStream(&StyleSheetFile);
|
|
||||||
Result = StyleSheetStream.readAll();
|
|
||||||
StyleSheetFile.close();
|
|
||||||
_this->setStyleSheet(Result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool DockManagerPrivate::restoreContainer(int Index, CDockingStateReader& stream, bool Testing)
|
|
||||||
{
|
|
||||||
if (Testing)
|
|
||||||
{
|
|
||||||
Index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Result = false;
|
|
||||||
if (Index >= Containers.count())
|
|
||||||
{
|
|
||||||
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this);
|
|
||||||
Result = FloatingWidget->restoreState(stream, Testing);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ADS_PRINT("d->Containers[i]->restoreState ");
|
|
||||||
auto Container = Containers[Index];
|
|
||||||
if (Container->isFloating())
|
|
||||||
{
|
|
||||||
Result = Container->floatingWidget()->restoreState(stream, Testing);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Result = Container->restoreState(stream, Testing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool DockManagerPrivate::checkFormat(const QByteArray &state, int version)
|
|
||||||
{
|
|
||||||
return restoreStateFromXml(state, version, internal::RestoreTesting);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool DockManagerPrivate::restoreStateFromXml(const QByteArray &state, int version,
|
|
||||||
bool Testing)
|
|
||||||
{
|
|
||||||
Q_UNUSED(version);
|
|
||||||
|
|
||||||
if (state.isEmpty())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
CDockingStateReader s(state);
|
|
||||||
s.readNextStartElement();
|
|
||||||
if (s.name().toString() != "QtAdvancedDockingSystem")
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ADS_PRINT(s.attributes().value("Version"));
|
|
||||||
bool ok;
|
|
||||||
int v = s.attributes().value("Version").toInt(&ok);
|
|
||||||
if (!ok || v > CurrentVersion)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
s.setFileVersion(v);
|
|
||||||
bool Result = true;
|
|
||||||
#ifdef ADS_DEBUG_PRINT
|
|
||||||
int DockContainers = s.attributes().value("Containers").toInt();
|
|
||||||
#endif
|
|
||||||
ADS_PRINT(DockContainers);
|
|
||||||
int DockContainerCount = 0;
|
|
||||||
while (s.readNextStartElement())
|
|
||||||
{
|
|
||||||
if (s.name().toString() == "Container")
|
|
||||||
{
|
|
||||||
Result = restoreContainer(DockContainerCount, s, Testing);
|
|
||||||
if (!Result)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
DockContainerCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Testing)
|
|
||||||
{
|
|
||||||
// Delete remaining empty floating widgets
|
|
||||||
int FloatingWidgetIndex = DockContainerCount - 1;
|
|
||||||
int DeleteCount = FloatingWidgets.count() - FloatingWidgetIndex;
|
|
||||||
for (int i = 0; i < DeleteCount; ++i)
|
|
||||||
{
|
|
||||||
FloatingWidgets[FloatingWidgetIndex + i]->deleteLater();
|
|
||||||
_this->removeDockContainer(FloatingWidgets[FloatingWidgetIndex + i]->dockContainer());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockManagerPrivate::restoreDockWidgetsOpenState()
|
|
||||||
{
|
|
||||||
// All dock widgets, that have not been processed in the restore state
|
|
||||||
// function are invisible to the user now and have no assigned dock area
|
|
||||||
// They do not belong to any dock container, until the user toggles the
|
|
||||||
// toggle view action the next time
|
|
||||||
for (auto DockWidget : DockWidgetsMap)
|
|
||||||
{
|
|
||||||
if (DockWidget->property(internal::DirtyProperty).toBool())
|
|
||||||
{
|
|
||||||
DockWidget->flagAsUnassigned();
|
|
||||||
emit DockWidget->viewToggled(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DockWidget->toggleViewInternal(!DockWidget->property(internal::ClosedProperty).toBool());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockManagerPrivate::restoreDockAreasIndices()
|
|
||||||
{
|
|
||||||
// Now all dock areas are properly restored and we setup the index of
|
|
||||||
// The dock areas because the previous toggleView() action has changed
|
|
||||||
// the dock area index
|
|
||||||
int Count = 0;
|
|
||||||
for (auto DockContainer : Containers)
|
|
||||||
{
|
|
||||||
Count++;
|
|
||||||
for (int i = 0; i < DockContainer->dockAreaCount(); ++i)
|
|
||||||
{
|
|
||||||
CDockAreaWidget* DockArea = DockContainer->dockArea(i);
|
|
||||||
QString DockWidgetName = DockArea->property("currentDockWidget").toString();
|
|
||||||
CDockWidget* DockWidget = nullptr;
|
|
||||||
if (!DockWidgetName.isEmpty())
|
|
||||||
{
|
|
||||||
DockWidget = _this->findDockWidget(DockWidgetName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DockWidget || DockWidget->isClosed())
|
|
||||||
{
|
|
||||||
int Index = DockArea->indexOfFirstOpenDockWidget();
|
|
||||||
if (Index < 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
DockArea->setCurrentIndex(Index);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DockArea->internalSetCurrentDockWidget(DockWidget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockManagerPrivate::emitTopLevelEvents()
|
|
||||||
{
|
|
||||||
// Finally we need to send the topLevelChanged() signals for all dock
|
|
||||||
// widgets if top level changed
|
|
||||||
for (auto DockContainer : Containers)
|
|
||||||
{
|
|
||||||
CDockWidget* TopLevelDockWidget = DockContainer->topLevelDockWidget();
|
|
||||||
if (TopLevelDockWidget)
|
|
||||||
{
|
|
||||||
TopLevelDockWidget->emitTopLevelChanged(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = 0; i < DockContainer->dockAreaCount(); ++i)
|
|
||||||
{
|
|
||||||
auto DockArea = DockContainer->dockArea(i);
|
|
||||||
for (auto DockWidget : DockArea->dockWidgets())
|
|
||||||
{
|
|
||||||
DockWidget->emitTopLevelChanged(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool DockManagerPrivate::restoreState(const QByteArray& State, int version)
|
|
||||||
{
|
|
||||||
QByteArray state = State.startsWith("<?xml") ? State : qUncompress(State);
|
|
||||||
if (!checkFormat(state, version))
|
|
||||||
{
|
|
||||||
ADS_PRINT("checkFormat: Error checking format!!!!!!!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide updates of floating widgets from use
|
|
||||||
hideFloatingWidgets();
|
|
||||||
markDockWidgetsDirty();
|
|
||||||
|
|
||||||
if (!restoreStateFromXml(state, version))
|
|
||||||
{
|
|
||||||
ADS_PRINT("restoreState: Error restoring state!!!!!!!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
restoreDockWidgetsOpenState();
|
|
||||||
restoreDockAreasIndices();
|
|
||||||
emitTopLevelEvents();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockManagerPrivate::addActionToMenu(QAction* Action, QMenu* Menu, bool InsertSorted)
|
|
||||||
{
|
|
||||||
if (InsertSorted)
|
|
||||||
{
|
|
||||||
auto Actions = Menu->actions();
|
|
||||||
auto it = std::find_if(Actions.begin(), Actions.end(),
|
|
||||||
[&Action](const QAction* a)
|
|
||||||
{
|
|
||||||
return a->text().compare(Action->text(), Qt::CaseInsensitive) > 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (it == Actions.end())
|
|
||||||
{
|
|
||||||
Menu->addAction(Action);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Menu->insertAction(*it, Action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Menu->addAction(Action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockManager::CDockManager(QWidget *parent) :
|
|
||||||
CDockContainerWidget(this, parent),
|
|
||||||
d(new DockManagerPrivate(this))
|
|
||||||
{
|
|
||||||
createRootSplitter();
|
|
||||||
QMainWindow* MainWindow = dynamic_cast<QMainWindow*>(parent);
|
|
||||||
if (MainWindow)
|
|
||||||
{
|
|
||||||
MainWindow->setCentralWidget(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
d->ViewMenu = new QMenu(tr("Show View"), this);
|
|
||||||
d->DockAreaOverlay = new CDockOverlay(this, CDockOverlay::ModeDockAreaOverlay);
|
|
||||||
d->ContainerOverlay = new CDockOverlay(this, CDockOverlay::ModeContainerOverlay);
|
|
||||||
d->Containers.append(this);
|
|
||||||
d->loadStylesheet();
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockManager::~CDockManager()
|
|
||||||
{
|
|
||||||
auto FloatingWidgets = d->FloatingWidgets;
|
|
||||||
for (auto FloatingWidget : FloatingWidgets)
|
|
||||||
{
|
|
||||||
delete FloatingWidget;
|
|
||||||
}
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockManager::registerFloatingWidget(CFloatingDockContainer* FloatingWidget)
|
|
||||||
{
|
|
||||||
d->FloatingWidgets.append(FloatingWidget);
|
|
||||||
ADS_PRINT("d->FloatingWidgets.count() " << d->FloatingWidgets.count());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockManager::removeFloatingWidget(CFloatingDockContainer* FloatingWidget)
|
|
||||||
{
|
|
||||||
d->FloatingWidgets.removeAll(FloatingWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockManager::registerDockContainer(CDockContainerWidget* DockContainer)
|
|
||||||
{
|
|
||||||
d->Containers.append(DockContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockManager::removeDockContainer(CDockContainerWidget* DockContainer)
|
|
||||||
{
|
|
||||||
if (this != DockContainer)
|
|
||||||
{
|
|
||||||
d->Containers.removeAll(DockContainer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockOverlay* CDockManager::containerOverlay() const
|
|
||||||
{
|
|
||||||
return d->ContainerOverlay;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockOverlay* CDockManager::dockAreaOverlay() const
|
|
||||||
{
|
|
||||||
return d->DockAreaOverlay;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
const QList<CDockContainerWidget*> CDockManager::dockContainers() const
|
|
||||||
{
|
|
||||||
return d->Containers;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
const QList<CFloatingDockContainer*> CDockManager::floatingWidgets() const
|
|
||||||
{
|
|
||||||
return d->FloatingWidgets;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
unsigned int CDockManager::zOrderIndex() const
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QByteArray CDockManager::saveState(int version) const
|
|
||||||
{
|
|
||||||
QByteArray xmldata;
|
|
||||||
QXmlStreamWriter s(&xmldata);
|
|
||||||
auto ConfigFlags = CDockManager::configFlags();
|
|
||||||
s.setAutoFormatting(ConfigFlags.testFlag(XmlAutoFormattingEnabled));
|
|
||||||
s.writeStartDocument();
|
|
||||||
s.writeStartElement("QtAdvancedDockingSystem");
|
|
||||||
s.writeAttribute("Version", QString::number(version));
|
|
||||||
s.writeAttribute("Containers", QString::number(d->Containers.count()));
|
|
||||||
for (auto Container : d->Containers)
|
|
||||||
{
|
|
||||||
Container->saveState(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
s.writeEndElement();
|
|
||||||
s.writeEndDocument();
|
|
||||||
|
|
||||||
return ConfigFlags.testFlag(XmlCompressionEnabled)
|
|
||||||
? qCompress(xmldata, 9) : xmldata;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CDockManager::restoreState(const QByteArray &state, int version)
|
|
||||||
{
|
|
||||||
// Prevent multiple calls as long as state is not restore. This may
|
|
||||||
// happen, if QApplication::processEvents() is called somewhere
|
|
||||||
if (d->RestoringState)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We hide the complete dock manager here. Restoring the state means
|
|
||||||
// that DockWidgets are removed from the DockArea internal stack layout
|
|
||||||
// which in turn means, that each time a widget is removed the stack
|
|
||||||
// will show and raise the next available widget which in turn
|
|
||||||
// triggers show events for the dock widgets. To avoid this we hide the
|
|
||||||
// dock manager. Because there will be no processing of application
|
|
||||||
// events until this function is finished, the user will not see this
|
|
||||||
// hiding
|
|
||||||
bool IsHidden = this->isHidden();
|
|
||||||
if (!IsHidden)
|
|
||||||
{
|
|
||||||
hide();
|
|
||||||
}
|
|
||||||
d->RestoringState = true;
|
|
||||||
emit restoringState();
|
|
||||||
bool Result = d->restoreState(state, version);
|
|
||||||
d->RestoringState = false;
|
|
||||||
emit stateRestored();
|
|
||||||
if (!IsHidden)
|
|
||||||
{
|
|
||||||
show();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CFloatingDockContainer* CDockManager::addDockWidgetFloating(CDockWidget* Dockwidget)
|
|
||||||
{
|
|
||||||
d->DockWidgetsMap.insert(Dockwidget->objectName(), Dockwidget);
|
|
||||||
CDockAreaWidget* OldDockArea = Dockwidget->dockAreaWidget();
|
|
||||||
if (OldDockArea)
|
|
||||||
{
|
|
||||||
OldDockArea->removeDockWidget(Dockwidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dockwidget->setDockManager(this);
|
|
||||||
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(Dockwidget);
|
|
||||||
FloatingWidget->resize(Dockwidget->size());
|
|
||||||
if (isVisible())
|
|
||||||
{
|
|
||||||
FloatingWidget->show();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d->UninitializedFloatingWidgets.append(FloatingWidget);
|
|
||||||
}
|
|
||||||
return FloatingWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockManager::showEvent(QShowEvent *event)
|
|
||||||
{
|
|
||||||
Super::showEvent(event);
|
|
||||||
if (d->UninitializedFloatingWidgets.empty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto FloatingWidget : d->UninitializedFloatingWidgets)
|
|
||||||
{
|
|
||||||
FloatingWidget->show();
|
|
||||||
}
|
|
||||||
d->UninitializedFloatingWidgets.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockAreaWidget* CDockManager::addDockWidget(DockWidgetArea area,
|
|
||||||
CDockWidget* Dockwidget, CDockAreaWidget* DockAreaWidget)
|
|
||||||
{
|
|
||||||
d->DockWidgetsMap.insert(Dockwidget->objectName(), Dockwidget);
|
|
||||||
return CDockContainerWidget::addDockWidget(area, Dockwidget, DockAreaWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockAreaWidget* CDockManager::addDockWidgetTab(DockWidgetArea area,
|
|
||||||
CDockWidget* Dockwidget)
|
|
||||||
{
|
|
||||||
CDockAreaWidget* AreaWidget = lastAddedDockAreaWidget(area);
|
|
||||||
if (AreaWidget)
|
|
||||||
{
|
|
||||||
return addDockWidget(ads::CenterDockWidgetArea, Dockwidget, AreaWidget);
|
|
||||||
}
|
|
||||||
else if (!openedDockAreas().isEmpty())
|
|
||||||
{
|
|
||||||
return addDockWidget(area, Dockwidget, openedDockAreas().last());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return addDockWidget(area, Dockwidget, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockAreaWidget* CDockManager::addDockWidgetTabToArea(CDockWidget* Dockwidget,
|
|
||||||
CDockAreaWidget* DockAreaWidget)
|
|
||||||
{
|
|
||||||
return addDockWidget(ads::CenterDockWidgetArea, Dockwidget, DockAreaWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockWidget* CDockManager::findDockWidget(const QString& ObjectName) const
|
|
||||||
{
|
|
||||||
return d->DockWidgetsMap.value(ObjectName, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockManager::removeDockWidget(CDockWidget* Dockwidget)
|
|
||||||
{
|
|
||||||
emit dockWidgetAboutToBeRemoved(Dockwidget);
|
|
||||||
d->DockWidgetsMap.remove(Dockwidget->objectName());
|
|
||||||
CDockContainerWidget::removeDockWidget(Dockwidget);
|
|
||||||
emit dockWidgetRemoved(Dockwidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QMap<QString, CDockWidget*> CDockManager::dockWidgetsMap() const
|
|
||||||
{
|
|
||||||
return d->DockWidgetsMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockManager::addPerspective(const QString& UniquePrespectiveName)
|
|
||||||
{
|
|
||||||
d->Perspectives.insert(UniquePrespectiveName, saveState());
|
|
||||||
emit perspectiveListChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockManager::removePerspective(const QString& Name)
|
|
||||||
{
|
|
||||||
removePerspectives({Name});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockManager::removePerspectives(const QStringList& Names)
|
|
||||||
{
|
|
||||||
int Count = 0;
|
|
||||||
for (auto Name : Names)
|
|
||||||
{
|
|
||||||
Count += d->Perspectives.remove(Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Count)
|
|
||||||
{
|
|
||||||
emit perspectivesRemoved();
|
|
||||||
emit perspectiveListChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QStringList CDockManager::perspectiveNames() const
|
|
||||||
{
|
|
||||||
return d->Perspectives.keys();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockManager::openPerspective(const QString& PerspectiveName)
|
|
||||||
{
|
|
||||||
const auto Iterator = d->Perspectives.find(PerspectiveName);
|
|
||||||
if (d->Perspectives.end() == Iterator)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit openingPerspective(PerspectiveName);
|
|
||||||
restoreState(Iterator.value());
|
|
||||||
emit perspectiveOpened(PerspectiveName);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockManager::savePerspectives(QSettings& Settings) const
|
|
||||||
{
|
|
||||||
Settings.beginWriteArray("Perspectives", d->Perspectives.size());
|
|
||||||
int i = 0;
|
|
||||||
for (auto it = d->Perspectives.constBegin(); it != d->Perspectives.constEnd(); ++it)
|
|
||||||
{
|
|
||||||
Settings.setArrayIndex(i);
|
|
||||||
Settings.setValue("Name", it.key());
|
|
||||||
Settings.setValue("State", it.value());
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
Settings.endArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockManager::loadPerspectives(QSettings& Settings)
|
|
||||||
{
|
|
||||||
d->Perspectives.clear();
|
|
||||||
int Size = Settings.beginReadArray("Perspectives");
|
|
||||||
if (!Size)
|
|
||||||
{
|
|
||||||
Settings.endArray();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < Size; ++i)
|
|
||||||
{
|
|
||||||
Settings.setArrayIndex(i);
|
|
||||||
QString Name = Settings.value("Name").toString();
|
|
||||||
QByteArray Data = Settings.value("State").toByteArray();
|
|
||||||
if (Name.isEmpty() || Data.isEmpty())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->Perspectives.insert(Name, Data);
|
|
||||||
}
|
|
||||||
|
|
||||||
Settings.endArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QAction* CDockManager::addToggleViewActionToMenu(QAction* ToggleViewAction,
|
|
||||||
const QString& Group, const QIcon& GroupIcon)
|
|
||||||
{
|
|
||||||
bool AlphabeticallySorted = (MenuAlphabeticallySorted == d->MenuInsertionOrder);
|
|
||||||
if (!Group.isEmpty())
|
|
||||||
{
|
|
||||||
QMenu* GroupMenu = d->ViewMenuGroups.value(Group, 0);
|
|
||||||
if (!GroupMenu)
|
|
||||||
{
|
|
||||||
GroupMenu = new QMenu(Group, this);
|
|
||||||
GroupMenu->setIcon(GroupIcon);
|
|
||||||
d->addActionToMenu(GroupMenu->menuAction(), d->ViewMenu, AlphabeticallySorted);
|
|
||||||
d->ViewMenuGroups.insert(Group, GroupMenu);
|
|
||||||
}
|
|
||||||
|
|
||||||
d->addActionToMenu(ToggleViewAction, GroupMenu, AlphabeticallySorted);
|
|
||||||
return GroupMenu->menuAction();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d->addActionToMenu(ToggleViewAction, d->ViewMenu, AlphabeticallySorted);
|
|
||||||
return ToggleViewAction;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QMenu* CDockManager::viewMenu() const
|
|
||||||
{
|
|
||||||
return d->ViewMenu;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockManager::setViewMenuInsertionOrder(eViewMenuInsertionOrder Order)
|
|
||||||
{
|
|
||||||
d->MenuInsertionOrder = Order;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
bool CDockManager::isRestoringState() const
|
|
||||||
{
|
|
||||||
return d->RestoringState;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
int CDockManager::startDragDistance()
|
|
||||||
{
|
|
||||||
return QApplication::startDragDistance() * 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
CDockManager::ConfigFlags CDockManager::configFlags()
|
|
||||||
{
|
|
||||||
return StaticConfigFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
void CDockManager::setConfigFlags(const ConfigFlags Flags)
|
|
||||||
{
|
|
||||||
StaticConfigFlags = Flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
void CDockManager::setConfigFlag(eConfigFlag Flag, bool On)
|
|
||||||
{
|
|
||||||
internal::setFlag(StaticConfigFlags, Flag, On);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
CIconProvider& CDockManager::iconProvider()
|
|
||||||
{
|
|
||||||
static CIconProvider Instance;
|
|
||||||
return Instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// EOF DockManager.cpp
|
|
@ -1,460 +0,0 @@
|
|||||||
#ifndef DockManagerH
|
|
||||||
#define DockManagerH
|
|
||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockManager.h
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 26.02.2017
|
|
||||||
/// \brief Declaration of CDockManager class
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
#include "DockContainerWidget.h"
|
|
||||||
#include "DockWidget.h"
|
|
||||||
#include "FloatingDockContainer.h"
|
|
||||||
#include <qbytearray.h>
|
|
||||||
#include <qflags.h>
|
|
||||||
#include <qlist.h>
|
|
||||||
#include <qmap.h>
|
|
||||||
#include <qobjectdefs.h>
|
|
||||||
#include <qstring.h>
|
|
||||||
#include <qstringlist.h>
|
|
||||||
#include <QtGui/qicon.h>
|
|
||||||
|
|
||||||
class QSettings;
|
|
||||||
class QMenu;
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
struct DockManagerPrivate;
|
|
||||||
class CFloatingDockContainer;
|
|
||||||
struct FloatingDockContainerPrivate;
|
|
||||||
class CDockContainerWidget;
|
|
||||||
class DockContainerWidgetPrivate;
|
|
||||||
class CDockOverlay;
|
|
||||||
class CDockAreaTabBar;
|
|
||||||
class CDockWidgetTab;
|
|
||||||
struct DockWidgetTabPrivate;
|
|
||||||
struct DockAreaWidgetPrivate;
|
|
||||||
class CIconProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The central dock manager that maintains the complete docking system.
|
|
||||||
* With the configuration flags you can globally control the functionality
|
|
||||||
* of the docking system. The dock manager uses an internal stylesheet to
|
|
||||||
* style its components like splitters, tabs and buttons. If you want to
|
|
||||||
* disable this stylesheet because your application uses its own,
|
|
||||||
* just call the function for settings the stylesheet with an empty
|
|
||||||
* string.
|
|
||||||
* \code
|
|
||||||
* DockManager->setStyleSheet("");
|
|
||||||
* \endcode
|
|
||||||
**/
|
|
||||||
class CDockManager : public CDockContainerWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
private:
|
|
||||||
DockManagerPrivate* d; ///< private data (pimpl)
|
|
||||||
friend struct DockManagerPrivate;
|
|
||||||
friend class CFloatingDockContainer;
|
|
||||||
friend struct FloatingDockContainerPrivate;
|
|
||||||
friend class CDockContainerWidget;
|
|
||||||
friend class DockContainerWidgetPrivate;
|
|
||||||
friend class CDockAreaTabBar;
|
|
||||||
friend class CDockWidgetTab;
|
|
||||||
friend struct DockAreaWidgetPrivate;
|
|
||||||
friend struct DockWidgetTabPrivate;
|
|
||||||
friend class CFloatingDragPreview;
|
|
||||||
friend struct FloatingDragPreviewPrivate;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Registers the given floating widget in the internal list of
|
|
||||||
* floating widgets
|
|
||||||
*/
|
|
||||||
void registerFloatingWidget(CFloatingDockContainer* FloatingWidget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the given floating widget from the list of registered floating
|
|
||||||
* widgets
|
|
||||||
*/
|
|
||||||
void removeFloatingWidget(CFloatingDockContainer* FloatingWidget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers the given dock container widget
|
|
||||||
*/
|
|
||||||
void registerDockContainer(CDockContainerWidget* DockContainer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove dock container from the internal list of registered dock
|
|
||||||
* containers
|
|
||||||
*/
|
|
||||||
void removeDockContainer(CDockContainerWidget* DockContainer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overlay for containers
|
|
||||||
*/
|
|
||||||
CDockOverlay* containerOverlay() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overlay for dock areas
|
|
||||||
*/
|
|
||||||
CDockOverlay* dockAreaOverlay() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the floating widgets that has been created floating
|
|
||||||
*/
|
|
||||||
virtual void showEvent(QShowEvent *event) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using Super = CDockContainerWidget;
|
|
||||||
|
|
||||||
enum eViewMenuInsertionOrder
|
|
||||||
{
|
|
||||||
MenuSortedByInsertion,
|
|
||||||
MenuAlphabeticallySorted
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* These global configuration flags configure some global dock manager
|
|
||||||
* settings.
|
|
||||||
*/
|
|
||||||
enum eConfigFlag
|
|
||||||
{
|
|
||||||
ActiveTabHasCloseButton = 0x0001, //!< If this flag is set, the active tab in a tab area has a close button
|
|
||||||
DockAreaHasCloseButton = 0x0002, //!< If the flag is set each dock area has a close button
|
|
||||||
DockAreaCloseButtonClosesTab = 0x0004,//!< If the flag is set, the dock area close button closes the active tab, if not set, it closes the complete cock area
|
|
||||||
OpaqueSplitterResize = 0x0008, //!< See QSplitter::setOpaqueResize() documentation
|
|
||||||
XmlAutoFormattingEnabled = 0x0010,//!< If enabled, the XML writer automatically adds line-breaks and indentation to empty sections between elements (ignorable whitespace).
|
|
||||||
XmlCompressionEnabled = 0x0020,//!< If enabled, the XML output will be compressed and is not human readable anymore
|
|
||||||
TabCloseButtonIsToolButton = 0x0040,//! If enabled the tab close buttons will be QToolButtons instead of QPushButtons - disabled by default
|
|
||||||
AllTabsHaveCloseButton = 0x0080, //!< if this flag is set, then all tabs that are closable show a close button
|
|
||||||
RetainTabSizeWhenCloseButtonHidden = 0x0100, //!< if this flag is set, the space for the close button is reserved even if the close button is not visible
|
|
||||||
OpaqueUndocking = 0x0200,///< If enabled, the widgets are immediately undocked into floating widgets, if disabled, only a draw preview is undocked and the real undocking is deferred until the mouse is released
|
|
||||||
DragPreviewIsDynamic = 0x0400,///< If opaque undocking is disabled, this flag defines the behavior of the drag preview window, if this flag is enabled, the preview will be adjusted dynamically to the drop area
|
|
||||||
DragPreviewShowsContentPixmap = 0x0800,///< If opaque undocking is disabled, the created drag preview window shows a copy of the content of the dock widget / dock are that is dragged
|
|
||||||
DragPreviewHasWindowFrame = 0x1000,///< If opaque undocking is disabled, then this flag configures if the drag preview is frameless or looks like a real window
|
|
||||||
DefaultConfig = ActiveTabHasCloseButton
|
|
||||||
| DockAreaHasCloseButton
|
|
||||||
| OpaqueSplitterResize
|
|
||||||
| XmlCompressionEnabled
|
|
||||||
| OpaqueUndocking, ///< the default configuration
|
|
||||||
DefaultNonOpaqueConfig = ActiveTabHasCloseButton
|
|
||||||
| DockAreaHasCloseButton
|
|
||||||
| XmlCompressionEnabled
|
|
||||||
| DragPreviewShowsContentPixmap, ///< the default configuration for non opaque operations
|
|
||||||
NonOpaqueWithWindowFrame = ActiveTabHasCloseButton
|
|
||||||
| DockAreaHasCloseButton
|
|
||||||
| XmlCompressionEnabled
|
|
||||||
| DragPreviewShowsContentPixmap
|
|
||||||
| DragPreviewHasWindowFrame ///< the default configuration for non opaque operations that show a real window with frame
|
|
||||||
};
|
|
||||||
Q_DECLARE_FLAGS(ConfigFlags, eConfigFlag)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default Constructor.
|
|
||||||
* If the given parent is a QMainWindow, the dock manager sets itself as the
|
|
||||||
* central widget.
|
|
||||||
* Before you create any dock widgets, you should properly setup the
|
|
||||||
* configuration flags via setConfigFlags().
|
|
||||||
*/
|
|
||||||
CDockManager(QWidget* parent = 0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual Destructor
|
|
||||||
*/
|
|
||||||
virtual ~CDockManager();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns the global configuration flags
|
|
||||||
*/
|
|
||||||
static ConfigFlags configFlags();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the global configuration flags for the whole docking system.
|
|
||||||
* Call this function before you create your first dock widget.
|
|
||||||
*/
|
|
||||||
static void setConfigFlags(const ConfigFlags Flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a certain config flag
|
|
||||||
*/
|
|
||||||
static void setConfigFlag(eConfigFlag Flag, bool On = true);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the global icon provider.
|
|
||||||
* The icon provider enables the use of custom icons in case using
|
|
||||||
* styleheets for icons is not an option.
|
|
||||||
*/
|
|
||||||
static CIconProvider& iconProvider();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds dockwidget into the given area.
|
|
||||||
* If DockAreaWidget is not null, then the area parameter indicates the area
|
|
||||||
* into the DockAreaWidget. If DockAreaWidget is null, the Dockwidget will
|
|
||||||
* be dropped into the container. If you would like to add a dock widget
|
|
||||||
* tabified, then you need to add it to an existing dock area object
|
|
||||||
* into the CenterDockWidgetArea. The following code shows this:
|
|
||||||
* \code
|
|
||||||
* DockManager->addDockWidget(ads::CenterDockWidgetArea, NewDockWidget,
|
|
||||||
* ExisitingDockArea);
|
|
||||||
* \endcode
|
|
||||||
* \return Returns the dock area widget that contains the new DockWidget
|
|
||||||
*/
|
|
||||||
CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
|
|
||||||
CDockAreaWidget* DockAreaWidget = nullptr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function will add the given Dockwidget to the given dock area as
|
|
||||||
* a new tab.
|
|
||||||
* If no dock area widget exists for the given area identifier, a new
|
|
||||||
* dock area widget is created.
|
|
||||||
*/
|
|
||||||
CDockAreaWidget* addDockWidgetTab(DockWidgetArea area,
|
|
||||||
CDockWidget* Dockwidget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function will add the given Dockwidget to the given DockAreaWidget
|
|
||||||
* as a new tab.
|
|
||||||
*/
|
|
||||||
CDockAreaWidget* addDockWidgetTabToArea(CDockWidget* Dockwidget,
|
|
||||||
CDockAreaWidget* DockAreaWidget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the given DockWidget floating and returns the created
|
|
||||||
* CFloatingDockContainer instance.
|
|
||||||
*/
|
|
||||||
CFloatingDockContainer* addDockWidgetFloating(CDockWidget* Dockwidget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Searches for a registered doc widget with the given ObjectName
|
|
||||||
* \return Return the found dock widget or nullptr if a dock widget with the
|
|
||||||
* given name is not registered
|
|
||||||
*/
|
|
||||||
CDockWidget* findDockWidget(const QString& ObjectName) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the given Dock from the dock manager
|
|
||||||
*/
|
|
||||||
void removeDockWidget(CDockWidget* Dockwidget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns a readable reference to the internal dock
|
|
||||||
* widgets map so that it is possible to iterate over all dock widgets
|
|
||||||
*/
|
|
||||||
QMap<QString, CDockWidget*> dockWidgetsMap() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the list of all active and visible dock containers
|
|
||||||
* Dock containers are the main dock manager and all floating widgets
|
|
||||||
*/
|
|
||||||
const QList<CDockContainerWidget*> dockContainers() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the list of all floating widgets
|
|
||||||
*/
|
|
||||||
const QList<CFloatingDockContainer*> floatingWidgets() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function always return 0 because the main window is always behind
|
|
||||||
* any floating widget
|
|
||||||
*/
|
|
||||||
virtual unsigned int zOrderIndex() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the current state of the dockmanger and all its dock widgets
|
|
||||||
* into the returned QByteArray.
|
|
||||||
* The XmlMode enables / disables the auto formatting for the XmlStreamWriter.
|
|
||||||
* If auto formatting is enabled, the output is intended and line wrapped.
|
|
||||||
* The XmlMode XmlAutoFormattingDisabled is better if you would like to have
|
|
||||||
* a more compact XML output - i.e. for storage in ini files.
|
|
||||||
*/
|
|
||||||
QByteArray saveState(int version = Version1) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restores the state of this dockmanagers dockwidgets.
|
|
||||||
* The version number is compared with that stored in state. If they do
|
|
||||||
* not match, the dockmanager's state is left unchanged, and this function
|
|
||||||
* returns false; otherwise, the state is restored, and this function
|
|
||||||
* returns true.
|
|
||||||
*/
|
|
||||||
bool restoreState(const QByteArray &state, int version = Version1);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the current perspective to the internal list of perspectives.
|
|
||||||
* A perspective is the current state of the dock manager assigned
|
|
||||||
* with a certain name. This makes it possible for the user,
|
|
||||||
* to switch between different perspectives quickly.
|
|
||||||
* If a perspective with the given name already exists, then
|
|
||||||
* it will be overwritten with the new state.
|
|
||||||
*/
|
|
||||||
void addPerspective(const QString& UniquePrespectiveName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the perspective with the given name from the list of perspectives
|
|
||||||
*/
|
|
||||||
void removePerspective(const QString& Name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the given perspectives from the dock manager
|
|
||||||
*/
|
|
||||||
void removePerspectives(const QStringList& Names);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the names of all available perspectives
|
|
||||||
*/
|
|
||||||
QStringList perspectiveNames() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the perspectives to the given settings file.
|
|
||||||
*/
|
|
||||||
void savePerspectives(QSettings& Settings) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the perspectives from the given settings file
|
|
||||||
*/
|
|
||||||
void loadPerspectives(QSettings& Settings);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a toggle view action to the the internal view menu.
|
|
||||||
* You can either manage the insertion of the toggle view actions in your
|
|
||||||
* application or you can add the actions to the internal view menu and
|
|
||||||
* then simply insert the menu object into your.
|
|
||||||
* \param[in] ToggleViewAction The action to insert. If no group is provided
|
|
||||||
* the action is directly inserted into the menu. If a group
|
|
||||||
* is provided, the action is inserted into the group and the
|
|
||||||
* group is inserted into the menu if it is not existing yet.
|
|
||||||
* \param[in] Group This is the text used for the group menu item
|
|
||||||
* \param[in] GroupIcon The icon used for grouping the workbenches in the
|
|
||||||
* view menu. I.e. if there is a workbench for each device
|
|
||||||
* like for spectrometer devices, it is good to group all these
|
|
||||||
* workbenches under a menu item
|
|
||||||
* \return If Group is not empty, this function returns the GroupAction
|
|
||||||
* for this group. If the group is empty, the function returns
|
|
||||||
* the given ToggleViewAction.
|
|
||||||
*/
|
|
||||||
QAction* addToggleViewActionToMenu(QAction* ToggleViewAction,
|
|
||||||
const QString& Group = QString(), const QIcon& GroupIcon = QIcon());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns the internal view menu.
|
|
||||||
* To fill the view menu, you can use the addToggleViewActionToMenu()
|
|
||||||
* function.
|
|
||||||
*/
|
|
||||||
QMenu* viewMenu() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define the insertion order for toggle view menu items.
|
|
||||||
* The order defines how the actions are added to the view menu.
|
|
||||||
* The default insertion order is MenuAlphabeticallySorted to make it
|
|
||||||
* easier for users to find the menu entry for a certain dock widget.
|
|
||||||
* You need to call this function befor you insert the first menu item
|
|
||||||
* into the view menu.
|
|
||||||
*/
|
|
||||||
void setViewMenuInsertionOrder(eViewMenuInsertionOrder Order);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns true between the restoringState() and
|
|
||||||
* stateRestored() signals.
|
|
||||||
*/
|
|
||||||
bool isRestoringState() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The distance the user needs to move the mouse with the left button
|
|
||||||
* hold down before a dock widget start floating
|
|
||||||
*/
|
|
||||||
static int startDragDistance();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
/**
|
|
||||||
* Opens the perspective with the given name.
|
|
||||||
*/
|
|
||||||
void openPerspective(const QString& PerspectiveName);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
/**
|
|
||||||
* This signal is emitted if the list of perspectives changed
|
|
||||||
*/
|
|
||||||
void perspectiveListChanged();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted if perspectives have been removed
|
|
||||||
*/
|
|
||||||
void perspectivesRemoved();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted, if the restore function is called, just before
|
|
||||||
* the dock manager starts restoring the state.
|
|
||||||
* If this function is called, nothing has changed yet
|
|
||||||
*/
|
|
||||||
void restoringState();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted if the state changed in restoreState.
|
|
||||||
* The signal is emitted if the restoreState() function is called or
|
|
||||||
* if the openPerspective() function is called
|
|
||||||
*/
|
|
||||||
void stateRestored();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted, if the dock manager starts opening a
|
|
||||||
* perspective.
|
|
||||||
* Opening a perspective may take more than a second if there are
|
|
||||||
* many complex widgets. The application may use this signal
|
|
||||||
* to show some progress indicator or to change the mouse cursor
|
|
||||||
* into a busy cursor.
|
|
||||||
*/
|
|
||||||
void openingPerspective(const QString& PerspectiveName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted if the dock manager finished opening a
|
|
||||||
* perspective
|
|
||||||
*/
|
|
||||||
void perspectiveOpened(const QString& PerspectiveName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted, if a new DockArea has been created.
|
|
||||||
* An application can use this signal to set custom icons or custom
|
|
||||||
* tooltips for the DockArea buttons.
|
|
||||||
*/
|
|
||||||
void dockAreaCreated(CDockAreaWidget* DockArea);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted just before the given dock widget is removed
|
|
||||||
* from the
|
|
||||||
*/
|
|
||||||
void dockWidgetAboutToBeRemoved(CDockWidget* DockWidget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted if a dock widget has been removed with the remove
|
|
||||||
* removeDockWidget() function.
|
|
||||||
* If this signal is emitted, the dock widget has been removed from the
|
|
||||||
* docking system but it is not deleted yet.
|
|
||||||
*/
|
|
||||||
void dockWidgetRemoved(CDockWidget* DockWidget);
|
|
||||||
}; // class DockManager
|
|
||||||
} // namespace ads
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#endif // DockManagerH
|
|
@ -1,817 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include "DockOverlay.h"
|
|
||||||
|
|
||||||
#include <QPointer>
|
|
||||||
#include <QPaintEvent>
|
|
||||||
#include <QResizeEvent>
|
|
||||||
#include <QMoveEvent>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QGridLayout>
|
|
||||||
#include <QCursor>
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QtGlobal>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QMap>
|
|
||||||
#include <QWindow>
|
|
||||||
|
|
||||||
#include "DockAreaWidget.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data class of CDockOverlay
|
|
||||||
*/
|
|
||||||
struct DockOverlayPrivate
|
|
||||||
{
|
|
||||||
CDockOverlay* _this;
|
|
||||||
DockWidgetAreas AllowedAreas = InvalidDockWidgetArea;
|
|
||||||
CDockOverlayCross* Cross;
|
|
||||||
QPointer<QWidget> TargetWidget;
|
|
||||||
DockWidgetArea LastLocation = InvalidDockWidgetArea;
|
|
||||||
bool DropPreviewEnabled = true;
|
|
||||||
CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay;
|
|
||||||
QRect DropAreaRect;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data constructor
|
|
||||||
*/
|
|
||||||
DockOverlayPrivate(CDockOverlay* _public) : _this(_public) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data of CDockOverlayCross class
|
|
||||||
*/
|
|
||||||
struct DockOverlayCrossPrivate
|
|
||||||
{
|
|
||||||
CDockOverlayCross* _this;
|
|
||||||
CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay;
|
|
||||||
CDockOverlay* DockOverlay;
|
|
||||||
QHash<DockWidgetArea, QWidget*> DropIndicatorWidgets;
|
|
||||||
QGridLayout* GridLayout;
|
|
||||||
QColor IconColors[5];
|
|
||||||
bool UpdateRequired = false;
|
|
||||||
double LastDevicePixelRatio = 0.1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data constructor
|
|
||||||
*/
|
|
||||||
DockOverlayCrossPrivate(CDockOverlayCross* _public) : _this(_public) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param area
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
QPoint areaGridPosition(const DockWidgetArea area);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Palette based default icon colors
|
|
||||||
*/
|
|
||||||
QColor defaultIconColor(CDockOverlayCross::eIconColor ColorIndex)
|
|
||||||
{
|
|
||||||
QPalette pal = _this->palette();
|
|
||||||
switch (ColorIndex)
|
|
||||||
{
|
|
||||||
case CDockOverlayCross::FrameColor: return pal.color(QPalette::Active, QPalette::Highlight);
|
|
||||||
case CDockOverlayCross::WindowBackgroundColor: return pal.color(QPalette::Active, QPalette::Base);
|
|
||||||
case CDockOverlayCross::OverlayColor:
|
|
||||||
{
|
|
||||||
QColor Color = pal.color(QPalette::Active, QPalette::Highlight);
|
|
||||||
Color.setAlpha(64);
|
|
||||||
return Color;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CDockOverlayCross::ArrowColor: return pal.color(QPalette::Active, QPalette::Base);
|
|
||||||
case CDockOverlayCross::ShadowColor: return QColor(0, 0, 0, 64);
|
|
||||||
default:
|
|
||||||
return QColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
return QColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stylehseet based icon colors
|
|
||||||
*/
|
|
||||||
QColor iconColor(CDockOverlayCross::eIconColor ColorIndex)
|
|
||||||
{
|
|
||||||
QColor Color = IconColors[ColorIndex];
|
|
||||||
if (!Color.isValid())
|
|
||||||
{
|
|
||||||
Color = defaultIconColor(ColorIndex);
|
|
||||||
IconColors[ColorIndex] = Color;
|
|
||||||
}
|
|
||||||
return Color;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/**
|
|
||||||
* Helper function that returns the drop indicator width depending on the
|
|
||||||
* operating system
|
|
||||||
*/
|
|
||||||
qreal dropIndicatiorWidth(QLabel* l) const
|
|
||||||
{
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
Q_UNUSED(l)
|
|
||||||
return 40;
|
|
||||||
#else
|
|
||||||
return static_cast<qreal>(l->fontMetrics().height()) * 3.f;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QWidget* createDropIndicatorWidget(DockWidgetArea DockWidgetArea,
|
|
||||||
CDockOverlay::eMode Mode)
|
|
||||||
{
|
|
||||||
QLabel* l = new QLabel();
|
|
||||||
l->setObjectName("DockWidgetAreaLabel");
|
|
||||||
|
|
||||||
const qreal metric = dropIndicatiorWidth(l);
|
|
||||||
const QSizeF size(metric, metric);
|
|
||||||
|
|
||||||
l->setPixmap(createHighDpiDropIndicatorPixmap(size, DockWidgetArea, Mode));
|
|
||||||
l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
|
|
||||||
l->setAttribute(Qt::WA_TranslucentBackground);
|
|
||||||
l->setProperty("dockWidgetArea", DockWidgetArea);
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void updateDropIndicatorIcon(QWidget* DropIndicatorWidget)
|
|
||||||
{
|
|
||||||
QLabel* l = qobject_cast<QLabel*>(DropIndicatorWidget);
|
|
||||||
const qreal metric = dropIndicatiorWidth(l);
|
|
||||||
const QSizeF size(metric, metric);
|
|
||||||
|
|
||||||
int Area = l->property("dockWidgetArea").toInt();
|
|
||||||
l->setPixmap(createHighDpiDropIndicatorPixmap(size, (DockWidgetArea)Area, Mode));
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QPixmap createHighDpiDropIndicatorPixmap(const QSizeF& size, DockWidgetArea DockWidgetArea,
|
|
||||||
CDockOverlay::eMode Mode)
|
|
||||||
{
|
|
||||||
QColor borderColor = iconColor(CDockOverlayCross::FrameColor);
|
|
||||||
QColor backgroundColor = iconColor(CDockOverlayCross::WindowBackgroundColor);
|
|
||||||
|
|
||||||
#if QT_VERSION >= 0x050600
|
|
||||||
double DevicePixelRatio = _this->window()->devicePixelRatioF();
|
|
||||||
#else
|
|
||||||
double DevicePixelRatio = _this->window()->devicePixelRatio();
|
|
||||||
#endif
|
|
||||||
QSizeF PixmapSize = size * DevicePixelRatio;
|
|
||||||
QPixmap pm(PixmapSize.toSize());
|
|
||||||
pm.fill(QColor(0, 0, 0, 0));
|
|
||||||
|
|
||||||
QPainter p(&pm);
|
|
||||||
QPen pen = p.pen();
|
|
||||||
QRectF ShadowRect(pm.rect());
|
|
||||||
QRectF baseRect;
|
|
||||||
baseRect.setSize(ShadowRect.size() * 0.7);
|
|
||||||
baseRect.moveCenter(ShadowRect.center());
|
|
||||||
|
|
||||||
// Fill
|
|
||||||
QColor ShadowColor = iconColor(CDockOverlayCross::ShadowColor);
|
|
||||||
if (ShadowColor.alpha() == 255)
|
|
||||||
{
|
|
||||||
ShadowColor.setAlpha(64);
|
|
||||||
}
|
|
||||||
p.fillRect(ShadowRect, ShadowColor);
|
|
||||||
|
|
||||||
// Drop area rect.
|
|
||||||
p.save();
|
|
||||||
QRectF areaRect;
|
|
||||||
QLineF areaLine;
|
|
||||||
QRectF nonAreaRect;
|
|
||||||
switch (DockWidgetArea)
|
|
||||||
{
|
|
||||||
case TopDockWidgetArea:
|
|
||||||
areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
|
|
||||||
nonAreaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
|
|
||||||
areaLine = QLineF(areaRect.bottomLeft(), areaRect.bottomRight());
|
|
||||||
break;
|
|
||||||
case RightDockWidgetArea:
|
|
||||||
areaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
|
|
||||||
nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
|
|
||||||
areaLine = QLineF(areaRect.topLeft(), areaRect.bottomLeft());
|
|
||||||
break;
|
|
||||||
case BottomDockWidgetArea:
|
|
||||||
areaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
|
|
||||||
nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
|
|
||||||
areaLine = QLineF(areaRect.topLeft(), areaRect.topRight());
|
|
||||||
break;
|
|
||||||
case LeftDockWidgetArea:
|
|
||||||
areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
|
|
||||||
nonAreaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
|
|
||||||
areaLine = QLineF(areaRect.topRight(), areaRect.bottomRight());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSizeF baseSize = baseRect.size();
|
|
||||||
if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea)
|
|
||||||
{
|
|
||||||
baseRect = areaRect;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.fillRect(baseRect, backgroundColor);
|
|
||||||
if (areaRect.isValid())
|
|
||||||
{
|
|
||||||
pen = p.pen();
|
|
||||||
pen.setColor(borderColor);
|
|
||||||
QColor Color = iconColor(CDockOverlayCross::OverlayColor);
|
|
||||||
if (Color.alpha() == 255)
|
|
||||||
{
|
|
||||||
Color.setAlpha(64);
|
|
||||||
}
|
|
||||||
p.setBrush(Color);
|
|
||||||
p.setPen(Qt::NoPen);
|
|
||||||
p.drawRect(areaRect);
|
|
||||||
|
|
||||||
pen = p.pen();
|
|
||||||
pen.setWidth(1);
|
|
||||||
pen.setColor(borderColor);
|
|
||||||
pen.setStyle(Qt::DashLine);
|
|
||||||
p.setPen(pen);
|
|
||||||
p.drawLine(areaLine);
|
|
||||||
}
|
|
||||||
p.restore();
|
|
||||||
|
|
||||||
p.save();
|
|
||||||
// Draw outer border
|
|
||||||
pen = p.pen();
|
|
||||||
pen.setColor(borderColor);
|
|
||||||
pen.setWidth(1);
|
|
||||||
p.setBrush(Qt::NoBrush);
|
|
||||||
p.setPen(pen);
|
|
||||||
p.drawRect(baseRect);
|
|
||||||
|
|
||||||
// draw window title bar
|
|
||||||
p.setBrush(borderColor);
|
|
||||||
QRectF FrameRect(baseRect.topLeft(), QSizeF(baseRect.width(), baseSize.height() / 10));
|
|
||||||
p.drawRect(FrameRect);
|
|
||||||
p.restore();
|
|
||||||
|
|
||||||
// Draw arrow for outer container drop indicators
|
|
||||||
if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea)
|
|
||||||
{
|
|
||||||
QRectF ArrowRect;
|
|
||||||
ArrowRect.setSize(baseSize);
|
|
||||||
ArrowRect.setWidth(ArrowRect.width() / 4.6);
|
|
||||||
ArrowRect.setHeight(ArrowRect.height() / 2);
|
|
||||||
ArrowRect.moveCenter(QPointF(0, 0));
|
|
||||||
QPolygonF Arrow;
|
|
||||||
Arrow << ArrowRect.topLeft()
|
|
||||||
<< QPointF( ArrowRect.right(), ArrowRect.center().y())
|
|
||||||
<< ArrowRect.bottomLeft();
|
|
||||||
p.setPen(Qt::NoPen);
|
|
||||||
p.setBrush(iconColor(CDockOverlayCross::ArrowColor));
|
|
||||||
p.setRenderHint(QPainter::Antialiasing, true);
|
|
||||||
p.translate(nonAreaRect.center().x(), nonAreaRect.center().y());
|
|
||||||
|
|
||||||
switch (DockWidgetArea)
|
|
||||||
{
|
|
||||||
case TopDockWidgetArea:
|
|
||||||
p.rotate(-90);
|
|
||||||
break;
|
|
||||||
case RightDockWidgetArea:
|
|
||||||
break;
|
|
||||||
case BottomDockWidgetArea:
|
|
||||||
p.rotate(90);
|
|
||||||
break;
|
|
||||||
case LeftDockWidgetArea:
|
|
||||||
p.rotate(180);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.drawPolygon(Arrow);
|
|
||||||
}
|
|
||||||
|
|
||||||
pm.setDevicePixelRatio(DevicePixelRatio);
|
|
||||||
return pm;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockOverlay::CDockOverlay(QWidget* parent, eMode Mode) :
|
|
||||||
QFrame(parent),
|
|
||||||
d(new DockOverlayPrivate(this))
|
|
||||||
{
|
|
||||||
d->Mode = Mode;
|
|
||||||
d->Cross = new CDockOverlayCross(this);
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
|
|
||||||
#else
|
|
||||||
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
|
|
||||||
#endif
|
|
||||||
setWindowOpacity(1);
|
|
||||||
setWindowTitle("DockOverlay");
|
|
||||||
setAttribute(Qt::WA_NoSystemBackground);
|
|
||||||
setAttribute(Qt::WA_TranslucentBackground);
|
|
||||||
|
|
||||||
d->Cross->setVisible(false);
|
|
||||||
setVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockOverlay::~CDockOverlay()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockOverlay::setAllowedAreas(DockWidgetAreas areas)
|
|
||||||
{
|
|
||||||
if (areas == d->AllowedAreas)
|
|
||||||
return;
|
|
||||||
d->AllowedAreas = areas;
|
|
||||||
d->Cross->reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
DockWidgetAreas CDockOverlay::allowedAreas() const
|
|
||||||
{
|
|
||||||
return d->AllowedAreas;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
|
|
||||||
{
|
|
||||||
DockWidgetArea Result = d->Cross->cursorLocation();
|
|
||||||
if (Result != InvalidDockWidgetArea)
|
|
||||||
{
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
CDockAreaWidget* DockArea = dynamic_cast<CDockAreaWidget*>(d->TargetWidget.data());
|
|
||||||
if (!DockArea)
|
|
||||||
{
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DockArea->titleBarGeometry().contains(DockArea->mapFromGlobal(QCursor::pos())))
|
|
||||||
{
|
|
||||||
return CenterDockWidgetArea;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
DockWidgetArea CDockOverlay::showOverlay(QWidget* target)
|
|
||||||
{
|
|
||||||
if (d->TargetWidget == target)
|
|
||||||
{
|
|
||||||
// Hint: We could update geometry of overlay here.
|
|
||||||
DockWidgetArea da = dropAreaUnderCursor();
|
|
||||||
if (da != d->LastLocation)
|
|
||||||
{
|
|
||||||
repaint();
|
|
||||||
d->LastLocation = da;
|
|
||||||
}
|
|
||||||
return da;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->TargetWidget = target;
|
|
||||||
d->LastLocation = InvalidDockWidgetArea;
|
|
||||||
|
|
||||||
// Move it over the target.
|
|
||||||
resize(target->size());
|
|
||||||
QPoint TopLeft = target->mapToGlobal(target->rect().topLeft());
|
|
||||||
move(TopLeft);
|
|
||||||
show();
|
|
||||||
d->Cross->updatePosition();
|
|
||||||
d->Cross->updateOverlayIcons();
|
|
||||||
return dropAreaUnderCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockOverlay::hideOverlay()
|
|
||||||
{
|
|
||||||
hide();
|
|
||||||
d->TargetWidget.clear();
|
|
||||||
d->LastLocation = InvalidDockWidgetArea;
|
|
||||||
d->DropAreaRect = QRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockOverlay::enableDropPreview(bool Enable)
|
|
||||||
{
|
|
||||||
d->DropPreviewEnabled = Enable;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CDockOverlay::dropPreviewEnabled() const
|
|
||||||
{
|
|
||||||
return d->DropPreviewEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockOverlay::paintEvent(QPaintEvent* event)
|
|
||||||
{
|
|
||||||
Q_UNUSED(event);
|
|
||||||
// Draw rect based on location
|
|
||||||
if (!d->DropPreviewEnabled)
|
|
||||||
{
|
|
||||||
d->DropAreaRect = QRect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QRect r = rect();
|
|
||||||
const DockWidgetArea da = dropAreaUnderCursor();
|
|
||||||
double Factor = (CDockOverlay::ModeContainerOverlay == d->Mode) ?
|
|
||||||
3 : 2;
|
|
||||||
|
|
||||||
switch (da)
|
|
||||||
{
|
|
||||||
case TopDockWidgetArea: r.setHeight(r.height() / Factor); break;
|
|
||||||
case RightDockWidgetArea: r.setX(r.width() * (1 - 1 / Factor)); break;
|
|
||||||
case BottomDockWidgetArea: r.setY(r.height() * (1 - 1 / Factor)); break;
|
|
||||||
case LeftDockWidgetArea: r.setWidth(r.width() / Factor); break;
|
|
||||||
case CenterDockWidgetArea: r = rect();break;
|
|
||||||
default: return;
|
|
||||||
}
|
|
||||||
QPainter painter(this);
|
|
||||||
QColor Color = palette().color(QPalette::Active, QPalette::Highlight);
|
|
||||||
QPen Pen = painter.pen();
|
|
||||||
Pen.setColor(Color.darker(120));
|
|
||||||
Pen.setStyle(Qt::SolidLine);
|
|
||||||
Pen.setWidth(1);
|
|
||||||
Pen.setCosmetic(true);
|
|
||||||
painter.setPen(Pen);
|
|
||||||
Color = Color.lighter(130);
|
|
||||||
Color.setAlpha(64);
|
|
||||||
painter.setBrush(Color);
|
|
||||||
painter.drawRect(r.adjusted(0, 0, -1, -1));
|
|
||||||
d->DropAreaRect = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QRect CDockOverlay::dropOverlayRect() const
|
|
||||||
{
|
|
||||||
return d->DropAreaRect;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockOverlay::showEvent(QShowEvent* e)
|
|
||||||
{
|
|
||||||
d->Cross->show();
|
|
||||||
QFrame::showEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockOverlay::hideEvent(QHideEvent* e)
|
|
||||||
{
|
|
||||||
d->Cross->hide();
|
|
||||||
QFrame::hideEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CDockOverlay::event(QEvent *e)
|
|
||||||
{
|
|
||||||
bool Result = Super::event(e);
|
|
||||||
if (e->type() == QEvent::Polish)
|
|
||||||
{
|
|
||||||
d->Cross->setupOverlayCross(d->Mode);
|
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
static int areaAlignment(const DockWidgetArea area)
|
|
||||||
{
|
|
||||||
switch (area)
|
|
||||||
{
|
|
||||||
case TopDockWidgetArea: return (int) Qt::AlignHCenter | Qt::AlignBottom;
|
|
||||||
case RightDockWidgetArea: return (int) Qt::AlignLeft | Qt::AlignVCenter;
|
|
||||||
case BottomDockWidgetArea: return (int) Qt::AlignHCenter | Qt::AlignTop;
|
|
||||||
case LeftDockWidgetArea: return (int) Qt::AlignRight | Qt::AlignVCenter;
|
|
||||||
case CenterDockWidgetArea: return (int) Qt::AlignCenter;
|
|
||||||
default: return Qt::AlignCenter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// DockOverlayCrossPrivate
|
|
||||||
//============================================================================
|
|
||||||
QPoint DockOverlayCrossPrivate::areaGridPosition(const DockWidgetArea area)
|
|
||||||
{
|
|
||||||
if (CDockOverlay::ModeDockAreaOverlay == Mode)
|
|
||||||
{
|
|
||||||
switch (area)
|
|
||||||
{
|
|
||||||
case TopDockWidgetArea: return QPoint(1, 2);
|
|
||||||
case RightDockWidgetArea: return QPoint(2, 3);
|
|
||||||
case BottomDockWidgetArea: return QPoint(3, 2);
|
|
||||||
case LeftDockWidgetArea: return QPoint(2, 1);
|
|
||||||
case CenterDockWidgetArea: return QPoint(2, 2);
|
|
||||||
default: return QPoint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (area)
|
|
||||||
{
|
|
||||||
case TopDockWidgetArea: return QPoint(0, 2);
|
|
||||||
case RightDockWidgetArea: return QPoint(2, 4);
|
|
||||||
case BottomDockWidgetArea: return QPoint(4, 2);
|
|
||||||
case LeftDockWidgetArea: return QPoint(2, 0);
|
|
||||||
case CenterDockWidgetArea: return QPoint(2, 2);
|
|
||||||
default: return QPoint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockOverlayCross::CDockOverlayCross(CDockOverlay* overlay) :
|
|
||||||
QWidget(overlay->parentWidget()),
|
|
||||||
d(new DockOverlayCrossPrivate(this))
|
|
||||||
{
|
|
||||||
d->DockOverlay = overlay;
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
|
|
||||||
#else
|
|
||||||
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
|
|
||||||
#endif
|
|
||||||
setWindowTitle("DockOverlayCross");
|
|
||||||
setAttribute(Qt::WA_TranslucentBackground);
|
|
||||||
|
|
||||||
d->GridLayout = new QGridLayout();
|
|
||||||
d->GridLayout->setSpacing(0);
|
|
||||||
setLayout(d->GridLayout);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockOverlayCross::~CDockOverlayCross()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockOverlayCross::setupOverlayCross(CDockOverlay::eMode Mode)
|
|
||||||
{
|
|
||||||
d->Mode = Mode;
|
|
||||||
|
|
||||||
QHash<DockWidgetArea, QWidget*> areaWidgets;
|
|
||||||
areaWidgets.insert(TopDockWidgetArea, d->createDropIndicatorWidget(TopDockWidgetArea, Mode));
|
|
||||||
areaWidgets.insert(RightDockWidgetArea, d->createDropIndicatorWidget(RightDockWidgetArea, Mode));
|
|
||||||
areaWidgets.insert(BottomDockWidgetArea, d->createDropIndicatorWidget(BottomDockWidgetArea, Mode));
|
|
||||||
areaWidgets.insert(LeftDockWidgetArea, d->createDropIndicatorWidget(LeftDockWidgetArea, Mode));
|
|
||||||
areaWidgets.insert(CenterDockWidgetArea, d->createDropIndicatorWidget(CenterDockWidgetArea, Mode));
|
|
||||||
#if QT_VERSION >= 0x050600
|
|
||||||
d->LastDevicePixelRatio = devicePixelRatioF();
|
|
||||||
#else
|
|
||||||
d->LastDevicePixelRatio = devicePixelRatio();
|
|
||||||
#endif
|
|
||||||
setAreaWidgets(areaWidgets);
|
|
||||||
d->UpdateRequired = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockOverlayCross::updateOverlayIcons()
|
|
||||||
{
|
|
||||||
if (windowHandle()->devicePixelRatio() == d->LastDevicePixelRatio)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto Widget : d->DropIndicatorWidgets)
|
|
||||||
{
|
|
||||||
d->updateDropIndicatorIcon(Widget);
|
|
||||||
}
|
|
||||||
#if QT_VESION >= 0x050600
|
|
||||||
d->LastDevicePixelRatio = devicePixelRatioF();
|
|
||||||
#else
|
|
||||||
d->LastDevicePixelRatio = devicePixelRatio();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockOverlayCross::setIconColor(eIconColor ColorIndex, const QColor& Color)
|
|
||||||
{
|
|
||||||
d->IconColors[ColorIndex] = Color;
|
|
||||||
d->UpdateRequired = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QColor CDockOverlayCross::iconColor(eIconColor ColorIndex) const
|
|
||||||
{
|
|
||||||
return d->IconColors[ColorIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockOverlayCross::setAreaWidgets(const QHash<DockWidgetArea, QWidget*>& widgets)
|
|
||||||
{
|
|
||||||
// Delete old widgets.
|
|
||||||
QMutableHashIterator<DockWidgetArea, QWidget*> i(d->DropIndicatorWidgets);
|
|
||||||
while (i.hasNext())
|
|
||||||
{
|
|
||||||
i.next();
|
|
||||||
QWidget* widget = i.value();
|
|
||||||
d->GridLayout->removeWidget(widget);
|
|
||||||
delete widget;
|
|
||||||
i.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert new widgets into grid.
|
|
||||||
d->DropIndicatorWidgets = widgets;
|
|
||||||
QHashIterator<DockWidgetArea, QWidget*> i2(d->DropIndicatorWidgets);
|
|
||||||
while (i2.hasNext())
|
|
||||||
{
|
|
||||||
i2.next();
|
|
||||||
const DockWidgetArea area = i2.key();
|
|
||||||
QWidget* widget = i2.value();
|
|
||||||
QPoint p = d->areaGridPosition(area);
|
|
||||||
d->GridLayout->addWidget(widget, p.x(), p.y(), (Qt::Alignment) areaAlignment(area));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CDockOverlay::ModeDockAreaOverlay == d->Mode)
|
|
||||||
{
|
|
||||||
d->GridLayout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
d->GridLayout->setRowStretch(0, 1);
|
|
||||||
d->GridLayout->setRowStretch(1, 0);
|
|
||||||
d->GridLayout->setRowStretch(2, 0);
|
|
||||||
d->GridLayout->setRowStretch(3, 0);
|
|
||||||
d->GridLayout->setRowStretch(4, 1);
|
|
||||||
|
|
||||||
d->GridLayout->setColumnStretch(0, 1);
|
|
||||||
d->GridLayout->setColumnStretch(1, 0);
|
|
||||||
d->GridLayout->setColumnStretch(2, 0);
|
|
||||||
d->GridLayout->setColumnStretch(3, 0);
|
|
||||||
d->GridLayout->setColumnStretch(4, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d->GridLayout->setContentsMargins(4, 4, 4, 4);
|
|
||||||
d->GridLayout->setRowStretch(0, 0);
|
|
||||||
d->GridLayout->setRowStretch(1, 1);
|
|
||||||
d->GridLayout->setRowStretch(2, 1);
|
|
||||||
d->GridLayout->setRowStretch(3, 1);
|
|
||||||
d->GridLayout->setRowStretch(4, 0);
|
|
||||||
|
|
||||||
d->GridLayout->setColumnStretch(0, 0);
|
|
||||||
d->GridLayout->setColumnStretch(1, 1);
|
|
||||||
d->GridLayout->setColumnStretch(2, 1);
|
|
||||||
d->GridLayout->setColumnStretch(3, 1);
|
|
||||||
d->GridLayout->setColumnStretch(4, 0);
|
|
||||||
}
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
DockWidgetArea CDockOverlayCross::cursorLocation() const
|
|
||||||
{
|
|
||||||
const QPoint pos = mapFromGlobal(QCursor::pos());
|
|
||||||
QHashIterator<DockWidgetArea, QWidget*> i(d->DropIndicatorWidgets);
|
|
||||||
while (i.hasNext())
|
|
||||||
{
|
|
||||||
i.next();
|
|
||||||
if (d->DockOverlay->allowedAreas().testFlag(i.key())
|
|
||||||
&& i.value()
|
|
||||||
&& i.value()->isVisible()
|
|
||||||
&& i.value()->geometry().contains(pos))
|
|
||||||
{
|
|
||||||
return i.key();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return InvalidDockWidgetArea;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockOverlayCross::showEvent(QShowEvent*)
|
|
||||||
{
|
|
||||||
if (d->UpdateRequired)
|
|
||||||
{
|
|
||||||
setupOverlayCross(d->Mode);
|
|
||||||
}
|
|
||||||
this->updatePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockOverlayCross::updatePosition()
|
|
||||||
{
|
|
||||||
resize(d->DockOverlay->size());
|
|
||||||
QPoint TopLeft = d->DockOverlay->pos();
|
|
||||||
QPoint Offest((this->width() - d->DockOverlay->width()) / 2,
|
|
||||||
(this->height() - d->DockOverlay->height()) / 2);
|
|
||||||
QPoint CrossTopLeft = TopLeft - Offest;
|
|
||||||
move(CrossTopLeft);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockOverlayCross::reset()
|
|
||||||
{
|
|
||||||
QList<DockWidgetArea> allAreas;
|
|
||||||
allAreas << TopDockWidgetArea << RightDockWidgetArea
|
|
||||||
<< BottomDockWidgetArea << LeftDockWidgetArea << CenterDockWidgetArea;
|
|
||||||
const DockWidgetAreas allowedAreas = d->DockOverlay->allowedAreas();
|
|
||||||
|
|
||||||
// Update visibility of area widgets based on allowedAreas.
|
|
||||||
for (int i = 0; i < allAreas.count(); ++i)
|
|
||||||
{
|
|
||||||
QPoint p = d->areaGridPosition(allAreas.at(i));
|
|
||||||
QLayoutItem* item = d->GridLayout->itemAtPosition(p.x(), p.y());
|
|
||||||
QWidget* w = nullptr;
|
|
||||||
if (item && (w = item->widget()) != nullptr)
|
|
||||||
{
|
|
||||||
w->setVisible(allowedAreas.testFlag(allAreas.at(i)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockOverlayCross::setIconColors(const QString& Colors)
|
|
||||||
{
|
|
||||||
static const QMap<QString, int> ColorCompenentStringMap{
|
|
||||||
{"Frame", CDockOverlayCross::FrameColor},
|
|
||||||
{"Background", CDockOverlayCross::WindowBackgroundColor},
|
|
||||||
{"Overlay", CDockOverlayCross::OverlayColor},
|
|
||||||
{"Arrow", CDockOverlayCross::ArrowColor},
|
|
||||||
{"Shadow", CDockOverlayCross::ShadowColor}};
|
|
||||||
|
|
||||||
auto ColorList = Colors.split(' ', Qt::SkipEmptyParts);
|
|
||||||
for (const auto& ColorListEntry : ColorList)
|
|
||||||
{
|
|
||||||
auto ComponentColor = ColorListEntry.split('=', Qt::SkipEmptyParts);
|
|
||||||
int Component = ColorCompenentStringMap.value(ComponentColor[0], -1);
|
|
||||||
if (Component < 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
d->IconColors[Component] = QColor(ComponentColor[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
d->UpdateRequired = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QString CDockOverlayCross::iconColors() const
|
|
||||||
{
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace ads
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
@ -1,257 +0,0 @@
|
|||||||
#ifndef DockOverlayH
|
|
||||||
#define DockOverlayH
|
|
||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include <QPointer>
|
|
||||||
#include <QHash>
|
|
||||||
#include <QRect>
|
|
||||||
#include <QFrame>
|
|
||||||
|
|
||||||
#include "ads_globals.h"
|
|
||||||
|
|
||||||
class QGridLayout;
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
struct DockOverlayPrivate;
|
|
||||||
class CDockOverlayCross;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* DockOverlay paints a translucent rectangle over another widget. The geometry
|
|
||||||
* of the rectangle is based on the mouse location.
|
|
||||||
*/
|
|
||||||
class CDockOverlay : public QFrame
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
private:
|
|
||||||
DockOverlayPrivate* d; //< private data class
|
|
||||||
friend struct DockOverlayPrivate;
|
|
||||||
friend class DockOverlayCross;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using Super = QFrame;
|
|
||||||
|
|
||||||
enum eMode
|
|
||||||
{
|
|
||||||
ModeDockAreaOverlay,
|
|
||||||
ModeContainerOverlay
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a dock overlay
|
|
||||||
*/
|
|
||||||
CDockOverlay(QWidget* parent, eMode Mode = ModeDockAreaOverlay);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual destructor
|
|
||||||
*/
|
|
||||||
virtual ~CDockOverlay();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the areas that are allowed for docking
|
|
||||||
*/
|
|
||||||
void setAllowedAreas(DockWidgetAreas areas);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns flags with all allowed drop areas
|
|
||||||
*/
|
|
||||||
DockWidgetAreas allowedAreas() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the drop area under the current cursor location
|
|
||||||
*/
|
|
||||||
DockWidgetArea dropAreaUnderCursor() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the drop overly for the given target widget
|
|
||||||
*/
|
|
||||||
DockWidgetArea showOverlay(QWidget* target);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hides the overlay
|
|
||||||
*/
|
|
||||||
void hideOverlay();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables / disables the semi transparent overlay rectangle that represents
|
|
||||||
* the future area of the dropped widget
|
|
||||||
*/
|
|
||||||
void enableDropPreview(bool Enable);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if drop preview is enabled
|
|
||||||
*/
|
|
||||||
bool dropPreviewEnabled() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The drop overlay rectangle for the target area
|
|
||||||
*/
|
|
||||||
QRect dropOverlayRect() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle polish events
|
|
||||||
*/
|
|
||||||
virtual bool event(QEvent *e) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void paintEvent(QPaintEvent *e) override;
|
|
||||||
virtual void showEvent(QShowEvent* e) override;
|
|
||||||
virtual void hideEvent(QHideEvent* e) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct DockOverlayCrossPrivate;
|
|
||||||
/*!
|
|
||||||
* DockOverlayCross shows a cross with 5 different drop area possibilities.
|
|
||||||
* I could have handled everything inside DockOverlay, but because of some
|
|
||||||
* styling issues it's better to have a separate class for the cross.
|
|
||||||
* You can style the cross icon using the property system.
|
|
||||||
* \code
|
|
||||||
* ads--CDockOverlayCross
|
|
||||||
{
|
|
||||||
qproperty-iconFrameColor: palette(highlight);
|
|
||||||
qproperty-iconBackgroundColor: palette(base);
|
|
||||||
qproperty-iconOverlayColor: palette(highlight);
|
|
||||||
qproperty-iconArrowColor: rgb(227, 227, 227);
|
|
||||||
qproperty-iconShadowColor: rgb(0, 0, 0);
|
|
||||||
}
|
|
||||||
* \endcode
|
|
||||||
* Or you can use the iconColors property to pass in AARRGGBB values as
|
|
||||||
* hex string like shown in the example below.
|
|
||||||
* \code
|
|
||||||
* ads--CDockOverlayCross
|
|
||||||
* {
|
|
||||||
* qproperty-iconColors: "Frame=#ff3d3d3d Background=#ff929292 Overlay=#1f3d3d3d Arrow=#ffb4b4b4 Shadow=#40474747";
|
|
||||||
* }
|
|
||||||
* \endcode
|
|
||||||
*/
|
|
||||||
class CDockOverlayCross : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(QString iconColors READ iconColors WRITE setIconColors)
|
|
||||||
Q_PROPERTY(QColor iconFrameColor READ iconColor WRITE setIconFrameColor)
|
|
||||||
Q_PROPERTY(QColor iconBackgroundColor READ iconColor WRITE setIconBackgroundColor)
|
|
||||||
Q_PROPERTY(QColor iconOverlayColor READ iconColor WRITE setIconOverlayColor)
|
|
||||||
Q_PROPERTY(QColor iconArrowColor READ iconColor WRITE setIconArrowColor)
|
|
||||||
Q_PROPERTY(QColor iconShadowColor READ iconColor WRITE setIconShadowColor)
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum eIconColor
|
|
||||||
{
|
|
||||||
FrameColor,///< the color of the frame of the small window icon
|
|
||||||
WindowBackgroundColor,///< the background color of the small window in the icon
|
|
||||||
OverlayColor,///< the color that shows the overlay (the dock side) in the icon
|
|
||||||
ArrowColor,///< the arrow that points into the direction
|
|
||||||
ShadowColor///< the color of the shadow rectangle that is painted below the icons
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
DockOverlayCrossPrivate* d;
|
|
||||||
friend struct DockOverlayCrossPrivate;
|
|
||||||
friend class CDockOverlay;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* This function returns an empty string and is only here to silence
|
|
||||||
* moc
|
|
||||||
*/
|
|
||||||
QString iconColors() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a dummy function for the property system
|
|
||||||
*/
|
|
||||||
QColor iconColor() const {return QColor();}
|
|
||||||
void setIconFrameColor(const QColor& Color) {setIconColor(FrameColor, Color);}
|
|
||||||
void setIconBackgroundColor(const QColor& Color) {setIconColor(WindowBackgroundColor, Color);}
|
|
||||||
void setIconOverlayColor(const QColor& Color) {setIconColor(OverlayColor, Color);}
|
|
||||||
void setIconArrowColor(const QColor& Color) {setIconColor(ArrowColor, Color);}
|
|
||||||
void setIconShadowColor(const QColor& Color) {setIconColor(ShadowColor, Color);}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Creates an overlay cross for the given overlay
|
|
||||||
*/
|
|
||||||
CDockOverlayCross(CDockOverlay* overlay);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual destructor
|
|
||||||
*/
|
|
||||||
virtual ~CDockOverlayCross();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a certain icon color
|
|
||||||
*/
|
|
||||||
void setIconColor(eIconColor ColorIndex, const QColor& Color);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the icon color given by ColorIndex
|
|
||||||
*/
|
|
||||||
QColor iconColor(eIconColor ColorIndex) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the dock widget area depending on the current cursor location.
|
|
||||||
* The function checks, if the mouse cursor is inside of any drop indicator
|
|
||||||
* widget and returns the corresponding DockWidgetArea.
|
|
||||||
*/
|
|
||||||
DockWidgetArea cursorLocation() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up the overlay cross for the given overlay mode
|
|
||||||
*/
|
|
||||||
void setupOverlayCross(CDockOverlay::eMode Mode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recreates the overlay icons.
|
|
||||||
*/
|
|
||||||
void updateOverlayIcons();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets and updates the
|
|
||||||
*/
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the current position
|
|
||||||
*/
|
|
||||||
void updatePosition();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A string with all icon colors to set.
|
|
||||||
* You can use this property to style the overly icon via CSS stylesheet
|
|
||||||
* file. The colors are set via a color identifier and a hex AARRGGBB value like
|
|
||||||
* in the example below.
|
|
||||||
* \code
|
|
||||||
* ads--CDockOverlayCross
|
|
||||||
* {
|
|
||||||
* qproperty-iconColors: "Frame=#ff3d3d3d Background=#ff929292 Overlay=#1f3d3d3d Arrow=#ffb4b4b4 Shadow=#40474747";
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
void setIconColors(const QString& Colors);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void showEvent(QShowEvent* e) override;
|
|
||||||
void setAreaWidgets(const QHash<DockWidgetArea, QWidget*>& widgets);
|
|
||||||
}; // CDockOverlayCross
|
|
||||||
|
|
||||||
} // namespace ads
|
|
||||||
#endif // DockOverlayH
|
|
@ -1,95 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockSplitter.cpp
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 24.03.2017
|
|
||||||
/// \brief Implementation of CDockSplitter
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include "DockSplitter.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QChildEvent>
|
|
||||||
#include <QVariant>
|
|
||||||
|
|
||||||
#include "DockAreaWidget.h"
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Private dock splitter data
|
|
||||||
*/
|
|
||||||
struct DockSplitterPrivate
|
|
||||||
{
|
|
||||||
CDockSplitter* _this;
|
|
||||||
int VisibleContentCount = 0;
|
|
||||||
|
|
||||||
DockSplitterPrivate(CDockSplitter* _public) : _this(_public) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockSplitter::CDockSplitter(QWidget *parent)
|
|
||||||
: QSplitter(parent),
|
|
||||||
d(new DockSplitterPrivate(this))
|
|
||||||
{
|
|
||||||
setProperty("ads-splitter", true);
|
|
||||||
setChildrenCollapsible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockSplitter::CDockSplitter(Qt::Orientation orientation, QWidget *parent)
|
|
||||||
: QSplitter(orientation, parent),
|
|
||||||
d(new DockSplitterPrivate(this))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockSplitter::~CDockSplitter()
|
|
||||||
{
|
|
||||||
ADS_PRINT("~CDockSplitter");
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CDockSplitter::hasVisibleContent() const
|
|
||||||
{
|
|
||||||
// TODO Cache or precalculate this to speed up
|
|
||||||
for (int i = 0; i < count(); ++i)
|
|
||||||
{
|
|
||||||
if (!widget(i)->isHidden())
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// EOF DockSplitter.cpp
|
|
@ -1,69 +0,0 @@
|
|||||||
#ifndef DockSplitterH
|
|
||||||
#define DockSplitterH
|
|
||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockSplitter.h
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 24.03.2017
|
|
||||||
/// \brief Declaration of CDockSplitter
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include <QSplitter>
|
|
||||||
|
|
||||||
#include "ads_globals.h"
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
struct DockSplitterPrivate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Splitter used internally instead of QSplitter with some additional
|
|
||||||
* fuctionality.
|
|
||||||
*/
|
|
||||||
class CDockSplitter : public QSplitter
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
private:
|
|
||||||
DockSplitterPrivate* d;
|
|
||||||
friend struct DockSplitterPrivate;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CDockSplitter(QWidget *parent = Q_NULLPTR);
|
|
||||||
CDockSplitter(Qt::Orientation orientation, QWidget *parent = Q_NULLPTR);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints debug info
|
|
||||||
*/
|
|
||||||
virtual ~CDockSplitter();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true, if any of the internal widgets is visible
|
|
||||||
*/
|
|
||||||
bool hasVisibleContent() const;
|
|
||||||
}; // class CDockSplitter
|
|
||||||
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
#endif // DockSplitterH
|
|
@ -1,823 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockWidget.cpp
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 26.02.2017
|
|
||||||
/// \brief Implementation of CDockWidget class
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include "DockWidgetTab.h"
|
|
||||||
#include "DockWidget.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <QBoxLayout>
|
|
||||||
#include <QAction>
|
|
||||||
#include <QSplitter>
|
|
||||||
#include <QStack>
|
|
||||||
#include <QScrollArea>
|
|
||||||
#include <QTextStream>
|
|
||||||
#include <QPointer>
|
|
||||||
#include <QEvent>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QToolBar>
|
|
||||||
#include <QXmlStreamWriter>
|
|
||||||
|
|
||||||
#include <QGuiApplication>
|
|
||||||
#include <QScreen>
|
|
||||||
#include <QWindow>
|
|
||||||
|
|
||||||
#include "DockContainerWidget.h"
|
|
||||||
#include "DockAreaWidget.h"
|
|
||||||
#include "DockManager.h"
|
|
||||||
#include "FloatingDockContainer.h"
|
|
||||||
#include "DockSplitter.h"
|
|
||||||
#include "ads_globals.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Private data class of CDockWidget class (pimpl)
|
|
||||||
*/
|
|
||||||
struct DockWidgetPrivate
|
|
||||||
{
|
|
||||||
CDockWidget* _this = nullptr;
|
|
||||||
QBoxLayout* Layout = nullptr;
|
|
||||||
QWidget* Widget = nullptr;
|
|
||||||
CDockWidgetTab* TabWidget = nullptr;
|
|
||||||
CDockWidget::DockWidgetFeatures Features = CDockWidget::DefaultDockWidgetFeatures;
|
|
||||||
CDockManager* DockManager = nullptr;
|
|
||||||
CDockAreaWidget* DockArea = nullptr;
|
|
||||||
QAction* ToggleViewAction = nullptr;
|
|
||||||
bool Closed = false;
|
|
||||||
QScrollArea* ScrollArea = nullptr;
|
|
||||||
QToolBar* ToolBar = nullptr;
|
|
||||||
Qt::ToolButtonStyle ToolBarStyleDocked = Qt::ToolButtonIconOnly;
|
|
||||||
Qt::ToolButtonStyle ToolBarStyleFloating = Qt::ToolButtonTextUnderIcon;
|
|
||||||
QSize ToolBarIconSizeDocked = QSize(16, 16);
|
|
||||||
QSize ToolBarIconSizeFloating = QSize(24, 24);
|
|
||||||
bool IsFloatingTopLevel = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data constructor
|
|
||||||
*/
|
|
||||||
DockWidgetPrivate(CDockWidget* _public);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show dock widget
|
|
||||||
*/
|
|
||||||
void showDockWidget();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hide dock widget.
|
|
||||||
*/
|
|
||||||
void hideDockWidget();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hides a dock area if all dock widgets in the area are closed.
|
|
||||||
* This function updates the current selected tab and hides the parent
|
|
||||||
* dock area if it is empty
|
|
||||||
*/
|
|
||||||
void updateParentDockArea();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup the top tool bar
|
|
||||||
*/
|
|
||||||
void setupToolBar();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup the main scroll area
|
|
||||||
*/
|
|
||||||
void setupScrollArea();
|
|
||||||
};
|
|
||||||
// struct DockWidgetPrivate
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
DockWidgetPrivate::DockWidgetPrivate(CDockWidget* _public) :
|
|
||||||
_this(_public)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockWidgetPrivate::showDockWidget()
|
|
||||||
{
|
|
||||||
if (!DockArea)
|
|
||||||
{
|
|
||||||
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this);
|
|
||||||
FloatingWidget->resize(_this->size());
|
|
||||||
FloatingWidget->show();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DockArea->setCurrentDockWidget(_this);
|
|
||||||
DockArea->toggleView(true);
|
|
||||||
TabWidget->show();
|
|
||||||
QSplitter* Splitter = internal::findParent<QSplitter*>(DockArea);
|
|
||||||
while (Splitter && !Splitter->isVisible())
|
|
||||||
{
|
|
||||||
Splitter->show();
|
|
||||||
Splitter = internal::findParent<QSplitter*>(Splitter);
|
|
||||||
}
|
|
||||||
|
|
||||||
CDockContainerWidget* Container = DockArea->dockContainer();
|
|
||||||
if (Container->isFloating())
|
|
||||||
{
|
|
||||||
CFloatingDockContainer* FloatingWidget = internal::findParent<
|
|
||||||
CFloatingDockContainer*>(Container);
|
|
||||||
FloatingWidget->show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockWidgetPrivate::hideDockWidget()
|
|
||||||
{
|
|
||||||
TabWidget->hide();
|
|
||||||
updateParentDockArea();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockWidgetPrivate::updateParentDockArea()
|
|
||||||
{
|
|
||||||
if (!DockArea)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto NextDockWidget = DockArea->nextOpenDockWidget(_this);
|
|
||||||
if (NextDockWidget)
|
|
||||||
{
|
|
||||||
DockArea->setCurrentDockWidget(NextDockWidget);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DockArea->hideAreaWithNoVisibleContent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockWidgetPrivate::setupToolBar()
|
|
||||||
{
|
|
||||||
ToolBar = new QToolBar(_this);
|
|
||||||
ToolBar->setObjectName("dockWidgetToolBar");
|
|
||||||
Layout->insertWidget(0, ToolBar);
|
|
||||||
ToolBar->setIconSize(QSize(16, 16));
|
|
||||||
ToolBar->toggleViewAction()->setEnabled(false);
|
|
||||||
ToolBar->toggleViewAction()->setVisible(false);
|
|
||||||
_this->connect(_this, SIGNAL(topLevelChanged(bool)), SLOT(setToolbarFloatingStyle(bool)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockWidgetPrivate::setupScrollArea()
|
|
||||||
{
|
|
||||||
ScrollArea = new QScrollArea(_this);
|
|
||||||
ScrollArea->setObjectName("dockWidgetScrollArea");
|
|
||||||
ScrollArea->setWidgetResizable(true);
|
|
||||||
Layout->addWidget(ScrollArea);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
|
|
||||||
QFrame(parent),
|
|
||||||
d(new DockWidgetPrivate(this))
|
|
||||||
{
|
|
||||||
d->Layout = new QBoxLayout(QBoxLayout::TopToBottom);
|
|
||||||
d->Layout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
d->Layout->setSpacing(0);
|
|
||||||
setLayout(d->Layout);
|
|
||||||
setWindowTitle(title);
|
|
||||||
setObjectName(title);
|
|
||||||
|
|
||||||
d->TabWidget = new CDockWidgetTab(this);
|
|
||||||
d->ToggleViewAction = new QAction(title, this);
|
|
||||||
d->ToggleViewAction->setCheckable(true);
|
|
||||||
connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this,
|
|
||||||
SLOT(toggleView(bool)));
|
|
||||||
setToolbarFloatingStyle(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockWidget::~CDockWidget()
|
|
||||||
{
|
|
||||||
ADS_PRINT("~CDockWidget()");
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::setToggleViewActionChecked(bool Checked)
|
|
||||||
{
|
|
||||||
QAction* Action = d->ToggleViewAction;
|
|
||||||
Action->blockSignals(true);
|
|
||||||
Action->setChecked(Checked);
|
|
||||||
Action->blockSignals(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::setWidget(QWidget* widget, eInsertMode InsertMode)
|
|
||||||
{
|
|
||||||
QScrollArea* ScrollAreaWidget = qobject_cast<QScrollArea*>(widget);
|
|
||||||
if (ScrollAreaWidget || ForceNoScrollArea == InsertMode)
|
|
||||||
{
|
|
||||||
d->Layout->addWidget(widget);
|
|
||||||
if (ScrollAreaWidget && ScrollAreaWidget->viewport())
|
|
||||||
{
|
|
||||||
ScrollAreaWidget->viewport()->setProperty("dockWidgetContent", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d->setupScrollArea();
|
|
||||||
d->ScrollArea->setWidget(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
d->Widget = widget;
|
|
||||||
d->Widget->setProperty("dockWidgetContent", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QWidget* CDockWidget::takeWidget()
|
|
||||||
{
|
|
||||||
d->ScrollArea->takeWidget();
|
|
||||||
d->Layout->removeWidget(d->Widget);
|
|
||||||
d->Widget->setParent(nullptr);
|
|
||||||
return d->Widget;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QWidget* CDockWidget::widget() const
|
|
||||||
{
|
|
||||||
return d->Widget;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockWidgetTab* CDockWidget::tabWidget() const
|
|
||||||
{
|
|
||||||
return d->TabWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::setFeatures(DockWidgetFeatures features)
|
|
||||||
{
|
|
||||||
if (d->Features == features)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->Features = features;
|
|
||||||
emit featuresChanged(d->Features);
|
|
||||||
d->TabWidget->onDockWidgetFeaturesChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::setFeature(DockWidgetFeature flag, bool on)
|
|
||||||
{
|
|
||||||
auto Features = features();
|
|
||||||
internal::setFlag(Features, flag, on);
|
|
||||||
setFeatures(Features);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockWidget::DockWidgetFeatures CDockWidget::features() const
|
|
||||||
{
|
|
||||||
return d->Features;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockManager* CDockWidget::dockManager() const
|
|
||||||
{
|
|
||||||
return d->DockManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::setDockManager(CDockManager* DockManager)
|
|
||||||
{
|
|
||||||
d->DockManager = DockManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockContainerWidget* CDockWidget::dockContainer() const
|
|
||||||
{
|
|
||||||
if (d->DockArea)
|
|
||||||
{
|
|
||||||
return d->DockArea->dockContainer();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockAreaWidget* CDockWidget::dockAreaWidget() const
|
|
||||||
{
|
|
||||||
return d->DockArea;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CDockWidget::isFloating() const
|
|
||||||
{
|
|
||||||
if (!isInFloatingContainer())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dockContainer()->topLevelDockWidget() == this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CDockWidget::isInFloatingContainer() const
|
|
||||||
{
|
|
||||||
auto Container = dockContainer();
|
|
||||||
if (!Container)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Container->isFloating())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CDockWidget::isClosed() const
|
|
||||||
{
|
|
||||||
return d->Closed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QAction* CDockWidget::toggleViewAction() const
|
|
||||||
{
|
|
||||||
return d->ToggleViewAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::setToggleViewActionMode(eToggleViewActionMode Mode)
|
|
||||||
{
|
|
||||||
if (ActionModeToggle == Mode)
|
|
||||||
{
|
|
||||||
d->ToggleViewAction->setCheckable(true);
|
|
||||||
d->ToggleViewAction->setIcon(QIcon());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d->ToggleViewAction->setCheckable(false);
|
|
||||||
d->ToggleViewAction->setIcon(d->TabWidget->icon());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::toggleView(bool Open)
|
|
||||||
{
|
|
||||||
// If the toggle view action mode is ActionModeShow, then Open is always
|
|
||||||
// true if the sender is the toggle view action
|
|
||||||
QAction* Sender = qobject_cast<QAction*>(sender());
|
|
||||||
if (Sender == d->ToggleViewAction && !d->ToggleViewAction->isCheckable())
|
|
||||||
{
|
|
||||||
Open = true;
|
|
||||||
}
|
|
||||||
// If the dock widget state is different, then we really need to toggle
|
|
||||||
// the state. If we are in the right state, then we simply make this
|
|
||||||
// dock widget the current dock widget
|
|
||||||
if (d->Closed != !Open)
|
|
||||||
{
|
|
||||||
toggleViewInternal(Open);
|
|
||||||
}
|
|
||||||
else if (Open && d->DockArea)
|
|
||||||
{
|
|
||||||
d->DockArea->setCurrentDockWidget(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::toggleViewInternal(bool Open)
|
|
||||||
{
|
|
||||||
CDockContainerWidget* DockContainer = dockContainer();
|
|
||||||
CDockWidget* TopLevelDockWidgetBefore = DockContainer
|
|
||||||
? DockContainer->topLevelDockWidget() : nullptr;
|
|
||||||
|
|
||||||
if (Open)
|
|
||||||
{
|
|
||||||
d->showDockWidget();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d->hideDockWidget();
|
|
||||||
}
|
|
||||||
d->Closed = !Open;
|
|
||||||
d->ToggleViewAction->blockSignals(true);
|
|
||||||
d->ToggleViewAction->setChecked(Open);
|
|
||||||
d->ToggleViewAction->blockSignals(false);
|
|
||||||
if (d->DockArea)
|
|
||||||
{
|
|
||||||
d->DockArea->toggleDockWidgetView(this, Open);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Open && TopLevelDockWidgetBefore)
|
|
||||||
{
|
|
||||||
CDockWidget::emitTopLevelEventForWidget(TopLevelDockWidgetBefore, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Here we need to call the dockContainer() function again, because if
|
|
||||||
// this dock widget was unassigned before the call to showDockWidget() then
|
|
||||||
// it has a dock container now
|
|
||||||
DockContainer = dockContainer();
|
|
||||||
CDockWidget* TopLevelDockWidgetAfter = DockContainer
|
|
||||||
? DockContainer->topLevelDockWidget() : nullptr;
|
|
||||||
CDockWidget::emitTopLevelEventForWidget(TopLevelDockWidgetAfter, true);
|
|
||||||
CFloatingDockContainer* FloatingContainer = DockContainer->floatingWidget();
|
|
||||||
if (FloatingContainer)
|
|
||||||
{
|
|
||||||
FloatingContainer->updateWindowTitle();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Open)
|
|
||||||
{
|
|
||||||
emit closed();
|
|
||||||
}
|
|
||||||
emit viewToggled(Open);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::setDockArea(CDockAreaWidget* DockArea)
|
|
||||||
{
|
|
||||||
d->DockArea = DockArea;
|
|
||||||
d->ToggleViewAction->setChecked(DockArea != nullptr && !this->isClosed());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::saveState(QXmlStreamWriter& s) const
|
|
||||||
{
|
|
||||||
s.writeStartElement("Widget");
|
|
||||||
s.writeAttribute("Name", objectName());
|
|
||||||
s.writeAttribute("Closed", QString::number(d->Closed ? 1 : 0));
|
|
||||||
s.writeEndElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::flagAsUnassigned()
|
|
||||||
{
|
|
||||||
d->Closed = true;
|
|
||||||
setParent(d->DockManager);
|
|
||||||
setVisible(false);
|
|
||||||
setDockArea(nullptr);
|
|
||||||
tabWidget()->setParent(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CDockWidget::event(QEvent *e)
|
|
||||||
{
|
|
||||||
switch (e->type())
|
|
||||||
{
|
|
||||||
case QEvent::Hide:
|
|
||||||
emit visibilityChanged(false);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QEvent::Show:
|
|
||||||
emit visibilityChanged(geometry().right() >= 0 && geometry().bottom() >= 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QEvent::WindowTitleChange :
|
|
||||||
{
|
|
||||||
const auto title = windowTitle();
|
|
||||||
if (d->TabWidget)
|
|
||||||
{
|
|
||||||
d->TabWidget->setText(title);
|
|
||||||
}
|
|
||||||
if (d->ToggleViewAction)
|
|
||||||
{
|
|
||||||
d->ToggleViewAction->setText(title);
|
|
||||||
}
|
|
||||||
if (d->DockArea)
|
|
||||||
{
|
|
||||||
d->DockArea->markTitleBarMenuOutdated();//update tabs menu
|
|
||||||
}
|
|
||||||
emit titleChanged(title);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Super::event(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef QT_NO_TOOLTIP
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::setTabToolTip(const QString &text)
|
|
||||||
{
|
|
||||||
if (d->TabWidget)
|
|
||||||
{
|
|
||||||
d->TabWidget->setToolTip(text);
|
|
||||||
}
|
|
||||||
if (d->ToggleViewAction)
|
|
||||||
{
|
|
||||||
d->ToggleViewAction->setToolTip(text);
|
|
||||||
}
|
|
||||||
if (d->DockArea)
|
|
||||||
{
|
|
||||||
d->DockArea->markTitleBarMenuOutdated();//update tabs menu
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::setIcon(const QIcon& Icon)
|
|
||||||
{
|
|
||||||
d->TabWidget->setIcon(Icon);
|
|
||||||
if (!d->ToggleViewAction->isCheckable())
|
|
||||||
{
|
|
||||||
d->ToggleViewAction->setIcon(Icon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QIcon CDockWidget::icon() const
|
|
||||||
{
|
|
||||||
return d->TabWidget->icon();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QToolBar* CDockWidget::toolBar() const
|
|
||||||
{
|
|
||||||
return d->ToolBar;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QToolBar* CDockWidget::createDefaultToolBar()
|
|
||||||
{
|
|
||||||
if (!d->ToolBar)
|
|
||||||
{
|
|
||||||
d->setupToolBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
return d->ToolBar;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::setToolBar(QToolBar* ToolBar)
|
|
||||||
{
|
|
||||||
if (d->ToolBar)
|
|
||||||
{
|
|
||||||
delete d->ToolBar;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->ToolBar = ToolBar;
|
|
||||||
d->Layout->insertWidget(0, d->ToolBar);
|
|
||||||
this->connect(this, SIGNAL(topLevelChanged(bool)), SLOT(setToolbarFloatingStyle(bool)));
|
|
||||||
setToolbarFloatingStyle(isFloating());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::setToolBarStyle(Qt::ToolButtonStyle Style, eState State)
|
|
||||||
{
|
|
||||||
if (StateFloating == State)
|
|
||||||
{
|
|
||||||
d->ToolBarStyleFloating = Style;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d->ToolBarStyleDocked = Style;
|
|
||||||
}
|
|
||||||
|
|
||||||
setToolbarFloatingStyle(isFloating());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
Qt::ToolButtonStyle CDockWidget::toolBarStyle(eState State) const
|
|
||||||
{
|
|
||||||
if (StateFloating == State)
|
|
||||||
{
|
|
||||||
return d->ToolBarStyleFloating;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return d->ToolBarStyleDocked;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::setToolBarIconSize(const QSize& IconSize, eState State)
|
|
||||||
{
|
|
||||||
if (StateFloating == State)
|
|
||||||
{
|
|
||||||
d->ToolBarIconSizeFloating = IconSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d->ToolBarIconSizeDocked = IconSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
setToolbarFloatingStyle(isFloating());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QSize CDockWidget::toolBarIconSize(eState State) const
|
|
||||||
{
|
|
||||||
if (StateFloating == State)
|
|
||||||
{
|
|
||||||
return d->ToolBarIconSizeFloating;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return d->ToolBarIconSizeDocked;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::setToolbarFloatingStyle(bool Floating)
|
|
||||||
{
|
|
||||||
if (!d->ToolBar)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto IconSize = Floating ? d->ToolBarIconSizeFloating : d->ToolBarIconSizeDocked;
|
|
||||||
if (IconSize != d->ToolBar->iconSize())
|
|
||||||
{
|
|
||||||
d->ToolBar->setIconSize(IconSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ButtonStyle = Floating ? d->ToolBarStyleFloating : d->ToolBarStyleDocked;
|
|
||||||
if (ButtonStyle != d->ToolBar->toolButtonStyle())
|
|
||||||
{
|
|
||||||
d->ToolBar->setToolButtonStyle(ButtonStyle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::emitTopLevelEventForWidget(CDockWidget* TopLevelDockWidget, bool Floating)
|
|
||||||
{
|
|
||||||
if (TopLevelDockWidget)
|
|
||||||
{
|
|
||||||
TopLevelDockWidget->dockAreaWidget()->updateTitleBarVisibility();
|
|
||||||
TopLevelDockWidget->emitTopLevelChanged(Floating);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::emitTopLevelChanged(bool Floating)
|
|
||||||
{
|
|
||||||
if (Floating != d->IsFloatingTopLevel)
|
|
||||||
{
|
|
||||||
d->IsFloatingTopLevel = Floating;
|
|
||||||
emit topLevelChanged(d->IsFloatingTopLevel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::setClosedState(bool Closed)
|
|
||||||
{
|
|
||||||
d->Closed = Closed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QSize CDockWidget::minimumSizeHint() const
|
|
||||||
{
|
|
||||||
return QSize(60, 40);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::setFloating()
|
|
||||||
{
|
|
||||||
if (isClosed())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->TabWidget->detachDockWidget();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::deleteDockWidget()
|
|
||||||
{
|
|
||||||
dockManager()->removeDockWidget(this);
|
|
||||||
deleteLater();
|
|
||||||
d->Closed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidget::closeDockWidget()
|
|
||||||
{
|
|
||||||
closeDockWidgetInternal(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CDockWidget::closeDockWidgetInternal(bool ForceClose)
|
|
||||||
{
|
|
||||||
if (!ForceClose)
|
|
||||||
{
|
|
||||||
emit closeRequested();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ForceClose && features().testFlag(CDockWidget::CustomCloseHandling))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
|
|
||||||
{
|
|
||||||
// If the dock widget is floating, then we check if we also need to
|
|
||||||
// delete the floating widget
|
|
||||||
if (isFloating())
|
|
||||||
{
|
|
||||||
CFloatingDockContainer* FloatingWidget = internal::findParent<
|
|
||||||
CFloatingDockContainer*>(this);
|
|
||||||
if (FloatingWidget->dockWidgets().count() == 1)
|
|
||||||
{
|
|
||||||
FloatingWidget->deleteLater();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FloatingWidget->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
deleteDockWidget();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
toggleView(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// EOF DockWidget.cpp
|
|
@ -1,488 +0,0 @@
|
|||||||
#ifndef DockWidgetH
|
|
||||||
#define DockWidgetH
|
|
||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockWidget.h
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 26.02.2017
|
|
||||||
/// \brief Declaration of CDockWidget class
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include <QFrame>
|
|
||||||
|
|
||||||
#include "ads_globals.h"
|
|
||||||
|
|
||||||
class QToolBar;
|
|
||||||
class QXmlStreamWriter;
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
struct DockWidgetPrivate;
|
|
||||||
class CDockWidgetTab;
|
|
||||||
class CDockManager;
|
|
||||||
class CDockContainerWidget;
|
|
||||||
class CDockAreaWidget;
|
|
||||||
class DockContainerWidgetPrivate;
|
|
||||||
class CFloatingDockContainer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The QDockWidget class provides a widget that can be docked inside a
|
|
||||||
* CDockManager or floated as a top-level window on the desktop.
|
|
||||||
*/
|
|
||||||
class CDockWidget : public QFrame
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
private:
|
|
||||||
DockWidgetPrivate* d; ///< private data (pimpl)
|
|
||||||
friend struct DockWidgetPrivate;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
/**
|
|
||||||
* Adjusts the toolbar icon sizes according to the floating state
|
|
||||||
*/
|
|
||||||
void setToolbarFloatingStyle(bool topLevel);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
friend class CDockContainerWidget;
|
|
||||||
friend class CDockAreaWidget;
|
|
||||||
friend class CFloatingDockContainer;
|
|
||||||
friend class CDockManager;
|
|
||||||
friend struct DockManagerPrivate;
|
|
||||||
friend class DockContainerWidgetPrivate;
|
|
||||||
friend class CDockAreaTabBar;
|
|
||||||
friend class CDockWidgetTab;
|
|
||||||
friend struct DockWidgetTabPrivate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assigns the dock manager that manages this dock widget
|
|
||||||
*/
|
|
||||||
void setDockManager(CDockManager* DockManager);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If this dock widget is inserted into a dock area, the dock area will
|
|
||||||
* be registered on this widget via this function. If a dock widget is
|
|
||||||
* removed from a dock area, this function will be called with nullptr
|
|
||||||
* value.
|
|
||||||
*/
|
|
||||||
void setDockArea(CDockAreaWidget* DockArea);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function changes the toggle view action without emitting any
|
|
||||||
* signal
|
|
||||||
*/
|
|
||||||
void setToggleViewActionChecked(bool Checked);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the state into the given stream
|
|
||||||
*/
|
|
||||||
void saveState(QXmlStreamWriter& Stream) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a helper function for the dock manager to flag this widget
|
|
||||||
* as unassigned.
|
|
||||||
* When calling the restore function, it may happen, that the saved state
|
|
||||||
* contains less dock widgets then currently available. All widgets whose
|
|
||||||
* data is not contained in the saved state, are flagged as unassigned
|
|
||||||
* after the restore process. If the user shows an unassigned dock widget,
|
|
||||||
* a floating widget will be created to take up the dock widget.
|
|
||||||
*/
|
|
||||||
void flagAsUnassigned();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call this function to emit a topLevelChanged() signal and to update
|
|
||||||
* the dock area tool bar visibility
|
|
||||||
*/
|
|
||||||
static void emitTopLevelEventForWidget(CDockWidget* TopLevelDockWidget, bool Floating);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use this function to emit a top level changed event.
|
|
||||||
* Do never use emit topLevelChanged(). Always use this function because
|
|
||||||
* it only emits a signal if the floating state has really changed
|
|
||||||
*/
|
|
||||||
void emitTopLevelChanged(bool Floating);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal function for modifying the closed state when restoring
|
|
||||||
* a saved docking state
|
|
||||||
*/
|
|
||||||
void setClosedState(bool Closed);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal toggle view function that does not check if the widget
|
|
||||||
* already is in the given state
|
|
||||||
*/
|
|
||||||
void toggleViewInternal(bool Open);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal close dock widget implementation.
|
|
||||||
* The function returns true if the dock widget has been closed or hidden
|
|
||||||
*/
|
|
||||||
bool closeDockWidgetInternal(bool ForceClose = false);
|
|
||||||
|
|
||||||
public:
|
|
||||||
using Super = QFrame;
|
|
||||||
|
|
||||||
enum DockWidgetFeature
|
|
||||||
{
|
|
||||||
DockWidgetClosable = 0x01,
|
|
||||||
DockWidgetMovable = 0x02,///< this feature is not properly implemented yet and is ignored
|
|
||||||
DockWidgetFloatable = 0x04,
|
|
||||||
DockWidgetDeleteOnClose = 0x08, ///< deletes the dock widget when it is closed
|
|
||||||
CustomCloseHandling = 0x10,
|
|
||||||
DefaultDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable,
|
|
||||||
AllDockWidgetFeatures = DefaultDockWidgetFeatures | DockWidgetDeleteOnClose | CustomCloseHandling,
|
|
||||||
NoDockWidgetFeatures = 0x00
|
|
||||||
};
|
|
||||||
Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature)
|
|
||||||
|
|
||||||
enum eState
|
|
||||||
{
|
|
||||||
StateHidden,
|
|
||||||
StateDocked,
|
|
||||||
StateFloating
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the widget for the dock widget to widget.
|
|
||||||
* The InsertMode defines how the widget is inserted into the dock widget.
|
|
||||||
* The content of a dock widget should be resizable do a very small size to
|
|
||||||
* prevent the dock widget from blocking the resizing. To ensure, that a
|
|
||||||
* dock widget can be resized very well, it is better to insert the content+
|
|
||||||
* widget into a scroll area or to provide a widget that is already a scroll
|
|
||||||
* area or that contains a scroll area.
|
|
||||||
* If the InsertMode is AutoScrollArea, the DockWidget tries to automatically
|
|
||||||
* detect how to insert the given widget. If the widget is derived from
|
|
||||||
* QScrollArea (i.e. an QAbstractItemView), then the widget is inserted
|
|
||||||
* directly. If the given widget is not a scroll area, the widget will be
|
|
||||||
* inserted into a scroll area.
|
|
||||||
* To force insertion into a scroll area, you can also provide the InsertMode
|
|
||||||
* ForceScrollArea. To prevent insertion into a scroll area, you can
|
|
||||||
* provide the InsertMode ForceNoScrollArea
|
|
||||||
*/
|
|
||||||
enum eInsertMode
|
|
||||||
{
|
|
||||||
AutoScrollArea,
|
|
||||||
ForceScrollArea,
|
|
||||||
ForceNoScrollArea
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This mode configures the behavior of the toggle view action.
|
|
||||||
* If the mode if ActionModeToggle, then the toggle view action is
|
|
||||||
* a checkable action to show / hide the dock widget. If the mode
|
|
||||||
* is ActionModeShow, then the action is not checkable an it will
|
|
||||||
* always show the dock widget if clicked. If the mode is ActionModeShow,
|
|
||||||
* the user can only close the DockWidget with the close button.
|
|
||||||
*/
|
|
||||||
enum eToggleViewActionMode
|
|
||||||
{
|
|
||||||
ActionModeToggle,//!< ActionModeToggle
|
|
||||||
ActionModeShow //!< ActionModeShow
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This constructor creates a dock widget with the given title.
|
|
||||||
* The title is the text that is shown in the window title when the dock
|
|
||||||
* widget is floating and it is the title that is shown in the titlebar
|
|
||||||
* or the tab of this dock widget if it is tabified.
|
|
||||||
* The object name of the dock widget is also set to the title. The
|
|
||||||
* object name is required by the dock manager to properly save and restore
|
|
||||||
* the state of the dock widget. That means, the title needs to be unique.
|
|
||||||
* If your title is not unique or if you would like to change the title
|
|
||||||
* during runtime, you need to set a unique object name explicitely
|
|
||||||
* by calling setObjectName() after construction.
|
|
||||||
* Use the layoutFlags to configure the layout of the dock widget.
|
|
||||||
*/
|
|
||||||
CDockWidget(const QString &title, QWidget* parent = 0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual Destructor
|
|
||||||
*/
|
|
||||||
virtual ~CDockWidget();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We return a fixed minimum size hint for all dock widgets
|
|
||||||
*/
|
|
||||||
virtual QSize minimumSizeHint() const override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the widget for the dock widget to widget.
|
|
||||||
* The InsertMode defines how the widget is inserted into the dock widget.
|
|
||||||
* The content of a dock widget should be resizable do a very small size to
|
|
||||||
* prevent the dock widget from blocking the resizing. To ensure, that a
|
|
||||||
* dock widget can be resized very well, it is better to insert the content+
|
|
||||||
* widget into a scroll area or to provide a widget that is already a scroll
|
|
||||||
* area or that contains a scroll area.
|
|
||||||
* If the InsertMode is AutoScrollArea, the DockWidget tries to automatically
|
|
||||||
* detect how to insert the given widget. If the widget is derived from
|
|
||||||
* QScrollArea (i.e. an QAbstractItemView), then the widget is inserted
|
|
||||||
* directly. If the given widget is not a scroll area, the widget will be
|
|
||||||
* inserted into a scroll area.
|
|
||||||
* To force insertion into a scroll area, you can also provide the InsertMode
|
|
||||||
* ForceScrollArea. To prevent insertion into a scroll area, you can
|
|
||||||
* provide the InsertMode ForceNoScrollArea
|
|
||||||
*/
|
|
||||||
void setWidget(QWidget* widget, eInsertMode InsertMode = AutoScrollArea);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the widget from the dock and give ownership back to the caller
|
|
||||||
*/
|
|
||||||
QWidget* takeWidget();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the widget for the dock widget. This function returns zero if
|
|
||||||
* the widget has not been set.
|
|
||||||
*/
|
|
||||||
QWidget* widget() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the tab widget of this dock widget that is shown in the dock
|
|
||||||
* area title bar
|
|
||||||
*/
|
|
||||||
CDockWidgetTab* tabWidget() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets, whether the dock widget is movable, closable, and floatable.
|
|
||||||
*/
|
|
||||||
void setFeatures(DockWidgetFeatures features);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the feature flag for this dock widget if on is true; otherwise
|
|
||||||
* clears the flag.
|
|
||||||
*/
|
|
||||||
void setFeature(DockWidgetFeature flag, bool on);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This property holds whether the dock widget is movable, closable, and
|
|
||||||
* floatable.
|
|
||||||
* By default, this property is set to a combination of DockWidgetClosable,
|
|
||||||
* DockWidgetMovable and DockWidgetFloatable.
|
|
||||||
*/
|
|
||||||
DockWidgetFeatures features() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the dock manager that manages the dock widget or 0 if the widget
|
|
||||||
* has not been assigned to any dock manager yet
|
|
||||||
*/
|
|
||||||
CDockManager* dockManager() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the dock container widget this dock area widget belongs to or 0
|
|
||||||
* if this dock widget has not been docked yet
|
|
||||||
*/
|
|
||||||
CDockContainerWidget* dockContainer() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the dock area widget this dock widget belongs to or 0
|
|
||||||
* if this dock widget has not been docked yet
|
|
||||||
*/
|
|
||||||
CDockAreaWidget* dockAreaWidget() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This property holds whether the dock widget is floating.
|
|
||||||
* A dock widget is only floating, if it is the one and only widget inside
|
|
||||||
* of a floating container. If there are more than one dock widget in a
|
|
||||||
* floating container, the all dock widgets are docked and not floating.
|
|
||||||
*/
|
|
||||||
bool isFloating() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns true, if this dock widget is in a floating.
|
|
||||||
* The function returns true, if the dock widget is floating and it also
|
|
||||||
* returns true if it is docked inside of a floating container.
|
|
||||||
*/
|
|
||||||
bool isInFloatingContainer() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true, if this dock widget is closed.
|
|
||||||
*/
|
|
||||||
bool isClosed() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a checkable action that can be used to show or close this dock widget.
|
|
||||||
* The action's text is set to the dock widget's window title.
|
|
||||||
*/
|
|
||||||
QAction* toggleViewAction() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the behavior of the toggle view action.
|
|
||||||
* \see eToggleViewActionMode for a detailed description
|
|
||||||
*/
|
|
||||||
void setToggleViewActionMode(eToggleViewActionMode Mode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the dock widget icon that is shown in tabs and in toggle view
|
|
||||||
* actions
|
|
||||||
*/
|
|
||||||
void setIcon(const QIcon& Icon);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the icon that has been assigned to the dock widget
|
|
||||||
*/
|
|
||||||
QIcon icon() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the WithToolBar layout flag is enabled, then this function returns
|
|
||||||
* the dock widget toolbar. If the flag is disabled, the function returns
|
|
||||||
* a nullptr.
|
|
||||||
* This function returns the dock widget top tool bar.
|
|
||||||
* If no toolbar is assigned, this function returns nullptr. To get a vaild
|
|
||||||
* toolbar you either need to create a default empty toolbar via
|
|
||||||
* createDefaultToolBar() function or you need to assign you custom
|
|
||||||
* toolbar via setToolBar().
|
|
||||||
*/
|
|
||||||
QToolBar* toolBar() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If you would like to use the default top tool bar, then call this
|
|
||||||
* function to create the default tool bar.
|
|
||||||
* After this function the toolBar() function will return a valid toolBar()
|
|
||||||
* object.
|
|
||||||
*/
|
|
||||||
QToolBar* createDefaultToolBar();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assign a new tool bar that is shown above the content widget.
|
|
||||||
* The dock widget will become the owner of the tool bar and deletes it
|
|
||||||
* on destruction
|
|
||||||
*/
|
|
||||||
void setToolBar(QToolBar* ToolBar);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function sets the tool button style for the given dock widget state.
|
|
||||||
* It is possible to switch the tool button style depending on the state.
|
|
||||||
* If a dock widget is floating, then here are more space and it is
|
|
||||||
* possible to select a style that requires more space like
|
|
||||||
* Qt::ToolButtonTextUnderIcon. For the docked state Qt::ToolButtonIconOnly
|
|
||||||
* might be better.
|
|
||||||
*/
|
|
||||||
void setToolBarStyle(Qt::ToolButtonStyle Style, eState State);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the tool button style for the given docking state.
|
|
||||||
* \see setToolBarStyle()
|
|
||||||
*/
|
|
||||||
Qt::ToolButtonStyle toolBarStyle(eState State) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function sets the tool button icon size for the given state.
|
|
||||||
* If a dock widget is floating, there is more space an increasing the
|
|
||||||
* icon size is possible. For docked widgets, small icon sizes, eg. 16 x 16
|
|
||||||
* might be better.
|
|
||||||
*/
|
|
||||||
void setToolBarIconSize(const QSize& IconSize, eState State);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the icon size for a given docking state.
|
|
||||||
* \see setToolBarIconSize()
|
|
||||||
*/
|
|
||||||
QSize toolBarIconSize(eState State) const;
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef QT_NO_TOOLTIP
|
|
||||||
/**
|
|
||||||
* This is function sets text tooltip for title bar widget
|
|
||||||
* and tooltip for toggle view action
|
|
||||||
*/
|
|
||||||
void setTabToolTip(const QString &text);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public: // reimplements QFrame -----------------------------------------------
|
|
||||||
/**
|
|
||||||
* Emits titleChanged signal if title change event occurs
|
|
||||||
*/
|
|
||||||
virtual bool event(QEvent *e) override;
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
/**
|
|
||||||
* This property controls whether the dock widget is open or closed.
|
|
||||||
* The toogleViewAction triggers this slot
|
|
||||||
*/
|
|
||||||
void toggleView(bool Open = true);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function will make a docked widget floating
|
|
||||||
*/
|
|
||||||
void setFloating();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function will delete the dock widget and its content from the
|
|
||||||
* docking system
|
|
||||||
*/
|
|
||||||
void deleteDockWidget();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the dock widget
|
|
||||||
*/
|
|
||||||
void closeDockWidget();
|
|
||||||
|
|
||||||
|
|
||||||
signals:
|
|
||||||
/**
|
|
||||||
* This signal is emitted if the dock widget is opened or closed
|
|
||||||
*/
|
|
||||||
void viewToggled(bool Open);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted if the dock widget is closed
|
|
||||||
*/
|
|
||||||
void closed();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted if the window title of this dock widget
|
|
||||||
* changed
|
|
||||||
*/
|
|
||||||
void titleChanged(const QString& Title);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted when the floating property changes.
|
|
||||||
* The topLevel parameter is true if the dock widget is now floating;
|
|
||||||
* otherwise it is false.
|
|
||||||
*/
|
|
||||||
void topLevelChanged(bool topLevel);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted, if close is requested
|
|
||||||
*/
|
|
||||||
void closeRequested();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted when the dock widget becomes visible (or invisible).
|
|
||||||
* This happens when the widget is hidden or shown, as well as when it is
|
|
||||||
* docked in a tabbed dock area and its tab becomes selected or unselected.
|
|
||||||
*/
|
|
||||||
void visibilityChanged(bool visible);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted when the features property changes.
|
|
||||||
* The features parameter gives the new value of the property.
|
|
||||||
*/
|
|
||||||
void featuresChanged(DockWidgetFeatures features);
|
|
||||||
}; // class DockWidget
|
|
||||||
}
|
|
||||||
// namespace ads
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#endif // DockWidgetH
|
|
@ -1,623 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockWidgetTab.cpp
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 27.02.2017
|
|
||||||
/// \brief Implementation of CDockWidgetTab class
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include "FloatingDragPreview.h"
|
|
||||||
#include "ElidingLabel.h"
|
|
||||||
#include "DockWidgetTab.h"
|
|
||||||
|
|
||||||
#include <QBoxLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <QStyle>
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QSplitter>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QToolButton>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QMenu>
|
|
||||||
|
|
||||||
#include "DockWidget.h"
|
|
||||||
#include "DockAreaWidget.h"
|
|
||||||
#include "FloatingDockContainer.h"
|
|
||||||
#include "DockOverlay.h"
|
|
||||||
#include "DockManager.h"
|
|
||||||
#include "IconProvider.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
|
|
||||||
using tTabLabel = CElidingLabel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data class of CDockWidgetTab class (pimpl)
|
|
||||||
*/
|
|
||||||
struct DockWidgetTabPrivate
|
|
||||||
{
|
|
||||||
CDockWidgetTab* _this;
|
|
||||||
CDockWidget* DockWidget;
|
|
||||||
QLabel* IconLabel = nullptr;
|
|
||||||
tTabLabel* TitleLabel;
|
|
||||||
QPoint GlobalDragStartMousePosition;
|
|
||||||
bool IsActiveTab = false;
|
|
||||||
CDockAreaWidget* DockArea = nullptr;
|
|
||||||
eDragState DragState = DraggingInactive;
|
|
||||||
IFloatingWidget* FloatingWidget = nullptr;
|
|
||||||
QIcon Icon;
|
|
||||||
QAbstractButton* CloseButton = nullptr;
|
|
||||||
QSpacerItem* IconTextSpacer;
|
|
||||||
QPoint TabDragStartPosition;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data constructor
|
|
||||||
*/
|
|
||||||
DockWidgetTabPrivate(CDockWidgetTab* _public);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the complete layout including all controls
|
|
||||||
*/
|
|
||||||
void createLayout();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves the tab depending on the position in the given mouse event
|
|
||||||
*/
|
|
||||||
void moveTab(QMouseEvent* ev);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test function for current drag state
|
|
||||||
*/
|
|
||||||
bool isDraggingState(eDragState dragState) const
|
|
||||||
{
|
|
||||||
return this->DragState == dragState;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the given global point is inside the title area geometry
|
|
||||||
* rectangle.
|
|
||||||
* The position is given as global position.
|
|
||||||
*/
|
|
||||||
bool titleAreaGeometryContains(const QPoint& GlobalPos) const
|
|
||||||
{
|
|
||||||
return DockArea->titleBarGeometry().contains(DockArea->mapFromGlobal(GlobalPos));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts floating of the dock widget that belongs to this title bar
|
|
||||||
* Returns true, if floating has been started and false if floating
|
|
||||||
* is not possible for any reason
|
|
||||||
*/
|
|
||||||
bool startFloating(eDragState DraggingState = DraggingFloatingWidget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the given config flag is set
|
|
||||||
*/
|
|
||||||
bool testConfigFlag(CDockManager::eConfigFlag Flag) const
|
|
||||||
{
|
|
||||||
return CDockManager::configFlags().testFlag(Flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the close button as QPushButton or as QToolButton
|
|
||||||
*/
|
|
||||||
QAbstractButton* createCloseButton() const
|
|
||||||
{
|
|
||||||
if (testConfigFlag(CDockManager::TabCloseButtonIsToolButton))
|
|
||||||
{
|
|
||||||
auto Button = new QToolButton();
|
|
||||||
Button->setAutoRaise(true);
|
|
||||||
return Button;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new QPushButton();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
IFloatingWidget* createFloatingWidget(T* Widget, bool OpaqueUndocking)
|
|
||||||
{
|
|
||||||
if (OpaqueUndocking)
|
|
||||||
{
|
|
||||||
return new CFloatingDockContainer(Widget);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto w = new CFloatingDragPreview(Widget);
|
|
||||||
_this->connect(w, &CFloatingDragPreview::draggingCanceled, [=]()
|
|
||||||
{
|
|
||||||
DragState = DraggingInactive;
|
|
||||||
});
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// struct DockWidgetTabPrivate
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
DockWidgetTabPrivate::DockWidgetTabPrivate(CDockWidgetTab* _public) :
|
|
||||||
_this(_public)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockWidgetTabPrivate::createLayout()
|
|
||||||
{
|
|
||||||
TitleLabel = new tTabLabel();
|
|
||||||
TitleLabel->setElideMode(Qt::ElideRight);
|
|
||||||
TitleLabel->setText(DockWidget->windowTitle());
|
|
||||||
TitleLabel->setObjectName("dockWidgetTabLabel");
|
|
||||||
TitleLabel->setAlignment(Qt::AlignCenter);
|
|
||||||
|
|
||||||
CloseButton = createCloseButton();
|
|
||||||
CloseButton->setObjectName("tabCloseButton");
|
|
||||||
QIcon CloseIcon = CDockManager::iconProvider().customIcon(TabCloseIcon);
|
|
||||||
if (CloseIcon.isNull())
|
|
||||||
{
|
|
||||||
// The standard icons do does not look good on high DPI screens
|
|
||||||
QPixmap normalPixmap = _this->style()->standardPixmap(QStyle::SP_TitleBarCloseButton, 0, CloseButton);
|
|
||||||
CloseIcon.addPixmap(normalPixmap, QIcon::Normal);
|
|
||||||
CloseIcon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled);
|
|
||||||
}
|
|
||||||
CloseButton->setIcon(CloseIcon);
|
|
||||||
CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
||||||
_this->onDockWidgetFeaturesChanged();
|
|
||||||
#ifndef QT_NO_TOOLTIP
|
|
||||||
CloseButton->setToolTip(QObject::tr("Close Tab"));
|
|
||||||
#endif
|
|
||||||
_this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeRequested()));
|
|
||||||
|
|
||||||
QFontMetrics fm(TitleLabel->font());
|
|
||||||
int Spacing = qRound(fm.height() / 4.0);
|
|
||||||
|
|
||||||
// Fill the layout
|
|
||||||
QBoxLayout* Layout = new QBoxLayout(QBoxLayout::LeftToRight);
|
|
||||||
Layout->setContentsMargins(2 * Spacing,0,0,0);
|
|
||||||
Layout->setSpacing(0);
|
|
||||||
_this->setLayout(Layout);
|
|
||||||
Layout->addWidget(TitleLabel, 1);
|
|
||||||
Layout->addSpacing(Spacing);
|
|
||||||
Layout->addWidget(CloseButton);
|
|
||||||
Layout->addSpacing(qRound(Spacing * 4.0 / 3.0));
|
|
||||||
Layout->setAlignment(Qt::AlignCenter);
|
|
||||||
|
|
||||||
TitleLabel->setVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void DockWidgetTabPrivate::moveTab(QMouseEvent* ev)
|
|
||||||
{
|
|
||||||
ev->accept();
|
|
||||||
QPoint Distance = ev->globalPos() - GlobalDragStartMousePosition;
|
|
||||||
Distance.setY(0);
|
|
||||||
auto TargetPos = Distance + TabDragStartPosition;
|
|
||||||
_this->move(TargetPos);
|
|
||||||
_this->raise();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool DockWidgetTabPrivate::startFloating(eDragState DraggingState)
|
|
||||||
{
|
|
||||||
auto dockContainer = DockWidget->dockContainer();
|
|
||||||
ADS_PRINT("isFloating " << dockContainer->isFloating());
|
|
||||||
ADS_PRINT("areaCount " << dockContainer->dockAreaCount());
|
|
||||||
ADS_PRINT("widgetCount " << DockWidget->dockAreaWidget()->dockWidgetsCount());
|
|
||||||
// if this is the last dock widget inside of this floating widget,
|
|
||||||
// then it does not make any sense, to make it floating because
|
|
||||||
// it is already floating
|
|
||||||
if (dockContainer->isFloating()
|
|
||||||
&& (dockContainer->visibleDockAreaCount() == 1)
|
|
||||||
&& (DockWidget->dockAreaWidget()->dockWidgetsCount() == 1))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ADS_PRINT("startFloating");
|
|
||||||
DragState = DraggingState;
|
|
||||||
auto DragStartMousePosition = _this->mapFromGlobal(GlobalDragStartMousePosition);
|
|
||||||
QSize Size = DockArea->size();
|
|
||||||
IFloatingWidget* FloatingWidget = nullptr;
|
|
||||||
bool OpaqueUndocking = CDockManager::configFlags().testFlag(CDockManager::OpaqueUndocking) ||
|
|
||||||
(DraggingFloatingWidget != DraggingState);
|
|
||||||
|
|
||||||
// If section widget has multiple tabs, we take only one tab
|
|
||||||
// If it has only one single tab, we can move the complete
|
|
||||||
// dock area into floating widget
|
|
||||||
if (DockArea->dockWidgetsCount() > 1)
|
|
||||||
{
|
|
||||||
FloatingWidget = createFloatingWidget(DockWidget, OpaqueUndocking);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FloatingWidget = createFloatingWidget(DockArea, OpaqueUndocking);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DraggingFloatingWidget == DraggingState)
|
|
||||||
{
|
|
||||||
FloatingWidget->startFloating(DragStartMousePosition, Size, DraggingFloatingWidget, _this);
|
|
||||||
auto Overlay = DockWidget->dockManager()->containerOverlay();
|
|
||||||
Overlay->setAllowedAreas(OuterDockAreas);
|
|
||||||
this->FloatingWidget = FloatingWidget;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FloatingWidget->startFloating(DragStartMousePosition, Size, DraggingInactive, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockWidgetTab::CDockWidgetTab(CDockWidget* DockWidget, QWidget *parent) :
|
|
||||||
QFrame(parent),
|
|
||||||
d(new DockWidgetTabPrivate(this))
|
|
||||||
{
|
|
||||||
setAttribute(Qt::WA_NoMousePropagation, true);
|
|
||||||
d->DockWidget = DockWidget;
|
|
||||||
d->createLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockWidgetTab::~CDockWidgetTab()
|
|
||||||
{
|
|
||||||
ADS_PRINT("~CDockWidgetTab()");
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidgetTab::mousePressEvent(QMouseEvent* ev)
|
|
||||||
{
|
|
||||||
if (ev->button() == Qt::LeftButton)
|
|
||||||
{
|
|
||||||
ev->accept();
|
|
||||||
d->GlobalDragStartMousePosition = ev->globalPos();
|
|
||||||
d->DragState = DraggingMousePressed;
|
|
||||||
emit clicked();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Super::mousePressEvent(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidgetTab::mouseReleaseEvent(QMouseEvent* ev)
|
|
||||||
{
|
|
||||||
if (ev->button() == Qt::LeftButton)
|
|
||||||
{
|
|
||||||
auto CurrentDragState = d->DragState;
|
|
||||||
d->GlobalDragStartMousePosition = QPoint();
|
|
||||||
d->DragState = DraggingInactive;
|
|
||||||
|
|
||||||
switch (CurrentDragState)
|
|
||||||
{
|
|
||||||
case DraggingTab:
|
|
||||||
// End of tab moving, emit signal
|
|
||||||
if (d->DockArea)
|
|
||||||
{
|
|
||||||
emit moved(ev->globalPos());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DraggingFloatingWidget:
|
|
||||||
d->FloatingWidget->finishDragging();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:; // do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Super::mouseReleaseEvent(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
|
|
||||||
{
|
|
||||||
if (!(ev->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive))
|
|
||||||
{
|
|
||||||
d->DragState = DraggingInactive;
|
|
||||||
Super::mouseMoveEvent(ev);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// move floating window
|
|
||||||
if (d->isDraggingState(DraggingFloatingWidget))
|
|
||||||
{
|
|
||||||
d->FloatingWidget->moveFloating();
|
|
||||||
Super::mouseMoveEvent(ev);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// move tab
|
|
||||||
if (d->isDraggingState(DraggingTab))
|
|
||||||
{
|
|
||||||
// Moving the tab is always allowed because it does not mean moving the
|
|
||||||
// dock widget around
|
|
||||||
d->moveTab(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maybe a fixed drag distance is better here ?
|
|
||||||
int DragDistanceY = qAbs(d->GlobalDragStartMousePosition.y() - ev->globalPos().y());
|
|
||||||
if (DragDistanceY >= CDockManager::startDragDistance())
|
|
||||||
{
|
|
||||||
// If this is the last dock area in a dock container with only
|
|
||||||
// one single dock widget it does not make sense to move it to a new
|
|
||||||
// floating widget and leave this one empty
|
|
||||||
if (d->DockArea->dockContainer()->isFloating()
|
|
||||||
&& d->DockArea->openDockWidgetsCount() == 1
|
|
||||||
&& d->DockArea->dockContainer()->visibleDockAreaCount() == 1)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Floating is only allowed for widgets that are movable
|
|
||||||
if (d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable))
|
|
||||||
{
|
|
||||||
// If we undock, we need to restore the initial position of this
|
|
||||||
// tab because it looks strange if it remains on its dragged position
|
|
||||||
if (d->isDraggingState(DraggingTab) && !CDockManager::configFlags().testFlag(CDockManager::OpaqueUndocking))
|
|
||||||
{
|
|
||||||
this->move(d->TabDragStartPosition);
|
|
||||||
}
|
|
||||||
d->startFloating();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (d->DockArea->openDockWidgetsCount() > 1
|
|
||||||
&& (ev->globalPos() - d->GlobalDragStartMousePosition).manhattanLength() >= QApplication::startDragDistance()) // Wait a few pixels before start moving
|
|
||||||
{
|
|
||||||
// If we start dragging the tab, we save its inital position to
|
|
||||||
// restore it later
|
|
||||||
if (DraggingTab != d->DragState)
|
|
||||||
{
|
|
||||||
d->TabDragStartPosition = this->pos();
|
|
||||||
}
|
|
||||||
d->DragState = DraggingTab;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Super::mouseMoveEvent(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev)
|
|
||||||
{
|
|
||||||
ev->accept();
|
|
||||||
if (d->isDraggingState(DraggingFloatingWidget))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->GlobalDragStartMousePosition = ev->globalPos();
|
|
||||||
QMenu Menu(this);
|
|
||||||
auto Action = Menu.addAction(tr("Detach"), this, SLOT(detachDockWidget()));
|
|
||||||
Action->setEnabled(d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable));
|
|
||||||
Menu.addSeparator();
|
|
||||||
Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested()));
|
|
||||||
Action->setEnabled(isClosable());
|
|
||||||
Menu.addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested()));
|
|
||||||
Menu.exec(ev->globalPos());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CDockWidgetTab::isActiveTab() const
|
|
||||||
{
|
|
||||||
return d->IsActiveTab;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidgetTab::setActiveTab(bool active)
|
|
||||||
{
|
|
||||||
bool DockWidgetClosable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetClosable);
|
|
||||||
bool ActiveTabHasCloseButton = d->testConfigFlag(CDockManager::ActiveTabHasCloseButton);
|
|
||||||
bool AllTabsHaveCloseButton = d->testConfigFlag(CDockManager::AllTabsHaveCloseButton);
|
|
||||||
bool TabHasCloseButton = (ActiveTabHasCloseButton && active) | AllTabsHaveCloseButton;
|
|
||||||
d->CloseButton->setVisible(DockWidgetClosable && TabHasCloseButton);
|
|
||||||
if (d->IsActiveTab == active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->IsActiveTab = active;
|
|
||||||
style()->unpolish(this);
|
|
||||||
style()->polish(this);
|
|
||||||
d->TitleLabel->style()->unpolish(d->TitleLabel);
|
|
||||||
d->TitleLabel->style()->polish(d->TitleLabel);
|
|
||||||
update();
|
|
||||||
|
|
||||||
emit activeTabChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockWidget* CDockWidgetTab::dockWidget() const
|
|
||||||
{
|
|
||||||
return d->DockWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidgetTab::setDockAreaWidget(CDockAreaWidget* DockArea)
|
|
||||||
{
|
|
||||||
d->DockArea = DockArea;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockAreaWidget* CDockWidgetTab::dockAreaWidget() const
|
|
||||||
{
|
|
||||||
return d->DockArea;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidgetTab::setIcon(const QIcon& Icon)
|
|
||||||
{
|
|
||||||
QBoxLayout* Layout = qobject_cast<QBoxLayout*>(layout());
|
|
||||||
if (!d->IconLabel && Icon.isNull())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!d->IconLabel)
|
|
||||||
{
|
|
||||||
d->IconLabel = new QLabel();
|
|
||||||
d->IconLabel->setAlignment(Qt::AlignVCenter);
|
|
||||||
d->IconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
|
||||||
#ifndef QT_NO_TOOLTIP
|
|
||||||
d->IconLabel->setToolTip(d->TitleLabel->toolTip());
|
|
||||||
#endif
|
|
||||||
Layout->insertWidget(0, d->IconLabel, Qt::AlignVCenter);
|
|
||||||
Layout->insertSpacing(1, qRound(1.5 * Layout->contentsMargins().left() / 2.0));
|
|
||||||
}
|
|
||||||
else if (Icon.isNull())
|
|
||||||
{
|
|
||||||
// Remove icon label and spacer item
|
|
||||||
Layout->removeWidget(d->IconLabel);
|
|
||||||
Layout->removeItem(Layout->itemAt(0));
|
|
||||||
delete d->IconLabel;
|
|
||||||
d->IconLabel = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->Icon = Icon;
|
|
||||||
if (d->IconLabel)
|
|
||||||
{
|
|
||||||
d->IconLabel->setPixmap(Icon.pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, this)));
|
|
||||||
d->IconLabel->setVisible(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
const QIcon& CDockWidgetTab::icon() const
|
|
||||||
{
|
|
||||||
return d->Icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QString CDockWidgetTab::text() const
|
|
||||||
{
|
|
||||||
return d->TitleLabel->text();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidgetTab::mouseDoubleClickEvent(QMouseEvent *event)
|
|
||||||
{
|
|
||||||
// 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
|
|
||||||
if ((!d->DockArea->dockContainer()->isFloating() || d->DockArea->dockWidgetsCount() > 1)
|
|
||||||
&& d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable))
|
|
||||||
{
|
|
||||||
d->GlobalDragStartMousePosition = event->globalPos();
|
|
||||||
d->startFloating(DraggingInactive);
|
|
||||||
}
|
|
||||||
|
|
||||||
Super::mouseDoubleClickEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidgetTab::setVisible(bool visible)
|
|
||||||
{
|
|
||||||
// Just here for debugging to insert debug output
|
|
||||||
Super::setVisible(visible);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidgetTab::setText(const QString& title)
|
|
||||||
{
|
|
||||||
d->TitleLabel->setText(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CDockWidgetTab::isClosable() const
|
|
||||||
{
|
|
||||||
return d->DockWidget && d->DockWidget->features().testFlag(CDockWidget::DockWidgetClosable);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
void CDockWidgetTab::detachDockWidget()
|
|
||||||
{
|
|
||||||
if (!d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->GlobalDragStartMousePosition = QCursor::pos();
|
|
||||||
d->startFloating(DraggingInactive);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CDockWidgetTab::event(QEvent *e)
|
|
||||||
{
|
|
||||||
#ifndef QT_NO_TOOLTIP
|
|
||||||
if (e->type() == QEvent::ToolTipChange)
|
|
||||||
{
|
|
||||||
const auto text = toolTip();
|
|
||||||
d->TitleLabel->setToolTip(text);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return Super::event(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockWidgetTab::onDockWidgetFeaturesChanged()
|
|
||||||
{
|
|
||||||
auto Features = d->DockWidget->features();
|
|
||||||
auto SizePolicy = d->CloseButton->sizePolicy();
|
|
||||||
SizePolicy.setRetainSizeWhenHidden(Features.testFlag(CDockWidget::DockWidgetClosable)
|
|
||||||
&& d->testConfigFlag(CDockManager::RetainTabSizeWhenCloseButtonHidden));
|
|
||||||
d->CloseButton->setSizePolicy(SizePolicy);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace ads
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// EOF DockWidgetTab.cpp
|
|
@ -1,159 +0,0 @@
|
|||||||
#ifndef DockWidgetTabH
|
|
||||||
#define DockWidgetTabH
|
|
||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockWidgetTab.h
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 27.02.2017
|
|
||||||
/// \brief Declaration of CDockWidgetTab class
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include <QFrame>
|
|
||||||
|
|
||||||
#include "ads_globals.h"
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
class CDockWidget;
|
|
||||||
class CDockAreaWidget;
|
|
||||||
struct DockWidgetTabPrivate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A dock widget tab that shows a title and an icon.
|
|
||||||
* The dock widget tab is shown in the dock area title bar to switch between
|
|
||||||
* tabbed dock widgets
|
|
||||||
*/
|
|
||||||
class CDockWidgetTab : public QFrame
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(bool activeTab READ isActiveTab WRITE setActiveTab NOTIFY activeTabChanged)
|
|
||||||
|
|
||||||
private:
|
|
||||||
DockWidgetTabPrivate* d; ///< private data (pimpl)
|
|
||||||
friend struct DockWidgetTabPrivate;
|
|
||||||
friend class CDockWidget;
|
|
||||||
void onDockWidgetFeaturesChanged();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void detachDockWidget();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void mousePressEvent(QMouseEvent* ev) override;
|
|
||||||
virtual void mouseReleaseEvent(QMouseEvent* ev) override;
|
|
||||||
virtual void mouseMoveEvent(QMouseEvent* ev) override;
|
|
||||||
virtual void contextMenuEvent(QContextMenuEvent* ev) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Double clicking the tab widget makes the assigned dock widget floating
|
|
||||||
*/
|
|
||||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using Super = QFrame;
|
|
||||||
/**
|
|
||||||
* Default Constructor
|
|
||||||
* param[in] DockWidget The dock widget this title bar belongs to
|
|
||||||
* param[in] parent The parent widget of this title bar
|
|
||||||
*/
|
|
||||||
CDockWidgetTab(CDockWidget* DockWidget, QWidget* parent = 0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual Destructor
|
|
||||||
*/
|
|
||||||
virtual ~CDockWidgetTab();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true, if this is the active tab
|
|
||||||
*/
|
|
||||||
bool isActiveTab() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set this true to make this tab the active tab
|
|
||||||
*/
|
|
||||||
void setActiveTab(bool active);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the dock widget this title widget belongs to
|
|
||||||
*/
|
|
||||||
CDockWidget* dockWidget() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the dock area widget the dockWidget returned by dockWidget()
|
|
||||||
* function belongs to.
|
|
||||||
*/
|
|
||||||
void setDockAreaWidget(CDockAreaWidget* DockArea);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the dock area widget this title bar belongs to.
|
|
||||||
* \return This function returns 0 if the dock widget that owns this title
|
|
||||||
* bar widget has not been added to any dock area yet.
|
|
||||||
*/
|
|
||||||
CDockAreaWidget* dockAreaWidget() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the icon to show in title bar
|
|
||||||
*/
|
|
||||||
void setIcon(const QIcon& Icon);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the icon
|
|
||||||
*/
|
|
||||||
const QIcon& icon() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the tab text
|
|
||||||
*/
|
|
||||||
QString text() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the tab text
|
|
||||||
*/
|
|
||||||
void setText(const QString& title);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns true if the assigned dock widget is closable
|
|
||||||
*/
|
|
||||||
bool isClosable() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Track event ToolTipChange and set child ToolTip
|
|
||||||
*/
|
|
||||||
virtual bool event(QEvent *e) override;
|
|
||||||
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
virtual void setVisible(bool visible) override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void activeTabChanged();
|
|
||||||
void clicked();
|
|
||||||
void closeRequested();
|
|
||||||
void closeOtherTabsRequested();
|
|
||||||
void moved(const QPoint& GlobalPos);
|
|
||||||
}; // class DockWidgetTab
|
|
||||||
}
|
|
||||||
// namespace ads
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#endif // DockWidgetTabH
|
|
@ -1,30 +0,0 @@
|
|||||||
//============================================================================
|
|
||||||
/// \file DockingStateReader.cpp
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 29.11.2019
|
|
||||||
/// \brief Implementation of CDockingStateReader
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include "DockingStateReader.h"
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CDockingStateReader::setFileVersion(int FileVersion)
|
|
||||||
{
|
|
||||||
m_FileVersion = FileVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
int CDockingStateReader::fileVersion() const
|
|
||||||
{
|
|
||||||
return m_FileVersion;
|
|
||||||
}
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// EOF DockingStateReader.cpp
|
|
@ -1,43 +0,0 @@
|
|||||||
#ifndef DockingStateReaderH
|
|
||||||
#define DockingStateReaderH
|
|
||||||
//============================================================================
|
|
||||||
/// \file DockingStateReader.h
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 29.11.2019
|
|
||||||
/// \brief Declaration of CDockingStateReader
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include <QXmlStreamReader>
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extends QXmlStreamReader with file version information
|
|
||||||
*/
|
|
||||||
class CDockingStateReader : public QXmlStreamReader
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
int m_FileVersion;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using QXmlStreamReader::QXmlStreamReader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the file version for this state reader
|
|
||||||
*/
|
|
||||||
void setFileVersion(int FileVersion);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the file version set via setFileVersion
|
|
||||||
*/
|
|
||||||
int fileVersion() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
#endif // DockingStateReaderH
|
|
@ -1,220 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file ElidingLabel.cpp
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 05.11.2018
|
|
||||||
/// \brief Implementation of CElidingLabel
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include "ElidingLabel.h"
|
|
||||||
#include <QMouseEvent>
|
|
||||||
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Private data of public CClickableLabel
|
|
||||||
*/
|
|
||||||
struct ElidingLabelPrivate
|
|
||||||
{
|
|
||||||
CElidingLabel* _this;
|
|
||||||
Qt::TextElideMode ElideMode = Qt::ElideNone;
|
|
||||||
QString Text;
|
|
||||||
|
|
||||||
ElidingLabelPrivate(CElidingLabel* _public) : _this(_public) {}
|
|
||||||
|
|
||||||
void elideText(int Width);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience function to check if the
|
|
||||||
*/
|
|
||||||
bool isModeElideNone() const
|
|
||||||
{
|
|
||||||
return Qt::ElideNone == ElideMode;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void ElidingLabelPrivate::elideText(int Width)
|
|
||||||
{
|
|
||||||
if (isModeElideNone())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QFontMetrics fm = _this->fontMetrics();
|
|
||||||
QString str = fm.elidedText(Text, ElideMode, Width - _this->margin() * 2 - _this->indent());
|
|
||||||
if (str == "...")
|
|
||||||
{
|
|
||||||
str = Text.at(0);
|
|
||||||
}
|
|
||||||
_this->QLabel::setText(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CElidingLabel::CElidingLabel(QWidget* parent, Qt::WindowFlags f)
|
|
||||||
: QLabel(parent, f),
|
|
||||||
d(new ElidingLabelPrivate(this))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CElidingLabel::CElidingLabel(const QString& text, QWidget* parent, Qt::WindowFlags f)
|
|
||||||
: QLabel(text, parent,f),
|
|
||||||
d(new ElidingLabelPrivate(this))
|
|
||||||
{
|
|
||||||
d->Text = text;
|
|
||||||
#ifndef QT_NO_TOOLTIP
|
|
||||||
setToolTip(text);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CElidingLabel::~CElidingLabel()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
Qt::TextElideMode CElidingLabel::elideMode() const
|
|
||||||
{
|
|
||||||
return d->ElideMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CElidingLabel::setElideMode(Qt::TextElideMode mode)
|
|
||||||
{
|
|
||||||
d->ElideMode = mode;
|
|
||||||
d->elideText(size().width());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CElidingLabel::mouseReleaseEvent(QMouseEvent* event)
|
|
||||||
{
|
|
||||||
Super::mouseReleaseEvent(event);
|
|
||||||
if (event->button() != Qt::LeftButton)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit clicked();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CElidingLabel::mouseDoubleClickEvent( QMouseEvent *ev )
|
|
||||||
{
|
|
||||||
Q_UNUSED(ev)
|
|
||||||
emit doubleClicked();
|
|
||||||
Super::mouseDoubleClickEvent(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CElidingLabel::resizeEvent(QResizeEvent *event)
|
|
||||||
{
|
|
||||||
if (!d->isModeElideNone())
|
|
||||||
{
|
|
||||||
d->elideText(event->size().width());
|
|
||||||
}
|
|
||||||
Super::resizeEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QSize CElidingLabel::minimumSizeHint() const
|
|
||||||
{
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
if (!pixmap().isNull() || d->isModeElideNone())
|
|
||||||
#else
|
|
||||||
if (pixmap() || d->isModeElideNone())
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return QLabel::minimumSizeHint();
|
|
||||||
}
|
|
||||||
const QFontMetrics &fm = fontMetrics();
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
|
|
||||||
QSize size(fm.horizontalAdvance(d->Text.left(2) + "..."), fm.height());
|
|
||||||
#else
|
|
||||||
QSize size(fm.width(d->Text.left(2) + "…"), fm.height());
|
|
||||||
#endif
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QSize CElidingLabel::sizeHint() const
|
|
||||||
{
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
if (!pixmap().isNull() || d->isModeElideNone())
|
|
||||||
#else
|
|
||||||
if (pixmap() || d->isModeElideNone())
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return QLabel::sizeHint();
|
|
||||||
}
|
|
||||||
const QFontMetrics& fm = fontMetrics();
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
|
|
||||||
QSize size(fm.horizontalAdvance(d->Text), QLabel::sizeHint().height());
|
|
||||||
#else
|
|
||||||
QSize size(fm.width(d->Text), QLabel::sizeHint().height());
|
|
||||||
#endif
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CElidingLabel::setText(const QString &text)
|
|
||||||
{
|
|
||||||
if (d->isModeElideNone())
|
|
||||||
{
|
|
||||||
Super::setText(text);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d->Text = text;
|
|
||||||
#ifndef QT_NO_TOOLTIP
|
|
||||||
setToolTip( text );
|
|
||||||
#endif
|
|
||||||
d->elideText(this->size().width());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QString CElidingLabel::text() const
|
|
||||||
{
|
|
||||||
return d->Text;
|
|
||||||
}
|
|
||||||
} // namespace QtLabb
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// EOF ClickableLabel.cpp
|
|
@ -1,99 +0,0 @@
|
|||||||
#ifndef ElidingLabelH
|
|
||||||
#define ElidingLabelH
|
|
||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file ElidingLabel.h
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 05.11.2018
|
|
||||||
/// \brief Declaration of CElidingLabel
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include <QLabel>
|
|
||||||
|
|
||||||
#include "ads_globals.h"
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
struct ElidingLabelPrivate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A QLabel that supports eliding text.
|
|
||||||
* Because the functions setText() and text() are no virtual functions setting
|
|
||||||
* and reading the text via a pointer to the base class QLabel does not work
|
|
||||||
* properly
|
|
||||||
*/
|
|
||||||
class CElidingLabel : public QLabel
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
private:
|
|
||||||
ElidingLabelPrivate* d;
|
|
||||||
friend struct ElidingLabelPrivate;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void mouseReleaseEvent(QMouseEvent* event) override;
|
|
||||||
virtual void resizeEvent( QResizeEvent *event ) override;
|
|
||||||
virtual void mouseDoubleClickEvent( QMouseEvent *ev ) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using Super = QLabel;
|
|
||||||
|
|
||||||
CElidingLabel(QWidget* parent = 0, Qt::WindowFlags f = Qt::Widget);
|
|
||||||
CElidingLabel(const QString& text, QWidget* parent = 0, Qt::WindowFlags f = Qt::Widget);
|
|
||||||
virtual ~CElidingLabel();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the text elide mode.
|
|
||||||
* The default mode is ElideNone
|
|
||||||
*/
|
|
||||||
Qt::TextElideMode elideMode() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the text elide mode
|
|
||||||
*/
|
|
||||||
void setElideMode(Qt::TextElideMode mode);
|
|
||||||
|
|
||||||
|
|
||||||
public: // reimplements QLabel ----------------------------------------------
|
|
||||||
virtual QSize minimumSizeHint() const override;
|
|
||||||
virtual QSize sizeHint() const override;
|
|
||||||
void setText(const QString &text);
|
|
||||||
QString text() const;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
/**
|
|
||||||
* This signal is emitted if the user clicks on the label (i.e. pressed
|
|
||||||
* down then released while the mouse cursor is inside the label)
|
|
||||||
*/
|
|
||||||
void clicked();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This signal is emitted if the user does a double click on the label
|
|
||||||
*/
|
|
||||||
void doubleClicked();
|
|
||||||
}; //class CElidingLabel
|
|
||||||
|
|
||||||
} // namespace QtLabb
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
#endif // ElidingLabelH
|
|
@ -1,629 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file FloatingDockContainer.cpp
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 01.03.2017
|
|
||||||
/// \brief Implementation of CFloatingDockContainer class
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include "FloatingDockContainer.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <QBoxLayout>
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <QPointer>
|
|
||||||
#include <QAction>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QAbstractButton>
|
|
||||||
#include <QElapsedTimer>
|
|
||||||
|
|
||||||
#include "DockContainerWidget.h"
|
|
||||||
#include "DockAreaWidget.h"
|
|
||||||
#include "DockManager.h"
|
|
||||||
#include "DockWidget.h"
|
|
||||||
#include "DockOverlay.h"
|
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
#include "linux/FloatingWidgetTitleBar.h"
|
|
||||||
#include <xcb/xcb.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
static unsigned int zOrderCounter = 0;
|
|
||||||
/**
|
|
||||||
* Private data class of CFloatingDockContainer class (pimpl)
|
|
||||||
*/
|
|
||||||
struct FloatingDockContainerPrivate
|
|
||||||
{
|
|
||||||
CFloatingDockContainer *_this;
|
|
||||||
CDockContainerWidget *DockContainer;
|
|
||||||
unsigned int zOrderIndex = ++zOrderCounter;
|
|
||||||
QPointer<CDockManager> DockManager;
|
|
||||||
eDragState DraggingState = DraggingInactive;
|
|
||||||
QPoint DragStartMousePosition;
|
|
||||||
CDockContainerWidget *DropContainer = nullptr;
|
|
||||||
CDockAreaWidget *SingleDockArea = nullptr;
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
QWidget* MouseEventHandler = nullptr;
|
|
||||||
CFloatingWidgetTitleBar* TitleBar = nullptr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data constructor
|
|
||||||
*/
|
|
||||||
FloatingDockContainerPrivate(CFloatingDockContainer *_public);
|
|
||||||
|
|
||||||
void titleMouseReleaseEvent();
|
|
||||||
void updateDropOverlays(const QPoint &GlobalPos);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests is a certain state is active
|
|
||||||
*/
|
|
||||||
bool isState(eDragState StateId) const
|
|
||||||
{
|
|
||||||
return StateId == DraggingState;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setState(eDragState StateId)
|
|
||||||
{
|
|
||||||
DraggingState = StateId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setWindowTitle(const QString &Text)
|
|
||||||
{
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
TitleBar->setTitle(Text);
|
|
||||||
#else
|
|
||||||
_this->setWindowTitle(Text);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// struct FloatingDockContainerPrivate
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
FloatingDockContainerPrivate::FloatingDockContainerPrivate(
|
|
||||||
CFloatingDockContainer *_public) :
|
|
||||||
_this(_public)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void FloatingDockContainerPrivate::titleMouseReleaseEvent()
|
|
||||||
{
|
|
||||||
setState(DraggingInactive);
|
|
||||||
if (!DropContainer)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DockManager->dockAreaOverlay()->dropAreaUnderCursor()
|
|
||||||
!= InvalidDockWidgetArea
|
|
||||||
|| DockManager->containerOverlay()->dropAreaUnderCursor()
|
|
||||||
!= InvalidDockWidgetArea)
|
|
||||||
{
|
|
||||||
// Resize the floating widget to the size of the highlighted drop area
|
|
||||||
// rectangle
|
|
||||||
CDockOverlay *Overlay = DockManager->containerOverlay();
|
|
||||||
if (!Overlay->dropOverlayRect().isValid())
|
|
||||||
{
|
|
||||||
Overlay = DockManager->dockAreaOverlay();
|
|
||||||
}
|
|
||||||
|
|
||||||
QRect Rect = Overlay->dropOverlayRect();
|
|
||||||
int FrameWidth = (_this->frameSize().width() - _this->rect().width())
|
|
||||||
/ 2;
|
|
||||||
int TitleBarHeight = _this->frameSize().height()
|
|
||||||
- _this->rect().height() - FrameWidth;
|
|
||||||
if (Rect.isValid())
|
|
||||||
{
|
|
||||||
QPoint TopLeft = Overlay->mapToGlobal(Rect.topLeft());
|
|
||||||
TopLeft.ry() += TitleBarHeight;
|
|
||||||
_this->setGeometry(
|
|
||||||
QRect(TopLeft,
|
|
||||||
QSize(Rect.width(), Rect.height() - TitleBarHeight)));
|
|
||||||
QApplication::processEvents();
|
|
||||||
}
|
|
||||||
DropContainer->dropFloatingWidget(_this, QCursor::pos());
|
|
||||||
}
|
|
||||||
|
|
||||||
DockManager->containerOverlay()->hideOverlay();
|
|
||||||
DockManager->dockAreaOverlay()->hideOverlay();
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos)
|
|
||||||
{
|
|
||||||
if (!_this->isVisible() || !DockManager)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Containers = DockManager->dockContainers();
|
|
||||||
CDockContainerWidget *TopContainer = nullptr;
|
|
||||||
for (auto ContainerWidget : Containers)
|
|
||||||
{
|
|
||||||
if (!ContainerWidget->isVisible())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DockContainer == ContainerWidget)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos);
|
|
||||||
if (ContainerWidget->rect().contains(MappedPos))
|
|
||||||
{
|
|
||||||
if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer))
|
|
||||||
{
|
|
||||||
TopContainer = ContainerWidget;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DropContainer = TopContainer;
|
|
||||||
auto ContainerOverlay = DockManager->containerOverlay();
|
|
||||||
auto DockAreaOverlay = DockManager->dockAreaOverlay();
|
|
||||||
|
|
||||||
if (!TopContainer)
|
|
||||||
{
|
|
||||||
ContainerOverlay->hideOverlay();
|
|
||||||
DockAreaOverlay->hideOverlay();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int VisibleDockAreas = TopContainer->visibleDockAreaCount();
|
|
||||||
ContainerOverlay->setAllowedAreas(
|
|
||||||
VisibleDockAreas > 1 ? OuterDockAreas : AllDockAreas);
|
|
||||||
DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer);
|
|
||||||
ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea);
|
|
||||||
auto DockArea = TopContainer->dockAreaAt(GlobalPos);
|
|
||||||
if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0)
|
|
||||||
{
|
|
||||||
DockAreaOverlay->enableDropPreview(true);
|
|
||||||
DockAreaOverlay->setAllowedAreas(
|
|
||||||
(VisibleDockAreas == 1) ? NoDockWidgetArea : AllDockAreas);
|
|
||||||
DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea);
|
|
||||||
|
|
||||||
// A CenterDockWidgetArea for the dockAreaOverlay() indicates that
|
|
||||||
// the mouse is in the title bar. If the ContainerArea is valid
|
|
||||||
// then we ignore the dock area of the dockAreaOverlay() and disable
|
|
||||||
// the drop preview
|
|
||||||
if ((Area == CenterDockWidgetArea)
|
|
||||||
&& (ContainerArea != InvalidDockWidgetArea))
|
|
||||||
{
|
|
||||||
DockAreaOverlay->enableDropPreview(false);
|
|
||||||
ContainerOverlay->enableDropPreview(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DockAreaOverlay->hideOverlay();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) :
|
|
||||||
tFloatingWidgetBase(DockManager),
|
|
||||||
d(new FloatingDockContainerPrivate(this))
|
|
||||||
{
|
|
||||||
d->DockManager = DockManager;
|
|
||||||
d->DockContainer = new CDockContainerWidget(DockManager, this);
|
|
||||||
connect(d->DockContainer, SIGNAL(dockAreasAdded()), this,
|
|
||||||
SLOT(onDockAreasAddedOrRemoved()));
|
|
||||||
connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this,
|
|
||||||
SLOT(onDockAreasAddedOrRemoved()));
|
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
d->TitleBar = new CFloatingWidgetTitleBar(this);
|
|
||||||
setWindowFlags(windowFlags() | Qt::Tool);
|
|
||||||
QDockWidget::setWidget(d->DockContainer);
|
|
||||||
QDockWidget::setFloating(true);
|
|
||||||
QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures);
|
|
||||||
setTitleBarWidget(d->TitleBar);
|
|
||||||
connect(d->TitleBar, SIGNAL(closeRequested()), SLOT(close()));
|
|
||||||
#else
|
|
||||||
setWindowFlags(
|
|
||||||
Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
|
|
||||||
QBoxLayout *l = new QBoxLayout(QBoxLayout::TopToBottom);
|
|
||||||
l->setContentsMargins(0, 0, 0, 0);
|
|
||||||
l->setSpacing(0);
|
|
||||||
setLayout(l);
|
|
||||||
l->addWidget(d->DockContainer);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DockManager->registerFloatingWidget(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget *DockArea) :
|
|
||||||
CFloatingDockContainer(DockArea->dockManager())
|
|
||||||
{
|
|
||||||
d->DockContainer->addDockArea(DockArea);
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
d->TitleBar->enableCloseButton(isClosable());
|
|
||||||
#endif
|
|
||||||
auto TopLevelDockWidget = topLevelDockWidget();
|
|
||||||
if (TopLevelDockWidget)
|
|
||||||
{
|
|
||||||
TopLevelDockWidget->emitTopLevelChanged(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CFloatingDockContainer::CFloatingDockContainer(CDockWidget *DockWidget) :
|
|
||||||
CFloatingDockContainer(DockWidget->dockManager())
|
|
||||||
{
|
|
||||||
d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget);
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
d->TitleBar->enableCloseButton(isClosable());
|
|
||||||
#endif
|
|
||||||
auto TopLevelDockWidget = topLevelDockWidget();
|
|
||||||
if (TopLevelDockWidget)
|
|
||||||
{
|
|
||||||
TopLevelDockWidget->emitTopLevelChanged(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CFloatingDockContainer::~CFloatingDockContainer()
|
|
||||||
{
|
|
||||||
ADS_PRINT("~CFloatingDockContainer");
|
|
||||||
if (d->DockManager)
|
|
||||||
{
|
|
||||||
d->DockManager->removeFloatingWidget(this);
|
|
||||||
}
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockContainerWidget* CFloatingDockContainer::dockContainer() const
|
|
||||||
{
|
|
||||||
return d->DockContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDockContainer::changeEvent(QEvent *event)
|
|
||||||
{
|
|
||||||
QWidget::changeEvent(event);
|
|
||||||
if ((event->type() == QEvent::ActivationChange) && isActiveWindow())
|
|
||||||
{
|
|
||||||
ADS_PRINT("FloatingWidget::changeEvent QEvent::ActivationChange ");
|
|
||||||
d->zOrderIndex = ++zOrderCounter;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDockContainer::moveEvent(QMoveEvent *event)
|
|
||||||
{
|
|
||||||
QWidget::moveEvent(event);
|
|
||||||
switch (d->DraggingState)
|
|
||||||
{
|
|
||||||
case DraggingMousePressed:
|
|
||||||
d->setState(DraggingFloatingWidget);
|
|
||||||
d->updateDropOverlays(QCursor::pos());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DraggingFloatingWidget:
|
|
||||||
d->updateDropOverlays(QCursor::pos());
|
|
||||||
#ifdef Q_OS_MACOS
|
|
||||||
// In OSX when hiding the DockAreaOverlay the application would set
|
|
||||||
// the main window as the active window for some reason. This fixes
|
|
||||||
// that by resetting the active window to the floating widget after
|
|
||||||
// updating the overlays.
|
|
||||||
QApplication::setActiveWindow(this);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDockContainer::closeEvent(QCloseEvent *event)
|
|
||||||
{
|
|
||||||
ADS_PRINT("CFloatingDockContainer closeEvent");
|
|
||||||
d->setState(DraggingInactive);
|
|
||||||
event->ignore();
|
|
||||||
|
|
||||||
if (isClosable())
|
|
||||||
{
|
|
||||||
auto TopLevelDockWidget = topLevelDockWidget();
|
|
||||||
if (TopLevelDockWidget && TopLevelDockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
|
|
||||||
{
|
|
||||||
if (!TopLevelDockWidget->closeDockWidgetInternal())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// In Qt version after 5.9.2 there seems to be a bug that causes the
|
|
||||||
// QWidget::event() function to not receive any NonClientArea mouse
|
|
||||||
// events anymore after a close/show cycle. The bug is reported here:
|
|
||||||
// https://bugreports.qt.io/browse/QTBUG-73295
|
|
||||||
// The following code is a workaround for Qt versions > 5.9.2 that seems
|
|
||||||
// to work
|
|
||||||
// Starting from Qt version 5.12.2 this seems to work again. But
|
|
||||||
// now the QEvent::NonClientAreaMouseButtonPress function returns always
|
|
||||||
// Qt::RightButton even if the left button was pressed
|
|
||||||
this->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDockContainer::hideEvent(QHideEvent *event)
|
|
||||||
{
|
|
||||||
Super::hideEvent(event);
|
|
||||||
if (event->spontaneous())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prevent toogleView() events during restore state
|
|
||||||
if (d->DockManager->isRestoringState())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto DockArea : d->DockContainer->openedDockAreas())
|
|
||||||
{
|
|
||||||
for (auto DockWidget : DockArea->openedDockWidgets())
|
|
||||||
{
|
|
||||||
DockWidget->toggleView(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDockContainer::showEvent(QShowEvent *event)
|
|
||||||
{
|
|
||||||
Super::showEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CFloatingDockContainer::event(QEvent *e)
|
|
||||||
{
|
|
||||||
switch (d->DraggingState)
|
|
||||||
{
|
|
||||||
case DraggingInactive:
|
|
||||||
{
|
|
||||||
// Normally we would check here, if the left mouse button is pressed.
|
|
||||||
// But from QT version 5.12.2 on the mouse events from
|
|
||||||
// QEvent::NonClientAreaMouseButtonPress return the wrong mouse button
|
|
||||||
// The event always returns Qt::RightButton even if the left button
|
|
||||||
// is clicked.
|
|
||||||
// It is really great to work around the whole NonClientMouseArea
|
|
||||||
// bugs
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 2))
|
|
||||||
if (e->type()
|
|
||||||
== QEvent::NonClientAreaMouseButtonPress /*&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)*/)
|
|
||||||
{
|
|
||||||
ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type());
|
|
||||||
d->setState(DraggingMousePressed);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (e->type() == QEvent::NonClientAreaMouseButtonPress && QGuiApplication::mouseButtons().testFlag(Qt::LeftButton))
|
|
||||||
{
|
|
||||||
ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type());
|
|
||||||
d->setState(DraggingMousePressed);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DraggingMousePressed:
|
|
||||||
switch (e->type())
|
|
||||||
{
|
|
||||||
case QEvent::NonClientAreaMouseButtonDblClick:
|
|
||||||
ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonDblClick");
|
|
||||||
d->setState(DraggingInactive);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QEvent::Resize:
|
|
||||||
// If the first event after the mouse press is a resize event, then
|
|
||||||
// the user resizes the window instead of dragging it around.
|
|
||||||
// But there is one exception. If the window is maximized,
|
|
||||||
// then dragging the window via title bar will cause the widget to
|
|
||||||
// leave the maximized state. This in turn will trigger a resize event.
|
|
||||||
// To know, if the resize event was triggered by user via moving a
|
|
||||||
// corner of the window frame or if it was caused by a windows state
|
|
||||||
// change, we check, if we are not in maximized state.
|
|
||||||
if (!isMaximized())
|
|
||||||
{
|
|
||||||
d->setState(DraggingInactive);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DraggingFloatingWidget:
|
|
||||||
if (e->type() == QEvent::NonClientAreaMouseButtonRelease)
|
|
||||||
{
|
|
||||||
ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease");
|
|
||||||
d->titleMouseReleaseEvent();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (ADS_DEBUG_LEVEL > 0)
|
|
||||||
qDebug() << "CFloatingDockContainer::event " << e->type();
|
|
||||||
#endif
|
|
||||||
return QWidget::event(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos,
|
|
||||||
const QSize &Size, eDragState DragState, QWidget *MouseEventHandler)
|
|
||||||
{
|
|
||||||
#ifndef Q_OS_LINUX
|
|
||||||
Q_UNUSED(MouseEventHandler)
|
|
||||||
#endif
|
|
||||||
resize(Size);
|
|
||||||
d->setState(DragState);
|
|
||||||
d->DragStartMousePosition = DragStartMousePos;
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
if (DraggingFloatingWidget == DragState)
|
|
||||||
{
|
|
||||||
setAttribute(Qt::WA_X11NetWmWindowTypeDock, true);
|
|
||||||
d->MouseEventHandler = MouseEventHandler;
|
|
||||||
if (d->MouseEventHandler)
|
|
||||||
{
|
|
||||||
d->MouseEventHandler->grabMouse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
moveFloating();
|
|
||||||
show();
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDockContainer::moveFloating()
|
|
||||||
{
|
|
||||||
int BorderSize = (frameSize().width() - size().width()) / 2;
|
|
||||||
const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition
|
|
||||||
- QPoint(BorderSize, 0);
|
|
||||||
move(moveToPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CFloatingDockContainer::isClosable() const
|
|
||||||
{
|
|
||||||
return d->DockContainer->features().testFlag(
|
|
||||||
CDockWidget::DockWidgetClosable);
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDockContainer::onDockAreasAddedOrRemoved()
|
|
||||||
{
|
|
||||||
ADS_PRINT("CFloatingDockContainer::onDockAreasAddedOrRemoved()");
|
|
||||||
auto TopLevelDockArea = d->DockContainer->topLevelDockArea();
|
|
||||||
if (TopLevelDockArea)
|
|
||||||
{
|
|
||||||
d->SingleDockArea = TopLevelDockArea;
|
|
||||||
d->setWindowTitle(
|
|
||||||
d->SingleDockArea->currentDockWidget()->windowTitle());
|
|
||||||
connect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
|
|
||||||
SLOT(onDockAreaCurrentChanged(int)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (d->SingleDockArea)
|
|
||||||
{
|
|
||||||
disconnect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
|
|
||||||
SLOT(onDockAreaCurrentChanged(int)));
|
|
||||||
d->SingleDockArea = nullptr;
|
|
||||||
}
|
|
||||||
d->setWindowTitle(qApp->applicationDisplayName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDockContainer::updateWindowTitle()
|
|
||||||
{
|
|
||||||
auto TopLevelDockArea = d->DockContainer->topLevelDockArea();
|
|
||||||
if (TopLevelDockArea)
|
|
||||||
{
|
|
||||||
d->setWindowTitle(TopLevelDockArea->currentDockWidget()->windowTitle());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d->setWindowTitle(qApp->applicationDisplayName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDockContainer::onDockAreaCurrentChanged(int Index)
|
|
||||||
{
|
|
||||||
Q_UNUSED(Index);
|
|
||||||
d->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle());
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CFloatingDockContainer::restoreState(CDockingStateReader &Stream,
|
|
||||||
bool Testing)
|
|
||||||
{
|
|
||||||
if (!d->DockContainer->restoreState(Stream, Testing))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
onDockAreasAddedOrRemoved();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CFloatingDockContainer::hasTopLevelDockWidget() const
|
|
||||||
{
|
|
||||||
return d->DockContainer->hasTopLevelDockWidget();
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockWidget* CFloatingDockContainer::topLevelDockWidget() const
|
|
||||||
{
|
|
||||||
return d->DockContainer->topLevelDockWidget();
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QList<CDockWidget*> CFloatingDockContainer::dockWidgets() const
|
|
||||||
{
|
|
||||||
return d->DockContainer->dockWidgets();
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDockContainer::finishDragging()
|
|
||||||
{
|
|
||||||
ADS_PRINT("CFloatingDockContainer::finishDragging");
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
setAttribute(Qt::WA_X11NetWmWindowTypeDock, false);
|
|
||||||
setWindowOpacity(1);
|
|
||||||
activateWindow();
|
|
||||||
if (d->MouseEventHandler)
|
|
||||||
{
|
|
||||||
d->MouseEventHandler->releaseMouse();
|
|
||||||
d->MouseEventHandler = nullptr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
d->titleMouseReleaseEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// EOF FloatingDockContainer.cpp
|
|
@ -1,244 +0,0 @@
|
|||||||
#ifndef FloatingDockContainerH
|
|
||||||
#define FloatingDockContainerH
|
|
||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file FloatingDockContainer.h
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 01.03.2017
|
|
||||||
/// \brief Declaration of CFloatingDockContainer class
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
#include <QRubberBand>
|
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
#include <QDockWidget>
|
|
||||||
#define tFloatingWidgetBase QDockWidget
|
|
||||||
#else
|
|
||||||
#include <QWidget>
|
|
||||||
#define tFloatingWidgetBase QWidget
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "ads_globals.h"
|
|
||||||
|
|
||||||
class CDockingStateReader;
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
struct FloatingDockContainerPrivate;
|
|
||||||
class CDockManager;
|
|
||||||
struct DockManagerPrivate;
|
|
||||||
class CDockAreaWidget;
|
|
||||||
class CDockContainerWidget;
|
|
||||||
class CDockWidget;
|
|
||||||
class CDockManager;
|
|
||||||
class CDockAreaTabBar;
|
|
||||||
class CDockWidgetTab;
|
|
||||||
struct DockWidgetTabPrivate;
|
|
||||||
class CDockAreaTitleBar;
|
|
||||||
struct DockAreaTitleBarPrivate;
|
|
||||||
class CFloatingWidgetTitleBar;
|
|
||||||
class CDockingStateReader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pure virtual interface for floating widgets.
|
|
||||||
* This interface is used for opaque and non-opaque undocking. If opaque
|
|
||||||
* undocking is used, the a real CFloatingDockContainer widget will be created
|
|
||||||
*/
|
|
||||||
class IFloatingWidget
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Starts floating.
|
|
||||||
* This function should get called typically from a mouse press event
|
|
||||||
* handler
|
|
||||||
*/
|
|
||||||
virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size,
|
|
||||||
eDragState DragState, QWidget* MouseEventHandler) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves the widget to a new position relative to the position given when
|
|
||||||
* startFloating() was called.
|
|
||||||
* This function should be called from a mouse mouve event handler to
|
|
||||||
* move the floating widget on mouse move events.
|
|
||||||
*/
|
|
||||||
virtual void moveFloating() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells the widget that to finish dragging if the mouse is released.
|
|
||||||
* This function should be called from a mouse release event handler
|
|
||||||
* to finish the dragging
|
|
||||||
*/
|
|
||||||
virtual void finishDragging() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This implements a floating widget that is a dock container that accepts
|
|
||||||
* docking of dock widgets like the main window and that can be docked into
|
|
||||||
* another dock container.
|
|
||||||
* Every floating window of the docking system is a FloatingDockContainer.
|
|
||||||
*/
|
|
||||||
class CFloatingDockContainer : public tFloatingWidgetBase, public IFloatingWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
private:
|
|
||||||
FloatingDockContainerPrivate* d; ///< private data (pimpl)
|
|
||||||
friend struct FloatingDockContainerPrivate;
|
|
||||||
friend class CDockManager;
|
|
||||||
friend struct DockManagerPrivate;
|
|
||||||
friend class CDockAreaTabBar;
|
|
||||||
friend struct DockWidgetTabPrivate;
|
|
||||||
friend class CDockWidgetTab;
|
|
||||||
friend class CDockAreaTitleBar;
|
|
||||||
friend struct DockAreaTitleBarPrivate;
|
|
||||||
friend class CDockWidget;
|
|
||||||
friend class CDockAreaWidget;
|
|
||||||
friend class CFloatingWidgetTitleBar;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onDockAreasAddedOrRemoved();
|
|
||||||
void onDockAreaCurrentChanged(int Index);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Starts floating at the given global position.
|
|
||||||
* Use moveToGlobalPos() to move the widget to a new position
|
|
||||||
* depending on the start position given in Pos parameter
|
|
||||||
*/
|
|
||||||
virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size,
|
|
||||||
eDragState DragState, QWidget* MouseEventHandler) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call this function to start dragging the floating widget
|
|
||||||
*/
|
|
||||||
void startDragging(const QPoint& DragStartMousePos, const QSize& Size,
|
|
||||||
QWidget* MouseEventHandler)
|
|
||||||
{
|
|
||||||
startFloating(DragStartMousePos, Size, DraggingFloatingWidget, MouseEventHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call this function if you explicitly want to signal that dragging has
|
|
||||||
* finished
|
|
||||||
*/
|
|
||||||
virtual void finishDragging() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call this function if you just want to initialize the position
|
|
||||||
* and size of the floating widget
|
|
||||||
*/
|
|
||||||
void initFloatingGeometry(const QPoint& DragStartMousePos, const QSize& Size)
|
|
||||||
{
|
|
||||||
startFloating(DragStartMousePos, Size, DraggingInactive, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves the widget to a new position relative to the position given when
|
|
||||||
* startFloating() was called
|
|
||||||
*/
|
|
||||||
void moveFloating();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restores the state from given stream.
|
|
||||||
* If Testing is true, the function only parses the data from the given
|
|
||||||
* stream but does not restore anything. You can use this check for
|
|
||||||
* faulty files before you start restoring the state
|
|
||||||
*/
|
|
||||||
bool restoreState(CDockingStateReader& Stream, bool Testing);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call this function to update the window title
|
|
||||||
*/
|
|
||||||
void updateWindowTitle();
|
|
||||||
|
|
||||||
|
|
||||||
protected: // reimplements QWidget
|
|
||||||
virtual void changeEvent(QEvent *event) override;
|
|
||||||
virtual void moveEvent(QMoveEvent *event) override;
|
|
||||||
virtual bool event(QEvent *e) override;
|
|
||||||
virtual void closeEvent(QCloseEvent *event) override;
|
|
||||||
virtual void hideEvent(QHideEvent *event) override;
|
|
||||||
virtual void showEvent(QShowEvent *event) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using Super = QWidget;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create empty floating widget - required for restore state
|
|
||||||
*/
|
|
||||||
CFloatingDockContainer(CDockManager* DockManager);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create floating widget with the given dock area
|
|
||||||
*/
|
|
||||||
CFloatingDockContainer(CDockAreaWidget* DockArea);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create floating widget with the given dock widget
|
|
||||||
*/
|
|
||||||
CFloatingDockContainer(CDockWidget* DockWidget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual Destructor
|
|
||||||
*/
|
|
||||||
virtual ~CFloatingDockContainer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Access function for the internal dock container
|
|
||||||
*/
|
|
||||||
CDockContainerWidget* dockContainer() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns true, if it can be closed.
|
|
||||||
* It can be closed, if all dock widgets in all dock areas can be closed
|
|
||||||
*/
|
|
||||||
bool isClosable() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns true, if this floating widget has only one single
|
|
||||||
* visible dock widget in a single visible dock area.
|
|
||||||
* The single dock widget is a real top level floating widget because no
|
|
||||||
* other widgets are docked.
|
|
||||||
*/
|
|
||||||
bool hasTopLevelDockWidget() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns the first dock widget in the first dock area.
|
|
||||||
* If the function hasSingleDockWidget() returns true, then this function
|
|
||||||
* returns this single dock widget.
|
|
||||||
*/
|
|
||||||
CDockWidget* topLevelDockWidget() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns a list of all dock widget in this floating widget.
|
|
||||||
* This is a simple convenience function that simply calls the dockWidgets()
|
|
||||||
* function of the internal container widget.
|
|
||||||
*/
|
|
||||||
QList<CDockWidget*> dockWidgets() const;
|
|
||||||
}; // class FloatingDockContainer
|
|
||||||
}
|
|
||||||
// namespace ads
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#endif // FloatingDockContainerH
|
|
@ -1,405 +0,0 @@
|
|||||||
//============================================================================
|
|
||||||
/// \file FloatingDragPreview.cpp
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 26.11.2019
|
|
||||||
/// \brief Implementation of CFloatingDragPreview
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include "FloatingDragPreview.h"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <QEvent>
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QKeyEvent>
|
|
||||||
|
|
||||||
#include "DockWidget.h"
|
|
||||||
#include "DockAreaWidget.h"
|
|
||||||
#include "DockManager.h"
|
|
||||||
#include "DockContainerWidget.h"
|
|
||||||
#include "DockOverlay.h"
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data class (pimpl)
|
|
||||||
*/
|
|
||||||
struct FloatingDragPreviewPrivate
|
|
||||||
{
|
|
||||||
CFloatingDragPreview *_this;
|
|
||||||
QWidget* Content;
|
|
||||||
CDockAreaWidget* ContentSourceArea = nullptr;
|
|
||||||
CDockContainerWidget* ContenSourceContainer = nullptr;
|
|
||||||
QPoint DragStartMousePosition;
|
|
||||||
CDockManager* DockManager;
|
|
||||||
CDockContainerWidget *DropContainer = nullptr;
|
|
||||||
qreal WindowOpacity;
|
|
||||||
bool Hidden = false;
|
|
||||||
QPixmap ContentPreviewPixmap;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data constructor
|
|
||||||
*/
|
|
||||||
FloatingDragPreviewPrivate(CFloatingDragPreview *_public);
|
|
||||||
void updateDropOverlays(const QPoint &GlobalPos);
|
|
||||||
|
|
||||||
void setHidden(bool Value)
|
|
||||||
{
|
|
||||||
Hidden = Value;
|
|
||||||
_this->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancel dragging and emit the draggingCanceled event
|
|
||||||
*/
|
|
||||||
void cancelDragging()
|
|
||||||
{
|
|
||||||
emit _this->draggingCanceled();
|
|
||||||
DockManager->containerOverlay()->hideOverlay();
|
|
||||||
DockManager->dockAreaOverlay()->hideOverlay();
|
|
||||||
_this->close();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// struct LedArrayPanelPrivate
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos)
|
|
||||||
{
|
|
||||||
if (!_this->isVisible() || !DockManager)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Containers = DockManager->dockContainers();
|
|
||||||
CDockContainerWidget *TopContainer = nullptr;
|
|
||||||
for (auto ContainerWidget : Containers)
|
|
||||||
{
|
|
||||||
if (!ContainerWidget->isVisible())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*if (DockContainer == ContainerWidget)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos);
|
|
||||||
if (ContainerWidget->rect().contains(MappedPos))
|
|
||||||
{
|
|
||||||
if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer))
|
|
||||||
{
|
|
||||||
TopContainer = ContainerWidget;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DropContainer = TopContainer;
|
|
||||||
auto ContainerOverlay = DockManager->containerOverlay();
|
|
||||||
auto DockAreaOverlay = DockManager->dockAreaOverlay();
|
|
||||||
auto DockDropArea = DockAreaOverlay->dropAreaUnderCursor();
|
|
||||||
auto ContainerDropArea = ContainerOverlay->dropAreaUnderCursor();
|
|
||||||
|
|
||||||
if (!TopContainer)
|
|
||||||
{
|
|
||||||
ContainerOverlay->hideOverlay();
|
|
||||||
DockAreaOverlay->hideOverlay();
|
|
||||||
if (CDockManager::configFlags().testFlag(CDockManager::DragPreviewIsDynamic))
|
|
||||||
{
|
|
||||||
setHidden(false);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int VisibleDockAreas = TopContainer->visibleDockAreaCount();
|
|
||||||
ContainerOverlay->setAllowedAreas(
|
|
||||||
VisibleDockAreas > 1 ? OuterDockAreas : AllDockAreas);
|
|
||||||
DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer);
|
|
||||||
ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea);
|
|
||||||
auto DockArea = TopContainer->dockAreaAt(GlobalPos);
|
|
||||||
if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0 && DockArea != ContentSourceArea)
|
|
||||||
{
|
|
||||||
DockAreaOverlay->enableDropPreview(true);
|
|
||||||
DockAreaOverlay->setAllowedAreas(
|
|
||||||
(VisibleDockAreas == 1) ? NoDockWidgetArea : AllDockAreas);
|
|
||||||
DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea);
|
|
||||||
|
|
||||||
// A CenterDockWidgetArea for the dockAreaOverlay() indicates that
|
|
||||||
// the mouse is in the title bar. If the ContainerArea is valid
|
|
||||||
// then we ignore the dock area of the dockAreaOverlay() and disable
|
|
||||||
// the drop preview
|
|
||||||
if ((Area == CenterDockWidgetArea)
|
|
||||||
&& (ContainerArea != InvalidDockWidgetArea))
|
|
||||||
{
|
|
||||||
DockAreaOverlay->enableDropPreview(false);
|
|
||||||
ContainerOverlay->enableDropPreview(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DockAreaOverlay->hideOverlay();
|
|
||||||
if (DockArea == ContentSourceArea && InvalidDockWidgetArea == ContainerDropArea)
|
|
||||||
{
|
|
||||||
DropContainer = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CDockManager::configFlags().testFlag(CDockManager::DragPreviewIsDynamic))
|
|
||||||
{
|
|
||||||
setHidden(DockDropArea != InvalidDockWidgetArea || ContainerDropArea != InvalidDockWidgetArea);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
FloatingDragPreviewPrivate::FloatingDragPreviewPrivate(CFloatingDragPreview *_public) :
|
|
||||||
_this(_public)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CFloatingDragPreview::CFloatingDragPreview(QWidget* Content, QWidget* parent) :
|
|
||||||
QWidget(parent),
|
|
||||||
d(new FloatingDragPreviewPrivate(this))
|
|
||||||
{
|
|
||||||
d->Content = Content;
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
if (CDockManager::configFlags().testFlag(CDockManager::DragPreviewHasWindowFrame))
|
|
||||||
{
|
|
||||||
setWindowFlags(
|
|
||||||
Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
|
|
||||||
setAttribute(Qt::WA_NoSystemBackground);
|
|
||||||
setAttribute(Qt::WA_TranslucentBackground);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
auto Flags = windowFlags();
|
|
||||||
Flags |= Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint;
|
|
||||||
setWindowFlags(Flags);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
setWindowOpacity(0.6);
|
|
||||||
|
|
||||||
// Create a static image of the widget that should get undocked
|
|
||||||
// This is like some kind preview image like it is uses in drag and drop
|
|
||||||
// operations
|
|
||||||
if (CDockManager::configFlags().testFlag(CDockManager::DragPreviewShowsContentPixmap))
|
|
||||||
{
|
|
||||||
d->ContentPreviewPixmap = QPixmap(Content->size());
|
|
||||||
Content->render(&d->ContentPreviewPixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)),
|
|
||||||
SLOT(onApplicationStateChanged(Qt::ApplicationState)));
|
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
// In Windows this widget directly receives the escape key press events
|
|
||||||
// in Linux we need to install an event filter for the given Content
|
|
||||||
// widget to receive the escape key press
|
|
||||||
Content->installEventFilter(this);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CFloatingDragPreview::CFloatingDragPreview(CDockWidget* Content)
|
|
||||||
: CFloatingDragPreview((QWidget*)Content, Content->dockManager())
|
|
||||||
{
|
|
||||||
d->DockManager = Content->dockManager();
|
|
||||||
if (Content->dockAreaWidget()->openDockWidgetsCount() == 1)
|
|
||||||
{
|
|
||||||
d->ContentSourceArea = Content->dockAreaWidget();
|
|
||||||
d->ContenSourceContainer = Content->dockContainer();
|
|
||||||
}
|
|
||||||
setWindowTitle(Content->windowTitle());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CFloatingDragPreview::CFloatingDragPreview(CDockAreaWidget* Content)
|
|
||||||
: CFloatingDragPreview((QWidget*)Content, Content->dockManager())
|
|
||||||
{
|
|
||||||
d->DockManager = Content->dockManager();
|
|
||||||
d->ContentSourceArea = Content;
|
|
||||||
d->ContenSourceContainer = Content->dockContainer();
|
|
||||||
setWindowTitle(Content->currentDockWidget()->windowTitle());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CFloatingDragPreview::~CFloatingDragPreview()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDragPreview::moveFloating()
|
|
||||||
{
|
|
||||||
int BorderSize = (frameSize().width() - size().width()) / 2;
|
|
||||||
const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition
|
|
||||||
- QPoint(BorderSize, 0);
|
|
||||||
move(moveToPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDragPreview::startFloating(const QPoint &DragStartMousePos,
|
|
||||||
const QSize &Size, eDragState DragState, QWidget *MouseEventHandler)
|
|
||||||
{
|
|
||||||
Q_UNUSED(MouseEventHandler)
|
|
||||||
Q_UNUSED(DragState)
|
|
||||||
resize(Size);
|
|
||||||
d->DragStartMousePosition = DragStartMousePos;
|
|
||||||
moveFloating();
|
|
||||||
show();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDragPreview::moveEvent(QMoveEvent *event)
|
|
||||||
{
|
|
||||||
QWidget::moveEvent(event);
|
|
||||||
d->updateDropOverlays(QCursor::pos());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDragPreview::finishDragging()
|
|
||||||
{
|
|
||||||
ADS_PRINT("CFloatingDragPreview::finishDragging");
|
|
||||||
auto DockDropArea = d->DockManager->dockAreaOverlay()->dropAreaUnderCursor();
|
|
||||||
auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
|
|
||||||
bool DropPossible = (DockDropArea != InvalidDockWidgetArea) || (ContainerDropArea != InvalidDockWidgetArea);
|
|
||||||
if (d->DropContainer && DropPossible)
|
|
||||||
{
|
|
||||||
d->DropContainer->dropWidget(d->Content, QCursor::pos());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CDockWidget* DockWidget = qobject_cast<CDockWidget*>(d->Content);
|
|
||||||
CFloatingDockContainer* FloatingWidget;
|
|
||||||
if (DockWidget)
|
|
||||||
{
|
|
||||||
FloatingWidget = new CFloatingDockContainer(DockWidget);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(d->Content);
|
|
||||||
FloatingWidget = new CFloatingDockContainer(DockArea);
|
|
||||||
}
|
|
||||||
FloatingWidget->setGeometry(this->geometry());
|
|
||||||
FloatingWidget->show();
|
|
||||||
if (!CDockManager::configFlags().testFlag(CDockManager::DragPreviewHasWindowFrame))
|
|
||||||
{
|
|
||||||
QApplication::processEvents();
|
|
||||||
int FrameHeight = FloatingWidget->frameGeometry().height() - FloatingWidget->geometry().height();
|
|
||||||
QRect FixedGeometry = this->geometry();
|
|
||||||
FixedGeometry.adjust(0, FrameHeight, 0, 0);
|
|
||||||
FloatingWidget->setGeometry(FixedGeometry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this->close();
|
|
||||||
d->DockManager->containerOverlay()->hideOverlay();
|
|
||||||
d->DockManager->dockAreaOverlay()->hideOverlay();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDragPreview::paintEvent(QPaintEvent* event)
|
|
||||||
{
|
|
||||||
Q_UNUSED(event);
|
|
||||||
if (d->Hidden)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPainter painter(this);
|
|
||||||
if (CDockManager::configFlags().testFlag(CDockManager::DragPreviewShowsContentPixmap))
|
|
||||||
{
|
|
||||||
painter.drawPixmap(QPoint(0, 0), d->ContentPreviewPixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we do not have a window frame then we paint a QRubberBand like
|
|
||||||
// frameless window
|
|
||||||
if (!CDockManager::configFlags().testFlag(CDockManager::DragPreviewHasWindowFrame))
|
|
||||||
{
|
|
||||||
QColor Color = palette().color(QPalette::Active, QPalette::Highlight);
|
|
||||||
QPen Pen = painter.pen();
|
|
||||||
Pen.setColor(Color.darker(120));
|
|
||||||
Pen.setStyle(Qt::SolidLine);
|
|
||||||
Pen.setWidth(1);
|
|
||||||
Pen.setCosmetic(true);
|
|
||||||
painter.setPen(Pen);
|
|
||||||
Color = Color.lighter(130);
|
|
||||||
Color.setAlpha(64);
|
|
||||||
painter.setBrush(Color);
|
|
||||||
painter.drawRect(rect().adjusted(0, 0, -1, -1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDragPreview::keyPressEvent(QKeyEvent *event)
|
|
||||||
{
|
|
||||||
Super::keyPressEvent(event);
|
|
||||||
if (event->key() == Qt::Key_Escape)
|
|
||||||
{
|
|
||||||
d->cancelDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CFloatingDragPreview::onApplicationStateChanged(Qt::ApplicationState state)
|
|
||||||
{
|
|
||||||
if (state != Qt::ApplicationActive)
|
|
||||||
{
|
|
||||||
disconnect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)),
|
|
||||||
this, SLOT(onApplicationStateChanged(Qt::ApplicationState)));
|
|
||||||
d->cancelDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
bool CFloatingDragPreview::eventFilter(QObject *watched, QEvent *event)
|
|
||||||
{
|
|
||||||
Q_UNUSED(watched);
|
|
||||||
if (event->type() == QEvent::KeyPress)
|
|
||||||
{
|
|
||||||
QKeyEvent* e = static_cast<QKeyEvent*>(event);
|
|
||||||
if (e->key() == Qt::Key_Escape)
|
|
||||||
{
|
|
||||||
d->Content->removeEventFilter(this);
|
|
||||||
d->cancelDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// EOF FloatingDragPreview.cpp
|
|
@ -1,118 +0,0 @@
|
|||||||
#ifndef FloatingDragPreviewH
|
|
||||||
#define FloatingDragPreviewH
|
|
||||||
//============================================================================
|
|
||||||
/// \file FloatingDragPreview.h
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 26.11.2019
|
|
||||||
/// \brief Declaration of CFloatingDragPreview
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include <QWidget>
|
|
||||||
#include "FloatingDockContainer.h"
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
class CDockWidget;
|
|
||||||
class CDockAreaWidget;
|
|
||||||
struct FloatingDragPreviewPrivate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A floating overlay is a temporary floating widget that is just used to
|
|
||||||
* indicate the floating widget movement.
|
|
||||||
* This widget is used as a placeholder for drag operations for non-opaque
|
|
||||||
* docking
|
|
||||||
*/
|
|
||||||
class CFloatingDragPreview : public QWidget, public IFloatingWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
private:
|
|
||||||
FloatingDragPreviewPrivate* d;
|
|
||||||
friend struct FloatingDragPreviewPrivate;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
/**
|
|
||||||
* Cancel non opaque undocking if application becomes inactive
|
|
||||||
*/
|
|
||||||
void onApplicationStateChanged(Qt::ApplicationState state);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Updates the drop overlays
|
|
||||||
*/
|
|
||||||
virtual void moveEvent(QMoveEvent *event) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cares about painting the
|
|
||||||
*/
|
|
||||||
virtual void paintEvent(QPaintEvent *e) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancel non opaque undocking with escape key
|
|
||||||
*/
|
|
||||||
virtual void keyPressEvent(QKeyEvent *event) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The content is a DockArea or a DockWidget
|
|
||||||
*/
|
|
||||||
CFloatingDragPreview(QWidget* Content, QWidget* parent);
|
|
||||||
|
|
||||||
public:
|
|
||||||
using Super = QWidget;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an instance for undocking the DockWidget in Content parameter
|
|
||||||
*/
|
|
||||||
CFloatingDragPreview(CDockWidget* Content);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an instance for undocking the DockArea given in Content
|
|
||||||
* parameters
|
|
||||||
*/
|
|
||||||
CFloatingDragPreview(CDockAreaWidget* Content);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete private data
|
|
||||||
*/
|
|
||||||
~CFloatingDragPreview();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We filter the events of the assigned content widget to receive
|
|
||||||
* escape key presses for canceling the drag operation
|
|
||||||
*/
|
|
||||||
virtual bool eventFilter(QObject *watched, QEvent *event) override;
|
|
||||||
|
|
||||||
|
|
||||||
public: // implements IFloatingWidget -----------------------------------------
|
|
||||||
virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size,
|
|
||||||
eDragState DragState, QWidget* MouseEventHandler) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves the widget to a new position relative to the position given when
|
|
||||||
* startFloating() was called
|
|
||||||
*/
|
|
||||||
virtual void moveFloating() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finishes dragging.
|
|
||||||
* Hides the dock overlays and executes the real undocking and docking
|
|
||||||
* of the assigned Content widget
|
|
||||||
*/
|
|
||||||
virtual void finishDragging() override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
/**
|
|
||||||
* This signal is emitted, if dragging has been canceled by escape key
|
|
||||||
* or by active application switching via task manager
|
|
||||||
*/
|
|
||||||
void draggingCanceled();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
#endif // FloatingDragPreviewH
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
|||||||
//============================================================================
|
|
||||||
/// \file IconProvider.cpp
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 18.10.2019
|
|
||||||
/// \brief Implementation of CIconProvider
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include "IconProvider.h"
|
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Private data class (pimpl)
|
|
||||||
*/
|
|
||||||
struct IconProviderPrivate
|
|
||||||
{
|
|
||||||
CIconProvider *_this;
|
|
||||||
QVector<QIcon> UserIcons{IconCount, QIcon()};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private data constructor
|
|
||||||
*/
|
|
||||||
IconProviderPrivate(CIconProvider *_public);
|
|
||||||
};
|
|
||||||
// struct LedArrayPanelPrivate
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
IconProviderPrivate::IconProviderPrivate(CIconProvider *_public) :
|
|
||||||
_this(_public)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CIconProvider::CIconProvider() :
|
|
||||||
d(new IconProviderPrivate(this))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CIconProvider::~CIconProvider()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QIcon CIconProvider::customIcon(eIcon IconId) const
|
|
||||||
{
|
|
||||||
Q_ASSERT(IconId < d->UserIcons.size());
|
|
||||||
return d->UserIcons[IconId];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void CIconProvider::registerCustomIcon(eIcon IconId, const QIcon &icon)
|
|
||||||
{
|
|
||||||
Q_ASSERT(IconId < d->UserIcons.size());
|
|
||||||
d->UserIcons[IconId] = icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// EOF IconProvider.cpp
|
|
@ -1,61 +0,0 @@
|
|||||||
#ifndef IconProviderH
|
|
||||||
#define IconProviderH
|
|
||||||
//============================================================================
|
|
||||||
/// \file IconProvider.h
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 18.10.2019
|
|
||||||
/// \brief Declaration of CIconProvider
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include <QIcon>
|
|
||||||
|
|
||||||
#include "ads_globals.h"
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
|
|
||||||
struct IconProviderPrivate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This object provides all icons that are required by the advanced docking
|
|
||||||
* system.
|
|
||||||
* The IconProvider enables the user to register custom icons in case using
|
|
||||||
* stylesheets is not an option.
|
|
||||||
*/
|
|
||||||
class CIconProvider
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
IconProviderPrivate* d; ///< private data (pimpl)
|
|
||||||
friend struct IconProviderPrivate;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Default Constructor
|
|
||||||
*/
|
|
||||||
CIconProvider();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Virtual Destructor
|
|
||||||
*/
|
|
||||||
virtual ~CIconProvider();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The function returns a custom icon if one is registered and a null Icon
|
|
||||||
* if no custom icon is registered
|
|
||||||
*/
|
|
||||||
QIcon customIcon(eIcon IconId) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers a custom icon for the given IconId
|
|
||||||
*/
|
|
||||||
void registerCustomIcon(eIcon IconId, const QIcon &icon);
|
|
||||||
}; // class IconProvider
|
|
||||||
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
#endif // IconProviderH
|
|
@ -1,99 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file ads_globals.cpp
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 24.02.2017
|
|
||||||
/// \brief Implementation of
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include <QVariant>
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
#include "DockSplitter.h"
|
|
||||||
#include "ads_globals.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace internal
|
|
||||||
{
|
|
||||||
//============================================================================
|
|
||||||
void replaceSplitterWidget(QSplitter* Splitter, QWidget* From, QWidget* To)
|
|
||||||
{
|
|
||||||
int index = Splitter->indexOf(From);
|
|
||||||
From->setParent(nullptr);
|
|
||||||
Splitter->insertWidget(index, To);
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
CDockInsertParam dockAreaInsertParameters(DockWidgetArea Area)
|
|
||||||
{
|
|
||||||
switch (Area)
|
|
||||||
{
|
|
||||||
case TopDockWidgetArea: return CDockInsertParam(Qt::Vertical, false);
|
|
||||||
case RightDockWidgetArea: return CDockInsertParam(Qt::Horizontal, true);
|
|
||||||
case CenterDockWidgetArea:
|
|
||||||
case BottomDockWidgetArea: return CDockInsertParam(Qt::Vertical, true);
|
|
||||||
case LeftDockWidgetArea: return CDockInsertParam(Qt::Horizontal, false);
|
|
||||||
default: CDockInsertParam(Qt::Vertical, false);
|
|
||||||
} // switch (Area)
|
|
||||||
|
|
||||||
return CDockInsertParam(Qt::Vertical, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
QPixmap createTransparentPixmap(const QPixmap& Source, qreal Opacity)
|
|
||||||
{
|
|
||||||
QPixmap TransparentPixmap(Source.size());
|
|
||||||
TransparentPixmap.fill(Qt::transparent);
|
|
||||||
QPainter p(&TransparentPixmap);
|
|
||||||
p.setOpacity(Opacity);
|
|
||||||
p.drawPixmap(0, 0, Source);
|
|
||||||
return TransparentPixmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void hideEmptyParentSplitters(CDockSplitter* Splitter)
|
|
||||||
{
|
|
||||||
while (Splitter && Splitter->isVisible())
|
|
||||||
{
|
|
||||||
if (!Splitter->hasVisibleContent())
|
|
||||||
{
|
|
||||||
Splitter->hide();
|
|
||||||
}
|
|
||||||
Splitter = internal::findParent<CDockSplitter*>(Splitter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// EOF ads_globals.cpp
|
|
@ -1,223 +0,0 @@
|
|||||||
#ifndef ads_globalsH
|
|
||||||
#define ads_globalsH
|
|
||||||
/*******************************************************************************
|
|
||||||
** Qt Advanced Docking System
|
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
|
||||||
**
|
|
||||||
** 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,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** 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/>.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
/// \file ads_globals.h
|
|
||||||
/// \author Uwe Kindler
|
|
||||||
/// \date 24.02.2017
|
|
||||||
/// \brief Declaration of
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
// INCLUDES
|
|
||||||
//============================================================================
|
|
||||||
#include <QPair>
|
|
||||||
#include <QtCore/QtGlobal>
|
|
||||||
#include <QPixmap>
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
#ifndef ADS_STATIC
|
|
||||||
#ifdef ADS_SHARED_EXPORT
|
|
||||||
#define ADS_EXPORT Q_DECL_EXPORT
|
|
||||||
#else
|
|
||||||
#define ADS_EXPORT Q_DECL_IMPORT
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define ADS_EXPORT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Define ADS_DEBUG_PRINT to enable a lot of debug output
|
|
||||||
#ifdef ADS_DEBUG_PRINT
|
|
||||||
#define ADS_PRINT(s) qDebug() << s
|
|
||||||
#else
|
|
||||||
#define ADS_PRINT(s)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Set ADS_DEBUG_LEVEL to enable additional debug output and to enable layout
|
|
||||||
// dumps to qDebug and std::cout after layout changes
|
|
||||||
#define ADS_DEBUG_LEVEL 0
|
|
||||||
|
|
||||||
class QSplitter;
|
|
||||||
|
|
||||||
namespace ads
|
|
||||||
{
|
|
||||||
enum eStateFileVersion
|
|
||||||
{
|
|
||||||
InitialVerison = 0,
|
|
||||||
Version1 = 1,
|
|
||||||
CurrentVersion = Version1
|
|
||||||
};
|
|
||||||
|
|
||||||
class CDockSplitter;
|
|
||||||
|
|
||||||
enum DockWidgetArea
|
|
||||||
{
|
|
||||||
NoDockWidgetArea = 0x00,
|
|
||||||
LeftDockWidgetArea = 0x01,
|
|
||||||
RightDockWidgetArea = 0x02,
|
|
||||||
TopDockWidgetArea = 0x04,
|
|
||||||
BottomDockWidgetArea = 0x08,
|
|
||||||
CenterDockWidgetArea = 0x10,
|
|
||||||
|
|
||||||
InvalidDockWidgetArea = NoDockWidgetArea,
|
|
||||||
OuterDockAreas = TopDockWidgetArea | LeftDockWidgetArea | RightDockWidgetArea | BottomDockWidgetArea,
|
|
||||||
AllDockAreas = OuterDockAreas | CenterDockWidgetArea
|
|
||||||
};
|
|
||||||
Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea)
|
|
||||||
|
|
||||||
|
|
||||||
enum TitleBarButton
|
|
||||||
{
|
|
||||||
TitleBarButtonTabsMenu,
|
|
||||||
TitleBarButtonUndock,
|
|
||||||
TitleBarButtonClose
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The different dragging states
|
|
||||||
*/
|
|
||||||
enum eDragState
|
|
||||||
{
|
|
||||||
DraggingInactive, //!< DraggingInactive
|
|
||||||
DraggingMousePressed, //!< DraggingMousePressed
|
|
||||||
DraggingTab, //!< DraggingTab
|
|
||||||
DraggingFloatingWidget//!< DraggingFloatingWidget
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The different icons used in the UI
|
|
||||||
*/
|
|
||||||
enum eIcon
|
|
||||||
{
|
|
||||||
TabCloseIcon, //!< TabCloseIcon
|
|
||||||
DockAreaMenuIcon, //!< DockAreaMenuIcon
|
|
||||||
DockAreaUndockIcon,//!< DockAreaUndockIcon
|
|
||||||
DockAreaCloseIcon, //!< DockAreaCloseIcon
|
|
||||||
|
|
||||||
IconCount, //!< just a delimiter for range checks
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For bitwise combination of dock wdget features
|
|
||||||
*/
|
|
||||||
enum eBitwiseOperator
|
|
||||||
{
|
|
||||||
BitwiseAnd,
|
|
||||||
BitwiseOr
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace internal
|
|
||||||
{
|
|
||||||
static const bool RestoreTesting = true;
|
|
||||||
static const bool Restore = false;
|
|
||||||
static const char* const ClosedProperty = "close";
|
|
||||||
static const char* const DirtyProperty = "dirty";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace the from widget in the given splitter with the To widget
|
|
||||||
*/
|
|
||||||
void replaceSplitterWidget(QSplitter* Splitter, QWidget* From, QWidget* To);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function walks the splitter tree upwards to hides all splitters
|
|
||||||
* that do not have visible content
|
|
||||||
*/
|
|
||||||
void hideEmptyParentSplitters(CDockSplitter* FirstParentSplitter);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience class for QPair to provide better naming than first and
|
|
||||||
* second
|
|
||||||
*/
|
|
||||||
class CDockInsertParam : public QPair<Qt::Orientation, bool>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//using QPair::QPair;
|
|
||||||
CDockInsertParam(Qt::Orientation o, bool b) : QPair<Qt::Orientation, bool>(o, b) {}
|
|
||||||
Qt::Orientation orientation() const {return this->first;}
|
|
||||||
bool append() const {return this->second;}
|
|
||||||
int insertOffset() const {return append() ? 1 : 0;}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the insertion parameters for the given dock area
|
|
||||||
*/
|
|
||||||
CDockInsertParam dockAreaInsertParameters(DockWidgetArea Area);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Searches for the parent widget of the given type.
|
|
||||||
* Returns the parent widget of the given widget or 0 if the widget is not
|
|
||||||
* child of any widget of type T
|
|
||||||
*
|
|
||||||
* It is not safe to use this function in in CDockWidget because only
|
|
||||||
* the current dock widget has a parent. All dock widgets that are not the
|
|
||||||
* current dock widget in a dock area have no parent.
|
|
||||||
*/
|
|
||||||
template <class T>
|
|
||||||
T findParent(const QWidget* w)
|
|
||||||
{
|
|
||||||
QWidget* parentWidget = w->parentWidget();
|
|
||||||
while (parentWidget)
|
|
||||||
{
|
|
||||||
T ParentImpl = qobject_cast<T>(parentWidget);
|
|
||||||
if (ParentImpl)
|
|
||||||
{
|
|
||||||
return ParentImpl;
|
|
||||||
}
|
|
||||||
parentWidget = parentWidget->parentWidget();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a semi transparent pixmap from the given pixmap Source.
|
|
||||||
* The Opacity parameter defines the opacity from completely transparent (0.0)
|
|
||||||
* to completely opaque (1.0)
|
|
||||||
*/
|
|
||||||
QPixmap createTransparentPixmap(const QPixmap& Source, qreal Opacity);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function for settings flags in a QFlags instance.
|
|
||||||
*/
|
|
||||||
template <class T>
|
|
||||||
void setFlag(T& Flags, typename T::enum_type flag, bool on = true)
|
|
||||||
{
|
|
||||||
#if QT_VERSION >= 0x050700
|
|
||||||
Flags.setFlag(flag, on);
|
|
||||||
#else
|
|
||||||
if(on)
|
|
||||||
{
|
|
||||||
Flags |= flag;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Flags &= ~flag;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace ads
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
#endif // ads_globalsH
|
|
@ -20,10 +20,10 @@ DockTitleBar::~DockTitleBar() {
|
|||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize DockTitleBar::minimumSizeHint() const {
|
//QSize DockTitleBar::minimumSizeHint() const {
|
||||||
QSize s = size();
|
// QSize s = size();
|
||||||
return s;
|
// return s;
|
||||||
}
|
//}
|
||||||
|
|
||||||
void DockTitleBar::SetTitle(const QString& title) {
|
void DockTitleBar::SetTitle(const QString& title) {
|
||||||
ui->sys_title->setText(title);
|
ui->sys_title->setText(title);
|
||||||
|
@ -13,7 +13,7 @@ public:
|
|||||||
DockTitleBar(QWidget* parent = 0);
|
DockTitleBar(QWidget* parent = 0);
|
||||||
~DockTitleBar() override;
|
~DockTitleBar() override;
|
||||||
|
|
||||||
QSize minimumSizeHint() const override;
|
//QSize minimumSizeHint() const override;
|
||||||
|
|
||||||
void SetTitle(const QString& title) override;
|
void SetTitle(const QString& title) override;
|
||||||
|
|
||||||
|
@ -16,14 +16,14 @@ DockWidgetTitleBar::~DockWidgetTitleBar() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize DockWidgetTitleBar::minimumSizeHint() const {
|
//QSize DockWidgetTitleBar::minimumSizeHint() const {
|
||||||
QDockWidget* dw = qobject_cast<QDockWidget*>(parentWidget());
|
// QDockWidget* dw = qobject_cast<QDockWidget*>(parentWidget());
|
||||||
Q_ASSERT(dw);
|
// Q_ASSERT(dw);
|
||||||
QSize result(0, 90);
|
// QSize result(0, 90);
|
||||||
if (dw->features() & QDockWidget::DockWidgetVerticalTitleBar)
|
// if (dw->features() & QDockWidget::DockWidgetVerticalTitleBar)
|
||||||
result.transpose();
|
// result.transpose();
|
||||||
return result;
|
// return result;
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
|
||||||
DockWidget::DockWidget(const QString& title, QWidget* parent)
|
DockWidget::DockWidget(const QString& title, QWidget* parent)
|
||||||
|
@ -14,10 +14,10 @@ public:
|
|||||||
|
|
||||||
virtual void SetTitle(const QString& title) {}
|
virtual void SetTitle(const QString& title) {}
|
||||||
|
|
||||||
QSize sizeHint() const override {
|
//QSize sizeHint() const override {
|
||||||
return minimumSizeHint();
|
// return QSize(270, 900);
|
||||||
}
|
//}
|
||||||
QSize minimumSizeHint() const override;
|
//QSize minimumSizeHint() const override;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void signalClose();
|
void signalClose();
|
||||||
|
Loading…
Reference in New Issue
Block a user