2017-03-23 17:23:53 +08:00
/*******************************************************************************
2017-06-10 04:04:02 +08:00
* * Qt Advanced Docking System
2017-03-23 17:23:53 +08:00
* * Copyright ( C ) 2017 Uwe Kindler
2017-06-10 04:04:02 +08:00
* *
* * This library is free software ; you can redistribute it and / or
* * modify it under the terms of the GNU Lesser General Public
* * License as published by the Free Software Foundation ; either
* * version 2.1 of the License , or ( at your option ) any later version .
* *
* * This library is distributed in the hope that it will be useful ,
2017-03-23 17:23:53 +08:00
* * but WITHOUT ANY WARRANTY ; without even the implied warranty of
2017-06-10 04:04:02 +08:00
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* * Lesser General Public License for more details .
* *
* * You should have received a copy of the GNU Lesser General Public
* * License along with this library ; If not , see < http : //www.gnu.org/licenses/>.
2017-03-23 17:23:53 +08:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//============================================================================
/// \file DockContainerWidget.cpp
/// \author Uwe Kindler
/// \date 24.02.2017
/// \brief Implementation of CDockContainerWidget class
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
# include "DockContainerWidget.h"
# include <QEvent>
# include <QList>
# include <QGridLayout>
# include <QPointer>
2017-03-28 16:57:03 +08:00
# include <QVariant>
2017-03-28 18:01:27 +08:00
# include <QDebug>
2017-12-30 01:18:16 +08:00
# include <QXmlStreamWriter>
2018-11-05 16:07:18 +08:00
# include <QAbstractButton>
2022-09-05 17:29:42 +08:00
# include <QLabel>
2017-03-23 17:23:53 +08:00
# include "DockManager.h"
# include "DockAreaWidget.h"
# include "DockWidget.h"
2019-11-29 22:56:57 +08:00
# include "DockingStateReader.h"
2017-03-23 17:23:53 +08:00
# include "FloatingDockContainer.h"
# include "DockOverlay.h"
# include "ads_globals.h"
2017-03-24 17:18:25 +08:00
# include "DockSplitter.h"
2022-09-05 17:29:42 +08:00
# include "SideTabBar.h"
# include "OverlayDockContainer.h"
# include "DockWidgetTab.h"
# include "DockWidgetSideTab.h"
# include "DockAreaTitleBar.h"
2022-09-15 13:04:49 +08:00
# include "DockFocusController.h"
2017-03-23 17:23:53 +08:00
2019-01-17 01:52:53 +08:00
# include <functional>
2018-12-03 19:52:57 +08:00
# include <iostream>
2018-10-10 21:15:59 +08:00
2019-01-14 15:59:37 +08:00
# if QT_VERSION < 0x050900
inline char toHexLower ( uint value )
{
return " 0123456789abcdef " [ value & 0xF ] ;
}
QByteArray qByteArrayToHex ( const QByteArray & src , char separator )
{
if ( src . size ( ) = = 0 )
return QByteArray ( ) ;
const int length = separator ? ( src . size ( ) * 3 - 1 ) : ( src . size ( ) * 2 ) ;
QByteArray hex ( length , Qt : : Uninitialized ) ;
char * hexData = hex . data ( ) ;
2019-01-17 01:52:53 +08:00
const uchar * data = reinterpret_cast < const uchar * > ( src . data ( ) ) ;
2019-01-14 15:59:37 +08:00
for ( int i = 0 , o = 0 ; i < src . size ( ) ; + + i ) {
hexData [ o + + ] = toHexLower ( data [ i ] > > 4 ) ;
hexData [ o + + ] = toHexLower ( data [ i ] & 0xf ) ;
if ( ( separator ) & & ( o < length ) )
hexData [ o + + ] = separator ;
}
return hex ;
}
# endif
2017-03-23 17:23:53 +08:00
namespace ads
{
static unsigned int zOrderCounter = 0 ;
2019-11-27 22:50:18 +08:00
enum eDropMode
{
DropModeIntoArea , ///< drop widget into a dock area
DropModeIntoContainer , ///< drop into container
DropModeInvalid ///< invalid mode - do not drop
} ;
2018-09-07 17:10:14 +08:00
/**
* Converts dock area ID to an index for array access
*/
static int areaIdToIndex ( DockWidgetArea area )
{
switch ( area )
{
case LeftDockWidgetArea : return 0 ;
case RightDockWidgetArea : return 1 ;
case TopDockWidgetArea : return 2 ;
case BottomDockWidgetArea : return 3 ;
case CenterDockWidgetArea : return 4 ;
default :
return 4 ;
}
}
2017-03-23 17:23:53 +08:00
/**
* Helper function to ease insertion of dock area into splitter
*/
static void insertWidgetIntoSplitter ( QSplitter * Splitter , QWidget * widget , bool Append )
{
if ( Append )
{
Splitter - > addWidget ( widget ) ;
}
else
{
Splitter - > insertWidget ( 0 , widget ) ;
}
}
/**
* Private data class of CDockContainerWidget class ( pimpl )
*/
2018-11-01 14:53:54 +08:00
class DockContainerWidgetPrivate
2017-03-23 17:23:53 +08:00
{
2018-11-01 14:53:54 +08:00
public :
2017-03-23 17:23:53 +08:00
CDockContainerWidget * _this ;
QPointer < CDockManager > DockManager ;
unsigned int zOrderIndex = 0 ;
QList < CDockAreaWidget * > DockAreas ;
2022-09-06 17:42:26 +08:00
QList < COverlayDockContainer * > OverlayWidgets ;
2022-09-08 11:30:56 +08:00
QMap < CDockWidgetSideTab : : SideTabBarArea , CSideTabBar * > SideTabBarWidgets ;
2017-03-23 17:23:53 +08:00
QGridLayout * Layout = nullptr ;
2018-12-11 22:19:59 +08:00
QSplitter * RootSplitter = nullptr ;
2017-03-23 17:23:53 +08:00
bool isFloating = false ;
2019-01-26 00:28:36 +08:00
CDockAreaWidget * LastAddedAreaCache [ 5 ] ;
2018-11-01 14:53:54 +08:00
int VisibleDockAreaCount = - 1 ;
2018-11-05 16:07:18 +08:00
CDockAreaWidget * TopLevelDockArea = nullptr ;
2017-03-23 17:23:53 +08:00
/**
* Private data constructor
*/
DockContainerWidgetPrivate ( CDockContainerWidget * _public ) ;
/**
* Adds dock widget to container and returns the dock area that contains
* the inserted dock widget
*/
2020-06-14 16:39:07 +08:00
CDockAreaWidget * addDockWidgetToContainer ( DockWidgetArea area , CDockWidget * Dockwidget ) ;
2017-03-23 17:23:53 +08:00
/**
* Adds dock widget to a existing DockWidgetArea
*/
2020-06-14 16:39:07 +08:00
CDockAreaWidget * addDockWidgetToDockArea ( DockWidgetArea area , CDockWidget * Dockwidget ,
2017-03-23 17:23:53 +08:00
CDockAreaWidget * TargetDockArea ) ;
/**
* Add dock area to this container
*/
void addDockArea ( CDockAreaWidget * NewDockWidget , DockWidgetArea area = CenterDockWidgetArea ) ;
/**
* Drop floating widget into container
*/
void dropIntoContainer ( CFloatingDockContainer * FloatingWidget , DockWidgetArea area ) ;
/**
* Drop floating widget into dock area
*/
void dropIntoSection ( CFloatingDockContainer * FloatingWidget ,
CDockAreaWidget * TargetArea , DockWidgetArea area ) ;
2019-11-26 21:40:56 +08:00
/**
* Moves the dock widget or dock area given in Widget parameter to a
* new dock widget area
*/
void moveToNewSection ( QWidget * Widget , CDockAreaWidget * TargetArea , DockWidgetArea area ) ;
2019-11-27 19:00:04 +08:00
/**
* Moves the dock widget or dock area given in Widget parameter to a
* a dock area in container
*/
void moveToContainer ( QWidget * Widgett , DockWidgetArea area ) ;
2019-01-14 20:58:40 +08:00
/**
* Creates a new tab for a widget dropped into the center of a section
*/
void dropIntoCenterOfSection ( CFloatingDockContainer * FloatingWidget ,
CDockAreaWidget * TargetArea ) ;
2019-11-26 21:40:56 +08:00
/**
* Creates a new tab for a widget dropped into the center of a section
*/
void moveIntoCenterOfSection ( QWidget * Widget , CDockAreaWidget * TargetArea ) ;
2017-03-23 17:23:53 +08:00
/**
* Adds new dock areas to the internal dock area list
*/
void addDockAreasToList ( const QList < CDockAreaWidget * > NewDockAreas ) ;
2017-03-23 22:57:15 +08:00
2018-11-05 16:07:18 +08:00
/**
* Wrapper function for DockAreas append , that ensures that dock area signals
* are properly connected to dock container slots
*/
void appendDockAreas ( const QList < CDockAreaWidget * > NewDockAreas ) ;
2017-03-23 22:57:15 +08:00
/**
* Save state of child nodes
*/
2017-12-30 01:18:16 +08:00
void saveChildNodesState ( QXmlStreamWriter & Stream , QWidget * Widget ) ;
2017-03-23 22:57:15 +08:00
/**
2022-09-05 17:29:42 +08:00
* Save state of overlay widgets
*/
void saveOverlayWidgetsState ( QXmlStreamWriter & Stream ) ;
/**
2017-03-27 16:41:27 +08:00
* Restore state of child nodes .
* \ param [ in ] Stream The data stream that contains the serialized state
2017-03-27 19:18:16 +08:00
* \ param [ out ] CreatedWidget The widget created from parsed data or 0 if
* the parsed widget was an empty splitter
2017-03-27 16:41:27 +08:00
* \ param [ in ] Testing If Testing is true , only the stream data is
* parsed without modifiying anything .
2017-03-23 22:57:15 +08:00
*/
2019-11-29 22:56:57 +08:00
bool restoreChildNodes ( CDockingStateReader & Stream , QWidget * & CreatedWidget ,
2017-03-27 16:41:27 +08:00
bool Testing ) ;
/**
* Restores a splitter .
* \ see restoreChildNodes ( ) for details
*/
2019-11-29 22:56:57 +08:00
bool restoreSplitter ( CDockingStateReader & Stream , QWidget * & CreatedWidget ,
2017-03-27 16:41:27 +08:00
bool Testing ) ;
/**
* Restores a dock area .
* \ see restoreChildNodes ( ) for details
*/
2019-11-29 22:56:57 +08:00
bool restoreDockArea ( CDockingStateReader & Stream , QWidget * & CreatedWidget ,
2017-03-27 16:41:27 +08:00
bool Testing ) ;
2017-03-28 14:48:44 +08:00
2022-09-05 17:29:42 +08:00
/**
* Restores the overlay dock area .
* Assumes that there are no overlay dock areas , and then restores all the dock areas that
* exist in the XML
*/
2022-09-08 11:30:56 +08:00
bool restoreOverlayDockArea ( CDockingStateReader & s , CDockWidgetSideTab : : SideTabBarArea area , bool Testing ) ;
2022-09-05 17:29:42 +08:00
/**
* Restores either a dock area or an overlay dock area depending on the value in the XML
*/
bool restoreDockOrOverlayDockArea ( CDockingStateReader & Stream , QWidget * & CreatedWidget ,
bool Testing ) ;
2017-03-28 14:48:44 +08:00
/**
* Helper function for recursive dumping of layout
*/
void dumpRecursive ( int level , QWidget * widget ) ;
2018-11-01 14:53:54 +08:00
2019-11-27 22:50:18 +08:00
/**
* Calculate the drop mode from the given target position
*/
eDropMode getDropMode ( const QPoint & TargetPos ) ;
2018-11-01 14:53:54 +08:00
/**
* Initializes the visible dock area count variable if it is not initialized
* yet
*/
void initVisibleDockAreaCount ( )
{
if ( VisibleDockAreaCount > - 1 )
{
return ;
}
VisibleDockAreaCount = 0 ;
for ( auto DockArea : DockAreas )
{
VisibleDockAreaCount + = DockArea - > isHidden ( ) ? 0 : 1 ;
}
}
/**
* Access function for the visible dock area counter
*/
int & visibleDockAreaCount ( )
{
// Lazy initialisation - we initialize the VisibleDockAreaCount variable
// on first use
initVisibleDockAreaCount ( ) ;
return VisibleDockAreaCount ;
}
2018-11-05 16:07:18 +08:00
/**
* The visible dock area count changes , if dock areas are remove , added or
* when its view is toggled
*/
void onVisibleDockAreaCountChanged ( ) ;
void emitDockAreasRemoved ( )
{
onVisibleDockAreaCountChanged ( ) ;
2021-01-22 13:18:34 +08:00
Q_EMIT _this - > dockAreasRemoved ( ) ;
2018-11-05 16:07:18 +08:00
}
void emitDockAreasAdded ( )
{
onVisibleDockAreaCountChanged ( ) ;
2021-01-22 13:18:34 +08:00
Q_EMIT _this - > dockAreasAdded ( ) ;
2018-11-05 16:07:18 +08:00
}
2018-12-11 22:19:59 +08:00
/**
* Helper function for creation of new splitter
*/
2019-01-26 00:28:36 +08:00
CDockSplitter * newSplitter ( Qt : : Orientation orientation , QWidget * parent = nullptr )
2018-12-11 22:19:59 +08:00
{
CDockSplitter * s = new CDockSplitter ( orientation , parent ) ;
2020-06-11 14:06:37 +08:00
s - > setOpaqueResize ( CDockManager : : testConfigFlag ( CDockManager : : OpaqueSplitterResize ) ) ;
2018-12-11 22:19:59 +08:00
s - > setChildrenCollapsible ( false ) ;
return s ;
}
2020-06-14 16:39:07 +08:00
/**
* Ensures equal distribution of the sizes of a splitter if an dock widget
* is inserted from code
*/
void adjustSplitterSizesOnInsertion ( QSplitter * Splitter , qreal LastRatio = 1.0 )
2020-06-13 22:59:13 +08:00
{
int AreaSize = ( Splitter - > orientation ( ) = = Qt : : Horizontal ) ? Splitter - > width ( ) : Splitter - > height ( ) ;
auto SplitterSizes = Splitter - > sizes ( ) ;
qreal TotRatio = SplitterSizes . size ( ) - 1.0 + LastRatio ;
2020-06-14 16:39:07 +08:00
for ( int i = 0 ; i < SplitterSizes . size ( ) - 1 ; i + + )
2020-06-13 22:59:13 +08:00
{
SplitterSizes [ i ] = AreaSize / TotRatio ;
}
2020-06-13 23:22:25 +08:00
SplitterSizes . back ( ) = AreaSize * LastRatio / TotRatio ;
2020-06-13 22:59:13 +08:00
Splitter - > setSizes ( SplitterSizes ) ;
}
2020-08-20 22:36:02 +08:00
/**
2020-08-24 16:22:12 +08:00
* This function forces the dock container widget to update handles of splitters
* based if a central widget exists .
2020-08-20 22:36:02 +08:00
*/
void updateSplitterHandles ( QSplitter * splitter ) ;
/**
2020-08-24 16:22:12 +08:00
* If no central widget exists , the widgets resize with the container .
* If a central widget exists , the widgets surrounding the central widget
* do not resize its height or width .
2020-08-20 22:36:02 +08:00
*/
bool widgetResizesWithContainer ( QWidget * widget ) ;
2020-06-14 16:39:07 +08:00
// private slots: ------------------------------------------------------------
void onDockAreaViewToggled ( bool Visible )
{
CDockAreaWidget * DockArea = qobject_cast < CDockAreaWidget * > ( _this - > sender ( ) ) ;
VisibleDockAreaCount + = Visible ? 1 : - 1 ;
onVisibleDockAreaCountChanged ( ) ;
2021-01-22 13:18:34 +08:00
Q_EMIT _this - > dockAreaViewToggled ( DockArea , Visible ) ;
2020-06-14 16:39:07 +08:00
}
2017-03-23 17:23:53 +08:00
} ; // struct DockContainerWidgetPrivate
//============================================================================
DockContainerWidgetPrivate : : DockContainerWidgetPrivate ( CDockContainerWidget * _public ) :
_this ( _public )
{
2019-01-26 00:28:36 +08:00
std : : fill ( std : : begin ( LastAddedAreaCache ) , std : : end ( LastAddedAreaCache ) , nullptr ) ;
2017-03-23 17:23:53 +08:00
}
2019-11-27 22:50:18 +08:00
//============================================================================
eDropMode DockContainerWidgetPrivate : : getDropMode ( const QPoint & TargetPos )
{
CDockAreaWidget * DockArea = _this - > dockAreaAt ( TargetPos ) ;
auto dropArea = InvalidDockWidgetArea ;
auto ContainerDropArea = DockManager - > containerOverlay ( ) - > dropAreaUnderCursor ( ) ;
if ( DockArea )
{
auto dropOverlay = DockManager - > dockAreaOverlay ( ) ;
2020-02-02 22:56:31 +08:00
dropOverlay - > setAllowedAreas ( DockArea - > allowedAreas ( ) ) ;
2019-11-27 22:50:18 +08:00
dropArea = dropOverlay - > showOverlay ( DockArea ) ;
if ( ContainerDropArea ! = InvalidDockWidgetArea & &
ContainerDropArea ! = dropArea )
{
dropArea = InvalidDockWidgetArea ;
}
if ( dropArea ! = InvalidDockWidgetArea )
{
ADS_PRINT ( " Dock Area Drop Content: " < < dropArea ) ;
return DropModeIntoArea ;
}
}
// mouse is over container
if ( InvalidDockWidgetArea = = dropArea )
{
dropArea = ContainerDropArea ;
ADS_PRINT ( " Container Drop Content: " < < dropArea ) ;
if ( dropArea ! = InvalidDockWidgetArea )
{
return DropModeIntoContainer ;
}
}
return DropModeInvalid ;
}
2018-11-05 16:07:18 +08:00
//============================================================================
void DockContainerWidgetPrivate : : onVisibleDockAreaCountChanged ( )
{
auto TopLevelDockArea = _this - > topLevelDockArea ( ) ;
if ( TopLevelDockArea )
{
this - > TopLevelDockArea = TopLevelDockArea ;
2022-09-08 16:08:20 +08:00
TopLevelDockArea - > updateTitleBarButtonVisibility ( true ) ;
2018-11-05 16:07:18 +08:00
}
else if ( this - > TopLevelDockArea )
{
2022-09-08 16:08:20 +08:00
this - > TopLevelDockArea - > updateTitleBarButtonVisibility ( false ) ;
2018-11-05 16:07:18 +08:00
this - > TopLevelDockArea = nullptr ;
}
}
2017-03-23 17:23:53 +08:00
//============================================================================
void DockContainerWidgetPrivate : : dropIntoContainer ( CFloatingDockContainer * FloatingWidget ,
DockWidgetArea area )
{
auto InsertParam = internal : : dockAreaInsertParameters ( area ) ;
2018-09-14 19:21:29 +08:00
CDockContainerWidget * FloatingDockContainer = FloatingWidget - > dockContainer ( ) ;
auto NewDockAreas = FloatingDockContainer - > findChildren < CDockAreaWidget * > (
2017-03-23 17:23:53 +08:00
QString ( ) , Qt : : FindChildrenRecursively ) ;
2017-03-24 19:54:43 +08:00
QSplitter * Splitter = RootSplitter ;
2017-03-23 17:23:53 +08:00
2017-03-24 19:54:43 +08:00
if ( DockAreas . count ( ) < = 1 )
2017-03-23 17:23:53 +08:00
{
2017-03-24 19:54:43 +08:00
Splitter - > setOrientation ( InsertParam . orientation ( ) ) ;
}
2017-03-28 14:48:44 +08:00
else if ( Splitter - > orientation ( ) ! = InsertParam . orientation ( ) )
2017-03-24 19:54:43 +08:00
{
2018-12-11 22:19:59 +08:00
QSplitter * NewSplitter = newSplitter ( InsertParam . orientation ( ) ) ;
2017-03-24 19:54:43 +08:00
QLayoutItem * li = Layout - > replaceWidget ( Splitter , NewSplitter ) ;
NewSplitter - > addWidget ( Splitter ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( NewSplitter ) ;
Splitter = NewSplitter ;
2017-03-29 18:18:49 +08:00
delete li ;
2017-03-23 17:23:53 +08:00
}
// Now we can insert the floating widget content into this container
2018-09-14 19:21:29 +08:00
auto FloatingSplitter = FloatingDockContainer - > rootSplitter ( ) ;
2017-03-28 14:48:44 +08:00
if ( FloatingSplitter - > count ( ) = = 1 )
2017-03-23 17:23:53 +08:00
{
2017-03-24 19:54:43 +08:00
insertWidgetIntoSplitter ( Splitter , FloatingSplitter - > widget ( 0 ) , InsertParam . append ( ) ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( Splitter ) ;
}
2017-03-23 17:23:53 +08:00
else if ( FloatingSplitter - > orientation ( ) = = InsertParam . orientation ( ) )
{
2020-05-17 18:21:52 +08:00
int InsertIndex = InsertParam . append ( ) ? Splitter - > count ( ) : 0 ;
2017-03-23 17:23:53 +08:00
while ( FloatingSplitter - > count ( ) )
{
2020-05-17 18:21:52 +08:00
Splitter - > insertWidget ( InsertIndex + + , FloatingSplitter - > widget ( 0 ) ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( Splitter ) ;
}
}
2017-03-23 17:23:53 +08:00
else
{
2017-03-24 19:54:43 +08:00
insertWidgetIntoSplitter ( Splitter , FloatingSplitter , InsertParam . append ( ) ) ;
2020-08-20 22:36:02 +08:00
}
2017-03-23 17:23:53 +08:00
2017-03-24 19:54:43 +08:00
RootSplitter = Splitter ;
2017-03-23 17:23:53 +08:00
addDockAreasToList ( NewDockAreas ) ;
2018-09-14 19:21:29 +08:00
2018-09-07 17:10:14 +08:00
// If we dropped the floating widget into the main dock container that does
// not contain any dock widgets, then splitter is invisible and we need to
// show it to display the docked widgets
if ( ! Splitter - > isVisible ( ) )
2017-09-06 21:45:22 +08:00
{
2018-09-07 17:10:14 +08:00
Splitter - > show ( ) ;
2020-08-20 22:36:02 +08:00
}
2017-03-28 14:48:44 +08:00
_this - > dumpLayout ( ) ;
2017-03-23 17:23:53 +08:00
}
2019-01-14 20:58:40 +08:00
//============================================================================
void DockContainerWidgetPrivate : : dropIntoCenterOfSection (
CFloatingDockContainer * FloatingWidget , CDockAreaWidget * TargetArea )
{
CDockContainerWidget * FloatingContainer = FloatingWidget - > dockContainer ( ) ;
auto NewDockWidgets = FloatingContainer - > dockWidgets ( ) ;
auto TopLevelDockArea = FloatingContainer - > topLevelDockArea ( ) ;
int NewCurrentIndex = - 1 ;
// If the floating widget contains only one single dock are, then the
// current dock widget of the dock area will also be the future current
// dock widget in the drop area.
if ( TopLevelDockArea )
{
NewCurrentIndex = TopLevelDockArea - > currentIndex ( ) ;
}
for ( int i = 0 ; i < NewDockWidgets . count ( ) ; + + i )
{
CDockWidget * DockWidget = NewDockWidgets [ i ] ;
TargetArea - > insertDockWidget ( i , DockWidget , false ) ;
// If the floating widget contains multiple visible dock areas, then we
// simply pick the first visible open dock widget and make it
// the current one.
if ( NewCurrentIndex < 0 & & ! DockWidget - > isClosed ( ) )
{
NewCurrentIndex = i ;
}
}
TargetArea - > setCurrentIndex ( NewCurrentIndex ) ;
TargetArea - > updateTitleBarVisibility ( ) ;
return ;
}
2017-03-23 17:23:53 +08:00
//============================================================================
void DockContainerWidgetPrivate : : dropIntoSection ( CFloatingDockContainer * FloatingWidget ,
CDockAreaWidget * TargetArea , DockWidgetArea area )
{
2018-12-11 22:19:59 +08:00
// Dropping into center means all dock widgets in the dropped floating
// widget will become tabs of the drop area
if ( CenterDockWidgetArea = = area )
2017-03-23 17:23:53 +08:00
{
2019-01-14 20:58:40 +08:00
dropIntoCenterOfSection ( FloatingWidget , TargetArea ) ;
2017-03-23 17:23:53 +08:00
return ;
}
auto InsertParam = internal : : dockAreaInsertParameters ( area ) ;
auto NewDockAreas = FloatingWidget - > dockContainer ( ) - > findChildren < CDockAreaWidget * > (
QString ( ) , Qt : : FindChildrenRecursively ) ;
QSplitter * TargetAreaSplitter = internal : : findParent < QSplitter * > ( TargetArea ) ;
if ( ! TargetAreaSplitter )
{
2018-12-11 22:19:59 +08:00
QSplitter * Splitter = newSplitter ( InsertParam . orientation ( ) ) ;
2017-03-23 17:23:53 +08:00
Layout - > replaceWidget ( TargetArea , Splitter ) ;
Splitter - > addWidget ( TargetArea ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( Splitter ) ;
TargetAreaSplitter = Splitter ;
2017-03-23 17:23:53 +08:00
}
int AreaIndex = TargetAreaSplitter - > indexOf ( TargetArea ) ;
auto Widget = FloatingWidget - > dockContainer ( ) - > findChild < QWidget * > ( QString ( ) , Qt : : FindDirectChildrenOnly ) ;
2019-01-14 20:58:40 +08:00
auto FloatingSplitter = qobject_cast < QSplitter * > ( Widget ) ;
2017-03-23 17:23:53 +08:00
if ( TargetAreaSplitter - > orientation ( ) = = InsertParam . orientation ( ) )
{
2019-01-14 20:58:40 +08:00
auto Sizes = TargetAreaSplitter - > sizes ( ) ;
int TargetAreaSize = ( InsertParam . orientation ( ) = = Qt : : Horizontal ) ? TargetArea - > width ( ) : TargetArea - > height ( ) ;
bool AdjustSplitterSizes = true ;
2017-03-24 19:54:43 +08:00
if ( ( FloatingSplitter - > orientation ( ) ! = InsertParam . orientation ( ) ) & & FloatingSplitter - > count ( ) > 1 )
2017-03-23 17:23:53 +08:00
{
TargetAreaSplitter - > insertWidget ( AreaIndex + InsertParam . insertOffset ( ) , Widget ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( TargetAreaSplitter ) ;
}
2017-03-23 17:23:53 +08:00
else
{
2019-01-14 20:58:40 +08:00
AdjustSplitterSizes = ( FloatingSplitter - > count ( ) = = 1 ) ;
2017-03-23 17:23:53 +08:00
int InsertIndex = AreaIndex + InsertParam . insertOffset ( ) ;
while ( FloatingSplitter - > count ( ) )
{
TargetAreaSplitter - > insertWidget ( InsertIndex + + , FloatingSplitter - > widget ( 0 ) ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( TargetAreaSplitter ) ;
}
}
2019-01-14 20:58:40 +08:00
if ( AdjustSplitterSizes )
{
int Size = ( TargetAreaSize - TargetAreaSplitter - > handleWidth ( ) ) / 2 ;
Sizes [ AreaIndex ] = Size ;
Sizes . insert ( AreaIndex , Size ) ;
TargetAreaSplitter - > setSizes ( Sizes ) ;
}
2017-03-23 17:23:53 +08:00
}
else
{
2019-01-14 20:58:40 +08:00
QList < int > NewSplitterSizes ;
2018-12-11 22:19:59 +08:00
QSplitter * NewSplitter = newSplitter ( InsertParam . orientation ( ) ) ;
2019-01-14 20:58:40 +08:00
int TargetAreaSize = ( InsertParam . orientation ( ) = = Qt : : Horizontal ) ? TargetArea - > width ( ) : TargetArea - > height ( ) ;
bool AdjustSplitterSizes = true ;
2017-03-24 19:54:43 +08:00
if ( ( FloatingSplitter - > orientation ( ) ! = InsertParam . orientation ( ) ) & & FloatingSplitter - > count ( ) > 1 )
2017-03-23 17:23:53 +08:00
{
NewSplitter - > addWidget ( Widget ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( NewSplitter ) ;
}
2017-03-23 17:23:53 +08:00
else
{
2019-01-14 20:58:40 +08:00
AdjustSplitterSizes = ( FloatingSplitter - > count ( ) = = 1 ) ;
2017-03-23 17:23:53 +08:00
while ( FloatingSplitter - > count ( ) )
{
NewSplitter - > addWidget ( FloatingSplitter - > widget ( 0 ) ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( NewSplitter ) ;
}
}
2017-03-23 17:23:53 +08:00
2019-01-14 20:58:40 +08:00
// Save the sizes before insertion and restore it later to prevent
// shrinking of existing area
auto Sizes = TargetAreaSplitter - > sizes ( ) ;
2018-09-14 21:02:47 +08:00
insertWidgetIntoSplitter ( NewSplitter , TargetArea , ! InsertParam . append ( ) ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( NewSplitter ) ;
if ( AdjustSplitterSizes )
2019-01-14 20:58:40 +08:00
{
int Size = TargetAreaSize / 2 ;
NewSplitter - > setSizes ( { Size , Size } ) ;
}
TargetAreaSplitter - > insertWidget ( AreaIndex , NewSplitter ) ;
TargetAreaSplitter - > setSizes ( Sizes ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( TargetAreaSplitter ) ;
}
2017-03-23 17:23:53 +08:00
addDockAreasToList ( NewDockAreas ) ;
2017-03-28 14:48:44 +08:00
_this - > dumpLayout ( ) ;
2017-03-23 17:23:53 +08:00
}
2019-11-26 21:40:56 +08:00
//============================================================================
void DockContainerWidgetPrivate : : moveIntoCenterOfSection ( QWidget * Widget , CDockAreaWidget * TargetArea )
{
auto DroppedDockWidget = qobject_cast < CDockWidget * > ( Widget ) ;
auto DroppedArea = qobject_cast < CDockAreaWidget * > ( Widget ) ;
if ( DroppedDockWidget )
{
CDockAreaWidget * OldDockArea = DroppedDockWidget - > dockAreaWidget ( ) ;
2020-05-15 18:25:22 +08:00
if ( OldDockArea = = TargetArea )
{
return ;
}
2019-11-26 21:40:56 +08:00
if ( OldDockArea )
{
OldDockArea - > removeDockWidget ( DroppedDockWidget ) ;
}
2019-12-17 20:45:33 +08:00
TargetArea - > insertDockWidget ( 0 , DroppedDockWidget , true ) ;
2019-11-26 21:40:56 +08:00
}
else
{
QList < CDockWidget * > NewDockWidgets = DroppedArea - > dockWidgets ( ) ;
int NewCurrentIndex = DroppedArea - > currentIndex ( ) ;
for ( int i = 0 ; i < NewDockWidgets . count ( ) ; + + i )
{
CDockWidget * DockWidget = NewDockWidgets [ i ] ;
TargetArea - > insertDockWidget ( i , DockWidget , false ) ;
}
TargetArea - > setCurrentIndex ( NewCurrentIndex ) ;
DroppedArea - > dockContainer ( ) - > removeDockArea ( DroppedArea ) ;
DroppedArea - > deleteLater ( ) ;
}
TargetArea - > updateTitleBarVisibility ( ) ;
return ;
}
//============================================================================
2019-11-28 04:43:36 +08:00
void DockContainerWidgetPrivate : : moveToNewSection ( QWidget * Widget , CDockAreaWidget * TargetArea , DockWidgetArea area )
2019-11-26 21:40:56 +08:00
{
// Dropping into center means all dock widgets in the dropped floating
// widget will become tabs of the drop area
if ( CenterDockWidgetArea = = area )
{
2019-11-28 04:43:36 +08:00
moveIntoCenterOfSection ( Widget , TargetArea ) ;
2019-11-26 21:40:56 +08:00
return ;
}
2019-11-27 19:00:04 +08:00
CDockWidget * DroppedDockWidget = qobject_cast < CDockWidget * > ( Widget ) ;
CDockAreaWidget * DroppedDockArea = qobject_cast < CDockAreaWidget * > ( Widget ) ;
CDockAreaWidget * NewDockArea ;
if ( DroppedDockWidget )
{
NewDockArea = new CDockAreaWidget ( DockManager , _this ) ;
CDockAreaWidget * OldDockArea = DroppedDockWidget - > dockAreaWidget ( ) ;
if ( OldDockArea )
{
OldDockArea - > removeDockWidget ( DroppedDockWidget ) ;
}
NewDockArea - > addDockWidget ( DroppedDockWidget ) ;
}
else
{
DroppedDockArea - > dockContainer ( ) - > removeDockArea ( DroppedDockArea ) ;
NewDockArea = DroppedDockArea ;
}
auto InsertParam = internal : : dockAreaInsertParameters ( area ) ;
2019-11-28 04:43:36 +08:00
QSplitter * TargetAreaSplitter = internal : : findParent < QSplitter * > ( TargetArea ) ;
int AreaIndex = TargetAreaSplitter - > indexOf ( TargetArea ) ;
auto Sizes = TargetAreaSplitter - > sizes ( ) ;
2019-11-27 19:00:04 +08:00
if ( TargetAreaSplitter - > orientation ( ) = = InsertParam . orientation ( ) )
{
2019-11-28 04:43:36 +08:00
int TargetAreaSize = ( InsertParam . orientation ( ) = = Qt : : Horizontal ) ? TargetArea - > width ( ) : TargetArea - > height ( ) ;
TargetAreaSplitter - > insertWidget ( AreaIndex + InsertParam . insertOffset ( ) , NewDockArea ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( TargetAreaSplitter ) ;
int Size = ( TargetAreaSize - TargetAreaSplitter - > handleWidth ( ) ) / 2 ;
2019-11-28 04:43:36 +08:00
Sizes [ AreaIndex ] = Size ;
Sizes . insert ( AreaIndex , Size ) ;
2019-11-27 19:00:04 +08:00
}
else
{
2019-11-28 04:43:36 +08:00
auto Sizes = TargetAreaSplitter - > sizes ( ) ;
int TargetAreaSize = ( InsertParam . orientation ( ) = = Qt : : Horizontal ) ? TargetArea - > width ( ) : TargetArea - > height ( ) ;
2019-11-27 19:00:04 +08:00
QSplitter * NewSplitter = newSplitter ( InsertParam . orientation ( ) ) ;
2019-11-28 04:43:36 +08:00
NewSplitter - > addWidget ( TargetArea ) ;
2019-11-27 19:00:04 +08:00
insertWidgetIntoSplitter ( NewSplitter , NewDockArea , InsertParam . append ( ) ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( NewSplitter ) ;
int Size = TargetAreaSize / 2 ;
2019-11-28 04:43:36 +08:00
NewSplitter - > setSizes ( { Size , Size } ) ;
TargetAreaSplitter - > insertWidget ( AreaIndex , NewSplitter ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( TargetAreaSplitter ) ;
}
2019-11-28 04:43:36 +08:00
TargetAreaSplitter - > setSizes ( Sizes ) ;
2019-11-27 19:00:04 +08:00
addDockAreasToList ( { NewDockArea } ) ;
}
2020-08-20 22:36:02 +08:00
//============================================================================
void DockContainerWidgetPrivate : : updateSplitterHandles ( QSplitter * splitter )
{
2020-08-24 16:22:12 +08:00
if ( ! DockManager - > centralWidget ( ) | | ! splitter )
{
return ;
}
for ( int i = 0 ; i < splitter - > count ( ) ; + + i )
2020-08-20 22:36:02 +08:00
{
2020-08-24 16:22:12 +08:00
splitter - > setStretchFactor ( i , widgetResizesWithContainer ( splitter - > widget ( i ) ) ? 1 : 0 ) ;
2020-08-20 22:36:02 +08:00
}
}
//============================================================================
bool DockContainerWidgetPrivate : : widgetResizesWithContainer ( QWidget * widget )
{
2020-08-24 16:22:12 +08:00
if ( ! DockManager - > centralWidget ( ) )
{
2020-08-20 22:36:02 +08:00
return true ;
2020-08-24 16:22:12 +08:00
}
2020-08-20 22:36:02 +08:00
2020-08-24 16:22:12 +08:00
auto Area = qobject_cast < CDockAreaWidget * > ( widget ) ;
2020-08-20 22:36:02 +08:00
if ( Area )
{
return Area - > isCentralWidgetArea ( ) ;
}
2020-08-24 16:22:12 +08:00
auto innerSplitter = qobject_cast < CDockSplitter * > ( widget ) ;
if ( innerSplitter )
2020-08-20 22:36:02 +08:00
{
2020-08-24 16:22:12 +08:00
return innerSplitter - > isResizingWithContainer ( ) ;
2020-08-20 22:36:02 +08:00
}
return false ;
}
2019-11-27 19:00:04 +08:00
//============================================================================
void DockContainerWidgetPrivate : : moveToContainer ( QWidget * Widget , DockWidgetArea area )
{
CDockWidget * DroppedDockWidget = qobject_cast < CDockWidget * > ( Widget ) ;
CDockAreaWidget * DroppedDockArea = qobject_cast < CDockAreaWidget * > ( Widget ) ;
CDockAreaWidget * NewDockArea ;
2019-11-27 22:50:18 +08:00
2019-11-27 19:00:04 +08:00
if ( DroppedDockWidget )
{
NewDockArea = new CDockAreaWidget ( DockManager , _this ) ;
CDockAreaWidget * OldDockArea = DroppedDockWidget - > dockAreaWidget ( ) ;
if ( OldDockArea )
{
OldDockArea - > removeDockWidget ( DroppedDockWidget ) ;
}
NewDockArea - > addDockWidget ( DroppedDockWidget ) ;
}
else
{
2020-03-12 17:23:41 +08:00
// We check, if we insert the dropped widget into the same place that
// it already has and do nothing, if it is the same place. It would
// also work without this check, but it looks nicer with the check
// because there will be no layout updates
auto Splitter = internal : : findParent < CDockSplitter * > ( DroppedDockArea ) ;
auto InsertParam = internal : : dockAreaInsertParameters ( area ) ;
if ( Splitter = = RootSplitter & & InsertParam . orientation ( ) = = Splitter - > orientation ( ) )
{
if ( InsertParam . append ( ) & & Splitter - > lastWidget ( ) = = DroppedDockArea )
{
return ;
}
else if ( ! InsertParam . append ( ) & & Splitter - > firstWidget ( ) = = DroppedDockArea )
{
return ;
}
}
2019-11-27 19:00:04 +08:00
DroppedDockArea - > dockContainer ( ) - > removeDockArea ( DroppedDockArea ) ;
NewDockArea = DroppedDockArea ;
}
addDockArea ( NewDockArea , area ) ;
LastAddedAreaCache [ areaIdToIndex ( area ) ] = NewDockArea ;
2019-11-26 21:40:56 +08:00
}
2017-03-23 17:23:53 +08:00
//============================================================================
void DockContainerWidgetPrivate : : addDockAreasToList ( const QList < CDockAreaWidget * > NewDockAreas )
{
int CountBefore = DockAreas . count ( ) ;
int NewAreaCount = NewDockAreas . count ( ) ;
2018-11-05 16:07:18 +08:00
appendDockAreas ( NewDockAreas ) ;
// If the user dropped a floating widget that contains only one single
// visible dock area, then its title bar button TitleBarButtonUndock is
// likely hidden. We need to ensure, that it is visible
for ( auto DockArea : NewDockAreas )
{
2018-12-02 19:09:31 +08:00
DockArea - > titleBarButton ( TitleBarButtonClose ) - > setVisible ( true ) ;
2022-09-05 17:29:42 +08:00
DockArea - > titleBarButton ( TitleBarButtonAutoHide ) - > setVisible ( true ) ;
2018-11-05 16:07:18 +08:00
}
2017-03-23 17:23:53 +08:00
// We need to ensure, that the dock area title bar is visible. The title bar
// is invisible, if the dock are is a single dock area in a floating widget.
if ( 1 = = CountBefore )
{
2018-11-05 16:07:18 +08:00
DockAreas . at ( 0 ) - > updateTitleBarVisibility ( ) ;
2017-03-23 17:23:53 +08:00
}
if ( 1 = = NewAreaCount )
{
2018-11-05 16:07:18 +08:00
DockAreas . last ( ) - > updateTitleBarVisibility ( ) ;
2017-03-23 17:23:53 +08:00
}
2018-11-05 16:07:18 +08:00
emitDockAreasAdded ( ) ;
}
//============================================================================
void DockContainerWidgetPrivate : : appendDockAreas ( const QList < CDockAreaWidget * > NewDockAreas )
{
DockAreas . append ( NewDockAreas ) ;
for ( auto DockArea : NewDockAreas )
{
2019-01-26 00:28:36 +08:00
QObject : : connect ( DockArea ,
& CDockAreaWidget : : viewToggled ,
_this ,
std : : bind ( & DockContainerWidgetPrivate : : onDockAreaViewToggled , this , std : : placeholders : : _1 ) ) ;
2018-11-05 16:07:18 +08:00
}
2017-03-23 17:23:53 +08:00
}
2017-03-23 22:57:15 +08:00
//============================================================================
2017-12-30 01:18:16 +08:00
void DockContainerWidgetPrivate : : saveChildNodesState ( QXmlStreamWriter & s , QWidget * Widget )
2017-03-23 22:57:15 +08:00
{
2020-02-14 01:56:04 +08:00
QSplitter * Splitter = qobject_cast < QSplitter * > ( Widget ) ;
2017-03-23 22:57:15 +08:00
if ( Splitter )
{
2017-12-30 01:18:16 +08:00
s . writeStartElement ( " Splitter " ) ;
2019-11-25 22:24:44 +08:00
s . writeAttribute ( " Orientation " , ( Splitter - > orientation ( ) = = Qt : : Horizontal ) ? " | " : " - " ) ;
2017-12-30 01:18:16 +08:00
s . writeAttribute ( " Count " , QString : : number ( Splitter - > count ( ) ) ) ;
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " NodeSplitter orient: " < < Splitter - > orientation ( )
< < " WidgetCont: " < < Splitter - > count ( ) ) ;
2017-12-30 01:18:16 +08:00
for ( int i = 0 ; i < Splitter - > count ( ) ; + + i )
{
saveChildNodesState ( s , Splitter - > widget ( i ) ) ;
}
s . writeStartElement ( " Sizes " ) ;
for ( auto Size : Splitter - > sizes ( ) )
{
s . writeCharacters ( QString : : number ( Size ) + " " ) ;
}
s . writeEndElement ( ) ;
s . writeEndElement ( ) ;
2017-03-23 22:57:15 +08:00
}
else
{
2020-02-14 01:56:04 +08:00
CDockAreaWidget * DockArea = qobject_cast < CDockAreaWidget * > ( Widget ) ;
2017-03-23 22:57:15 +08:00
if ( DockArea )
{
2017-12-30 01:18:16 +08:00
DockArea - > saveState ( s ) ;
2017-03-23 22:57:15 +08:00
}
}
}
2022-09-05 17:29:42 +08:00
void DockContainerWidgetPrivate : : saveOverlayWidgetsState ( QXmlStreamWriter & Stream )
{
2022-09-14 17:39:57 +08:00
for ( const auto sideTabBar : SideTabBarWidgets . values ( ) )
2022-09-05 17:29:42 +08:00
{
2022-09-14 17:39:57 +08:00
for ( auto itemIndex = 0 ; itemIndex < sideTabBar - > tabCount ( ) ; itemIndex + + )
{
const auto sideTab = sideTabBar - > tabAt ( itemIndex ) ;
if ( sideTab = = nullptr )
{
continue ;
}
2022-09-05 17:29:42 +08:00
2022-09-14 17:39:57 +08:00
const auto dockArea = sideTab - > dockWidget ( ) - > dockAreaWidget ( ) ;
dockArea - > saveState ( Stream ) ;
}
2022-09-05 17:29:42 +08:00
}
}
2017-03-23 22:57:15 +08:00
//============================================================================
2019-11-29 22:56:57 +08:00
bool DockContainerWidgetPrivate : : restoreSplitter ( CDockingStateReader & s ,
2017-03-27 16:41:27 +08:00
QWidget * & CreatedWidget , bool Testing )
2017-03-23 22:57:15 +08:00
{
2017-12-30 01:18:16 +08:00
bool Ok ;
2018-12-11 22:19:59 +08:00
QString OrientationStr = s . attributes ( ) . value ( " Orientation " ) . toString ( ) ;
2019-11-29 22:56:57 +08:00
// Check if the orientation string is right
if ( ! OrientationStr . startsWith ( " | " ) & & ! OrientationStr . startsWith ( " - " ) )
2018-12-11 22:19:59 +08:00
{
2019-11-29 22:56:57 +08:00
return false ;
2018-12-11 22:19:59 +08:00
}
2019-11-29 22:56:57 +08:00
// The "|" shall indicate a vertical splitter handle which in turn means
// a Horizontal orientation of the splitter layout.
bool HorizontalSplitter = OrientationStr . startsWith ( " | " ) ;
// In version 0 we had a small bug. The "|" indicated a vertical orientation,
// but this is wrong, because only the splitter handle is vertical, the
// layout of the splitter is a horizontal layout. We fix this here
if ( s . fileVersion ( ) = = 0 )
2017-12-30 01:18:16 +08:00
{
2019-11-29 22:56:57 +08:00
HorizontalSplitter = ! HorizontalSplitter ;
2017-12-30 01:18:16 +08:00
}
2019-11-29 22:56:57 +08:00
int Orientation = HorizontalSplitter ? Qt : : Horizontal : Qt : : Vertical ;
2017-12-30 01:18:16 +08:00
int WidgetCount = s . attributes ( ) . value ( " Count " ) . toInt ( & Ok ) ;
if ( ! Ok )
{
return false ;
}
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " Restore NodeSplitter Orientation: " < < Orientation < <
" WidgetCount: " < < WidgetCount ) ;
2017-03-27 16:41:27 +08:00
QSplitter * Splitter = nullptr ;
if ( ! Testing )
{
2019-01-26 00:28:36 +08:00
Splitter = newSplitter ( static_cast < Qt : : Orientation > ( Orientation ) ) ;
2017-03-27 16:41:27 +08:00
}
bool Visible = false ;
2017-12-30 01:18:16 +08:00
QList < int > Sizes ;
while ( s . readNextStartElement ( ) )
2017-03-27 16:41:27 +08:00
{
2017-12-30 01:18:16 +08:00
QWidget * ChildNode = nullptr ;
bool Result = true ;
2021-01-03 01:06:45 +08:00
if ( s . name ( ) = = QLatin1String ( " Splitter " ) )
2017-12-30 01:18:16 +08:00
{
Result = restoreSplitter ( s , ChildNode , Testing ) ;
}
2021-01-03 01:06:45 +08:00
else if ( s . name ( ) = = QLatin1String ( " Area " ) )
2017-12-30 01:18:16 +08:00
{
Result = restoreDockArea ( s , ChildNode , Testing ) ;
}
2021-01-03 01:06:45 +08:00
else if ( s . name ( ) = = QLatin1String ( " Sizes " ) )
2017-12-30 01:18:16 +08:00
{
QString sSizes = s . readElementText ( ) . trimmed ( ) ;
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " Sizes: " < < sSizes ) ;
2017-12-30 01:18:16 +08:00
QTextStream TextStream ( & sSizes ) ;
while ( ! TextStream . atEnd ( ) )
{
int value ;
TextStream > > value ;
Sizes . append ( value ) ;
}
}
else
{
s . skipCurrentElement ( ) ;
}
if ( ! Result )
2017-03-24 17:18:25 +08:00
{
2017-03-27 16:41:27 +08:00
return false ;
}
2017-12-30 01:18:16 +08:00
if ( Testing | | ! ChildNode )
2017-03-27 16:41:27 +08:00
{
continue ;
2017-03-24 17:18:25 +08:00
}
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " ChildNode isVisible " < < ChildNode - > isVisible ( )
< < " isVisibleTo " < < ChildNode - > isVisibleTo ( Splitter ) ) ;
2017-03-27 16:41:27 +08:00
Splitter - > addWidget ( ChildNode ) ;
Visible | = ChildNode - > isVisibleTo ( Splitter ) ;
}
2020-08-20 22:36:02 +08:00
if ( ! Testing )
{
updateSplitterHandles ( Splitter ) ;
}
2017-03-27 16:41:27 +08:00
2017-12-30 01:18:16 +08:00
if ( Sizes . count ( ) ! = WidgetCount )
{
return false ;
}
2017-03-27 16:41:27 +08:00
if ( ! Testing )
{
2017-03-24 23:17:55 +08:00
if ( ! Splitter - > count ( ) )
2017-03-23 22:57:15 +08:00
{
2017-03-24 23:17:55 +08:00
delete Splitter ;
Splitter = nullptr ;
2017-03-23 22:57:15 +08:00
}
else
{
2017-03-24 23:17:55 +08:00
Splitter - > setSizes ( Sizes ) ;
Splitter - > setVisible ( Visible ) ;
2017-03-23 22:57:15 +08:00
}
2017-03-24 23:17:55 +08:00
CreatedWidget = Splitter ;
2017-03-23 22:57:15 +08:00
}
else
{
2017-03-27 16:41:27 +08:00
CreatedWidget = nullptr ;
}
2017-12-30 01:18:16 +08:00
2017-03-27 16:41:27 +08:00
return true ;
}
2017-03-24 23:17:55 +08:00
2022-09-05 17:29:42 +08:00
//============================================================================
2022-09-08 11:30:56 +08:00
bool DockContainerWidgetPrivate : : restoreOverlayDockArea ( CDockingStateReader & s , CDockWidgetSideTab : : SideTabBarArea area , bool Testing )
2022-09-05 17:29:42 +08:00
{
bool Ok ;
# ifdef ADS_DEBUG_PRINT
int Tabs = s . attributes ( ) . value ( " Tabs " ) . toInt ( & Ok ) ;
if ( ! Ok )
{
return false ;
}
# endif
QString CurrentDockWidget = s . attributes ( ) . value ( " Current " ) . toString ( ) ;
ADS_PRINT ( " Restore NodeDockArea Tabs: " < < Tabs < < " Current: "
< < CurrentDockWidget ) ;
2022-09-06 15:35:18 +08:00
if ( ! COverlayDockContainer : : areaExistsInConfig ( area ) )
2022-09-05 17:29:42 +08:00
{
return false ;
}
CDockAreaWidget * DockArea = nullptr ;
if ( ! Testing )
{
const auto dockContainer = new COverlayDockContainer ( DockManager , area , _this ) ;
if ( ! dockContainer - > restoreState ( s , Testing ) )
{
return false ;
}
dockContainer - > hide ( ) ;
DockArea = dockContainer - > dockAreaWidget ( ) ;
2022-09-09 14:43:59 +08:00
DockArea - > updateAutoHideButtonCheckState ( ) ;
DockArea - > updateTitleBarButtonToolTip ( ) ;
2022-09-05 17:29:42 +08:00
}
while ( s . readNextStartElement ( ) )
{
if ( s . name ( ) ! = QLatin1String ( " Widget " ) )
{
continue ;
}
auto ObjectName = s . attributes ( ) . value ( " Name " ) ;
if ( ObjectName . isEmpty ( ) )
{
return false ;
}
2022-09-09 12:18:41 +08:00
bool Closed = s . attributes ( ) . value ( " Closed " ) . toInt ( & Ok ) ;
if ( ! Ok )
{
return false ;
}
2022-09-05 17:29:42 +08:00
s . skipCurrentElement ( ) ;
CDockWidget * DockWidget = DockManager - > findDockWidget ( ObjectName . toString ( ) ) ;
if ( ! DockWidget | | Testing )
{
continue ;
}
ADS_PRINT ( " Dock Widget found - parent " < < DockWidget - > parent ( ) ) ;
// We hide the DockArea here to prevent the short display (the flashing)
// of the dock areas during application startup
DockArea - > hide ( ) ;
2022-09-09 12:18:41 +08:00
DockWidget - > setToggleViewActionChecked ( ! Closed ) ;
DockWidget - > setClosedState ( Closed ) ;
DockWidget - > setProperty ( internal : : ClosedProperty , Closed ) ;
2022-09-05 17:29:42 +08:00
DockWidget - > setProperty ( internal : : DirtyProperty , false ) ;
2022-09-14 17:39:57 +08:00
_this - > sideTabBar ( area ) - > insertSideTab ( - 1 , DockWidget - > sideTabWidget ( ) ) ;
2022-09-05 17:29:42 +08:00
DockArea - > overlayDockContainer ( ) - > addDockWidget ( DockWidget ) ;
2022-09-08 14:04:18 +08:00
DockWidget - > sideTabWidget ( ) - > updateStyle ( ) ; // Needed as the side tab widget get it's left/right property from the overlay dock container which was just added
2022-09-13 13:10:29 +08:00
DockArea - > overlayDockContainer ( ) - > toggleView ( ! Closed ) ;
2022-09-05 17:29:42 +08:00
}
return true ;
}
//============================================================================
bool DockContainerWidgetPrivate : : restoreDockOrOverlayDockArea ( CDockingStateReader & Stream , QWidget * & CreatedWidget ,
bool Testing )
{
bool Ok ;
const auto sideTabAreaValue = Stream . attributes ( ) . value ( " SideTabBarArea " ) ;
if ( ! sideTabAreaValue . isNull ( ) )
{
2022-09-08 11:30:56 +08:00
auto sideTabBarArea = static_cast < CDockWidgetSideTab : : SideTabBarArea > ( sideTabAreaValue . toInt ( & Ok ) ) ;
2022-09-05 17:29:42 +08:00
if ( ! Ok )
{
return false ;
}
2022-09-08 14:13:45 +08:00
return restoreOverlayDockArea ( Stream , sideTabBarArea , Testing ) ;
2022-09-05 17:29:42 +08:00
}
// If there's no SideTabBarArea value in the XML, or the value of SideTabBarArea is none, restore the dock area
return restoreDockArea ( Stream , CreatedWidget , Testing ) ;
}
2017-03-27 16:41:27 +08:00
//============================================================================
2019-11-29 22:56:57 +08:00
bool DockContainerWidgetPrivate : : restoreDockArea ( CDockingStateReader & s ,
2017-03-27 16:41:27 +08:00
QWidget * & CreatedWidget , bool Testing )
{
2017-12-30 01:18:16 +08:00
bool Ok ;
2019-10-01 17:48:53 +08:00
# ifdef ADS_DEBUG_PRINT
2017-12-30 01:18:16 +08:00
int Tabs = s . attributes ( ) . value ( " Tabs " ) . toInt ( & Ok ) ;
if ( ! Ok )
{
return false ;
}
2019-10-01 17:48:53 +08:00
# endif
2018-11-01 15:52:14 +08:00
2018-12-11 22:19:59 +08:00
QString CurrentDockWidget = s . attributes ( ) . value ( " Current " ) . toString ( ) ;
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " Restore NodeDockArea Tabs: " < < Tabs < < " Current: "
< < CurrentDockWidget ) ;
2017-03-27 16:41:27 +08:00
CDockAreaWidget * DockArea = nullptr ;
if ( ! Testing )
{
DockArea = new CDockAreaWidget ( DockManager , _this ) ;
2020-08-18 05:50:37 +08:00
const auto AllowedAreasAttribute = s . attributes ( ) . value ( " AllowedAreas " ) ;
if ( ! AllowedAreasAttribute . isEmpty ( ) )
{
DockArea - > setAllowedAreas ( ( DockWidgetArea ) AllowedAreasAttribute . toInt ( nullptr , 16 ) ) ;
}
2020-08-18 16:48:35 +08:00
const auto FlagsAttribute = s . attributes ( ) . value ( " Flags " ) ;
if ( ! FlagsAttribute . isEmpty ( ) )
{
DockArea - > setDockAreaFlags ( ( CDockAreaWidget : : DockAreaFlags ) FlagsAttribute . toInt ( nullptr , 16 ) ) ;
}
2017-03-27 16:41:27 +08:00
}
2017-12-30 01:18:16 +08:00
while ( s . readNextStartElement ( ) )
2017-03-27 16:41:27 +08:00
{
2021-01-03 01:06:45 +08:00
if ( s . name ( ) ! = QLatin1String ( " Widget " ) )
2017-12-30 01:18:16 +08:00
{
continue ;
}
2018-12-11 22:19:59 +08:00
auto ObjectName = s . attributes ( ) . value ( " Name " ) ;
2017-12-30 01:18:16 +08:00
if ( ObjectName . isEmpty ( ) )
2017-03-23 22:57:15 +08:00
{
2017-03-27 16:41:27 +08:00
return false ;
2017-03-24 23:17:55 +08:00
}
2017-03-24 17:18:25 +08:00
2017-12-30 01:18:16 +08:00
bool Closed = s . attributes ( ) . value ( " Closed " ) . toInt ( & Ok ) ;
if ( ! Ok )
{
return false ;
}
2017-03-27 16:41:27 +08:00
2017-12-30 01:18:16 +08:00
s . skipCurrentElement ( ) ;
CDockWidget * DockWidget = DockManager - > findDockWidget ( ObjectName . toString ( ) ) ;
2017-03-27 16:41:27 +08:00
if ( ! DockWidget | | Testing )
2017-03-24 23:17:55 +08:00
{
2017-03-27 16:41:27 +08:00
continue ;
2017-03-23 22:57:15 +08:00
}
2017-03-27 16:41:27 +08:00
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " Dock Widget found - parent " < < DockWidget - > parent ( ) ) ;
2018-09-07 17:10:14 +08:00
// We hide the DockArea here to prevent the short display (the flashing)
// of the dock areas during application startup
2017-03-29 04:38:47 +08:00
DockArea - > hide ( ) ;
2022-09-05 17:29:42 +08:00
DockArea - > addDockWidget ( DockWidget ) ;
2017-03-29 21:43:18 +08:00
DockWidget - > setToggleViewActionChecked ( ! Closed ) ;
2018-09-26 15:57:36 +08:00
DockWidget - > setClosedState ( Closed ) ;
2019-10-01 17:48:53 +08:00
DockWidget - > setProperty ( internal : : ClosedProperty , Closed ) ;
DockWidget - > setProperty ( internal : : DirtyProperty , false ) ;
2017-03-27 16:41:27 +08:00
}
if ( Testing )
{
return true ;
}
2018-09-14 14:46:10 +08:00
if ( ! DockArea - > dockWidgetsCount ( ) )
2017-03-27 16:41:27 +08:00
{
delete DockArea ;
DockArea = nullptr ;
}
2017-03-29 04:38:47 +08:00
else
{
2018-11-01 15:52:14 +08:00
DockArea - > setProperty ( " currentDockWidget " , CurrentDockWidget ) ;
2018-11-05 16:07:18 +08:00
appendDockAreas ( { DockArea } ) ;
2017-03-29 04:38:47 +08:00
}
2018-02-13 19:00:58 +08:00
2017-03-27 16:41:27 +08:00
CreatedWidget = DockArea ;
return true ;
}
//============================================================================
2019-11-29 22:56:57 +08:00
bool DockContainerWidgetPrivate : : restoreChildNodes ( CDockingStateReader & s ,
2017-03-27 16:41:27 +08:00
QWidget * & CreatedWidget , bool Testing )
{
2017-12-30 01:18:16 +08:00
bool Result = true ;
while ( s . readNextStartElement ( ) )
2017-03-27 16:41:27 +08:00
{
2021-01-03 01:06:45 +08:00
if ( s . name ( ) = = QLatin1String ( " Splitter " ) )
2017-12-30 01:18:16 +08:00
{
Result = restoreSplitter ( s , CreatedWidget , Testing ) ;
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " Splitter " ) ;
2017-12-30 01:18:16 +08:00
}
2021-01-03 01:06:45 +08:00
else if ( s . name ( ) = = QLatin1String ( " Area " ) )
2017-12-30 01:18:16 +08:00
{
2022-09-05 17:29:42 +08:00
Result = restoreDockOrOverlayDockArea ( s , CreatedWidget , Testing ) ;
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " DockAreaWidget " ) ;
2017-12-30 01:18:16 +08:00
}
else
{
s . skipCurrentElement ( ) ;
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " Unknown element " ) ;
2017-12-30 01:18:16 +08:00
}
2017-03-23 22:57:15 +08:00
}
2017-12-30 01:18:16 +08:00
return Result ;
2017-03-23 22:57:15 +08:00
}
2017-03-23 17:23:53 +08:00
//============================================================================
2020-06-14 16:39:07 +08:00
CDockAreaWidget * DockContainerWidgetPrivate : : addDockWidgetToContainer ( DockWidgetArea area ,
2017-03-23 17:23:53 +08:00
CDockWidget * Dockwidget )
{
CDockAreaWidget * NewDockArea = new CDockAreaWidget ( DockManager , _this ) ;
NewDockArea - > addDockWidget ( Dockwidget ) ;
addDockArea ( NewDockArea , area ) ;
2018-11-05 16:07:18 +08:00
NewDockArea - > updateTitleBarVisibility ( ) ;
2018-09-07 17:10:14 +08:00
LastAddedAreaCache [ areaIdToIndex ( area ) ] = NewDockArea ;
2017-03-23 17:23:53 +08:00
return NewDockArea ;
}
//============================================================================
void DockContainerWidgetPrivate : : addDockArea ( CDockAreaWidget * NewDockArea , DockWidgetArea area )
{
auto InsertParam = internal : : dockAreaInsertParameters ( area ) ;
2017-03-24 19:54:43 +08:00
// As long as we have only one dock area in the splitter we can adjust
// its orientation
if ( DockAreas . count ( ) < = 1 )
2017-03-23 17:23:53 +08:00
{
2017-03-24 19:54:43 +08:00
RootSplitter - > setOrientation ( InsertParam . orientation ( ) ) ;
2017-03-23 17:23:53 +08:00
}
2017-03-24 19:54:43 +08:00
QSplitter * Splitter = RootSplitter ;
if ( Splitter - > orientation ( ) = = InsertParam . orientation ( ) )
2017-03-23 17:23:53 +08:00
{
insertWidgetIntoSplitter ( Splitter , NewDockArea , InsertParam . append ( ) ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( Splitter ) ;
if ( Splitter - > isHidden ( ) )
2020-05-07 22:13:59 +08:00
{
Splitter - > show ( ) ;
}
2017-03-23 17:23:53 +08:00
}
else
{
2018-12-11 22:19:59 +08:00
QSplitter * NewSplitter = newSplitter ( InsertParam . orientation ( ) ) ;
2017-03-24 19:54:43 +08:00
if ( InsertParam . append ( ) )
2017-03-23 17:23:53 +08:00
{
2017-03-24 19:54:43 +08:00
QLayoutItem * li = Layout - > replaceWidget ( Splitter , NewSplitter ) ;
NewSplitter - > addWidget ( Splitter ) ;
NewSplitter - > addWidget ( NewDockArea ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( NewSplitter ) ;
delete li ;
2017-03-23 17:23:53 +08:00
}
else
{
2017-03-24 19:54:43 +08:00
NewSplitter - > addWidget ( NewDockArea ) ;
QLayoutItem * li = Layout - > replaceWidget ( Splitter , NewSplitter ) ;
NewSplitter - > addWidget ( Splitter ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( NewSplitter ) ;
delete li ;
2017-03-23 17:23:53 +08:00
}
2017-03-24 19:54:43 +08:00
RootSplitter = NewSplitter ;
2017-03-23 17:23:53 +08:00
}
2019-11-27 19:00:04 +08:00
addDockAreasToList ( { NewDockArea } ) ;
2017-03-23 17:23:53 +08:00
}
2017-03-28 14:48:44 +08:00
//============================================================================
void DockContainerWidgetPrivate : : dumpRecursive ( int level , QWidget * widget )
{
2017-03-28 16:57:03 +08:00
# if defined(QT_DEBUG)
2020-02-14 01:56:04 +08:00
QSplitter * Splitter = qobject_cast < QSplitter * > ( widget ) ;
2017-03-28 14:48:44 +08:00
QByteArray buf ;
buf . fill ( ' ' , level * 4 ) ;
if ( Splitter )
{
2019-07-21 15:53:24 +08:00
# ifdef ADS_DEBUG_PRINT
2017-09-06 21:45:22 +08:00
qDebug ( " %sSplitter %s v: %s c: %s " ,
( const char * ) buf ,
2018-12-03 19:52:57 +08:00
( Splitter - > orientation ( ) = = Qt : : Vertical ) ? " -- " : " | " ,
Splitter - > isHidden ( ) ? " " : " v " ,
2017-09-06 21:45:22 +08:00
QString : : number ( Splitter - > count ( ) ) . toStdString ( ) . c_str ( ) ) ;
2019-07-21 15:53:24 +08:00
std : : cout < < ( const char * ) buf < < " Splitter "
< < ( ( Splitter - > orientation ( ) = = Qt : : Vertical ) ? " -- " : " | " ) < < " "
< < ( Splitter - > isHidden ( ) ? " " : " v " ) < < " "
< < QString : : number ( Splitter - > count ( ) ) . toStdString ( ) < < std : : endl ;
# endif
2017-03-28 14:48:44 +08:00
for ( int i = 0 ; i < Splitter - > count ( ) ; + + i )
{
dumpRecursive ( level + 1 , Splitter - > widget ( i ) ) ;
}
}
else
{
2020-02-14 01:56:04 +08:00
CDockAreaWidget * DockArea = qobject_cast < CDockAreaWidget * > ( widget ) ;
2017-03-28 14:48:44 +08:00
if ( ! DockArea )
{
return ;
}
2019-07-21 15:53:24 +08:00
# ifdef ADS_DEBUG_PRINT
2017-03-28 18:01:27 +08:00
qDebug ( " %sDockArea " , ( const char * ) buf ) ;
2018-12-03 19:52:57 +08:00
std : : cout < < ( const char * ) buf
< < ( DockArea - > isHidden ( ) ? " " : " v " )
< < ( DockArea - > openDockWidgetsCount ( ) > 0 ? " " : " c " )
2020-09-21 15:39:42 +08:00
< < " DockArea " < < " [hs: " < < DockArea - > sizePolicy ( ) . horizontalStretch ( ) < < " , vs: " < < DockArea - > sizePolicy ( ) . verticalStretch ( ) < < " ] " < < std : : endl ;
2018-12-03 19:52:57 +08:00
buf . fill ( ' ' , ( level + 1 ) * 4 ) ;
for ( int i = 0 ; i < DockArea - > dockWidgetsCount ( ) ; + + i )
{
std : : cout < < ( const char * ) buf < < ( i = = DockArea - > currentIndex ( ) ? " * " : " " ) ;
CDockWidget * DockWidget = DockArea - > dockWidget ( i ) ;
std : : cout < < ( DockWidget - > isHidden ( ) ? " " : " v " ) ;
std : : cout < < ( DockWidget - > isClosed ( ) ? " c " : " " ) < < " " ;
std : : cout < < DockWidget - > windowTitle ( ) . toStdString ( ) < < std : : endl ;
2019-07-21 15:53:24 +08:00
}
# endif
2017-03-28 14:48:44 +08:00
}
2017-03-29 18:18:49 +08:00
# else
Q_UNUSED ( level ) ;
Q_UNUSED ( widget ) ;
2017-03-28 16:57:03 +08:00
# endif
2017-03-28 14:48:44 +08:00
}
2017-03-23 17:23:53 +08:00
//============================================================================
2020-06-14 16:39:07 +08:00
CDockAreaWidget * DockContainerWidgetPrivate : : addDockWidgetToDockArea ( DockWidgetArea area ,
2017-03-23 17:23:53 +08:00
CDockWidget * Dockwidget , CDockAreaWidget * TargetDockArea )
{
if ( CenterDockWidgetArea = = area )
{
TargetDockArea - > addDockWidget ( Dockwidget ) ;
2019-09-30 23:33:40 +08:00
TargetDockArea - > updateTitleBarVisibility ( ) ;
2017-03-23 17:23:53 +08:00
return TargetDockArea ;
}
CDockAreaWidget * NewDockArea = new CDockAreaWidget ( DockManager , _this ) ;
NewDockArea - > addDockWidget ( Dockwidget ) ;
auto InsertParam = internal : : dockAreaInsertParameters ( area ) ;
2017-03-24 19:54:43 +08:00
QSplitter * TargetAreaSplitter = internal : : findParent < QSplitter * > ( TargetDockArea ) ;
int index = TargetAreaSplitter - > indexOf ( TargetDockArea ) ;
if ( TargetAreaSplitter - > orientation ( ) = = InsertParam . orientation ( ) )
2017-03-23 17:23:53 +08:00
{
2020-06-13 22:59:13 +08:00
ADS_PRINT ( " TargetAreaSplitter->orientation() == InsertParam.orientation() " ) ;
2017-03-24 19:54:43 +08:00
TargetAreaSplitter - > insertWidget ( index + InsertParam . insertOffset ( ) , NewDockArea ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( TargetAreaSplitter ) ;
// do nothing, if flag is not enabled
2020-06-14 16:39:07 +08:00
if ( CDockManager : : testConfigFlag ( CDockManager : : EqualSplitOnInsertion ) )
{
adjustSplitterSizesOnInsertion ( TargetAreaSplitter ) ;
}
2017-03-23 17:23:53 +08:00
}
else
{
2020-06-13 22:59:13 +08:00
ADS_PRINT ( " TargetAreaSplitter->orientation() != InsertParam.orientation() " ) ;
auto TargetAreaSizes = TargetAreaSplitter - > sizes ( ) ;
2018-12-11 22:19:59 +08:00
QSplitter * NewSplitter = newSplitter ( InsertParam . orientation ( ) ) ;
2017-03-24 19:54:43 +08:00
NewSplitter - > addWidget ( TargetDockArea ) ;
2020-06-13 22:59:13 +08:00
2017-03-24 19:54:43 +08:00
insertWidgetIntoSplitter ( NewSplitter , NewDockArea , InsertParam . append ( ) ) ;
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( NewSplitter ) ;
TargetAreaSplitter - > insertWidget ( index , NewSplitter ) ;
updateSplitterHandles ( TargetAreaSplitter ) ;
if ( CDockManager : : testConfigFlag ( CDockManager : : EqualSplitOnInsertion ) )
{
2020-06-14 16:39:07 +08:00
TargetAreaSplitter - > setSizes ( TargetAreaSizes ) ;
adjustSplitterSizesOnInsertion ( NewSplitter ) ;
}
2017-03-23 17:23:53 +08:00
}
2020-11-21 22:08:30 +08:00
addDockAreasToList ( { NewDockArea } ) ;
2017-03-23 17:23:53 +08:00
return NewDockArea ;
}
//============================================================================
CDockContainerWidget : : CDockContainerWidget ( CDockManager * DockManager , QWidget * parent ) :
QFrame ( parent ) ,
d ( new DockContainerWidgetPrivate ( this ) )
{
d - > DockManager = DockManager ;
2018-12-11 22:19:59 +08:00
d - > isFloating = floatingWidget ( ) ! = nullptr ;
2017-03-23 17:23:53 +08:00
d - > Layout = new QGridLayout ( ) ;
2021-12-20 14:46:26 +08:00
d - > Layout - > setContentsMargins ( 0 , 0 , 0 , 0 ) ;
2017-03-23 17:23:53 +08:00
d - > Layout - > setSpacing ( 0 ) ;
2022-09-05 17:29:42 +08:00
d - > Layout - > setColumnStretch ( 1 , 1 ) ;
2022-09-13 10:42:58 +08:00
d - > Layout - > setRowStretch ( 0 , 1 ) ;
2017-03-23 17:23:53 +08:00
setLayout ( d - > Layout ) ;
2017-03-24 19:54:43 +08:00
2018-12-11 22:19:59 +08:00
// The function d->newSplitter() accesses the config flags from dock
// manager which in turn requires a properly constructed dock manager.
// If this dock container is the dock manager, then it is not properly
// constructed yet because this base class constructor is called before
// the constructor of the DockManager private class
if ( DockManager ! = this )
{
d - > DockManager - > registerDockContainer ( this ) ;
createRootSplitter ( ) ;
2022-09-05 17:29:42 +08:00
createSideTabBarWidgets ( ) ;
2018-12-11 22:19:59 +08:00
}
2017-03-23 17:23:53 +08:00
}
//============================================================================
CDockContainerWidget : : ~ CDockContainerWidget ( )
{
if ( d - > DockManager )
{
d - > DockManager - > removeDockContainer ( this ) ;
}
2022-09-06 17:42:26 +08:00
auto OverlayWidgets = d - > OverlayWidgets ;
for ( auto OverlayWidget : OverlayWidgets )
{
delete OverlayWidget ;
}
2017-03-23 17:23:53 +08:00
delete d ;
}
//============================================================================
CDockAreaWidget * CDockContainerWidget : : addDockWidget ( DockWidgetArea area , CDockWidget * Dockwidget ,
CDockAreaWidget * DockAreaWidget )
{
CDockAreaWidget * OldDockArea = Dockwidget - > dockAreaWidget ( ) ;
if ( OldDockArea )
{
OldDockArea - > removeDockWidget ( Dockwidget ) ;
}
Dockwidget - > setDockManager ( d - > DockManager ) ;
if ( DockAreaWidget )
{
2020-06-14 16:39:07 +08:00
return d - > addDockWidgetToDockArea ( area , Dockwidget , DockAreaWidget ) ;
2017-03-23 17:23:53 +08:00
}
else
{
2020-06-14 16:39:07 +08:00
return d - > addDockWidgetToContainer ( area , Dockwidget ) ;
2017-03-23 17:23:53 +08:00
}
}
2022-09-06 15:35:18 +08:00
//============================================================================
2022-09-14 15:52:34 +08:00
COverlayDockContainer * CDockContainerWidget : : createAndInitializeDockWidgetOverlayContainer ( CDockWidgetSideTab : : SideTabBarArea area , CDockWidget * DockWidget , CDockWidget : : eOverlayInsertOrder insertOrder )
2022-09-05 17:29:42 +08:00
{
if ( d - > DockManager ! = DockWidget - > dockManager ( ) )
{
DockWidget - > setDockManager ( d - > DockManager ) ; // Overlay Dock Container needs a valid dock manager
}
2022-09-06 15:35:18 +08:00
if ( ! COverlayDockContainer : : areaExistsInConfig ( area ) )
{
2022-09-07 16:56:17 +08:00
Q_ASSERT_X ( false , " CDockContainerWidget::createAndInitializeDockWidgetOverlayContainer " ,
" Requested area does not exist in config " ) ;
2022-09-06 15:35:18 +08:00
return nullptr ;
}
2022-09-19 14:19:31 +08:00
DockWidget - > sideTabWidget ( ) - > updateOrientationAndSpacing ( area ) ;
2022-09-14 15:52:34 +08:00
sideTabBar ( area ) - > insertSideTab ( insertOrder = = CDockWidget : : First ? 0 : - 1 , DockWidget - > sideTabWidget ( ) ) ;
2022-09-06 15:35:18 +08:00
DockWidget - > sideTabWidget ( ) - > show ( ) ;
2022-09-06 17:42:26 +08:00
const auto dockContainer = new COverlayDockContainer ( DockWidget , area , this ) ;
2022-09-05 17:29:42 +08:00
dockContainer - > hide ( ) ;
2022-09-15 13:04:49 +08:00
d - > DockManager - > dockFocusController ( ) - > clearDockWidgetFocus ( DockWidget ) ;
2022-09-06 15:35:18 +08:00
return dockContainer ;
2022-09-05 17:29:42 +08:00
}
//============================================================================
2022-09-08 11:30:56 +08:00
CDockWidgetSideTab : : SideTabBarArea CDockContainerWidget : : getDockAreaPosition ( CDockAreaWidget * DockAreaWidget )
2022-09-05 17:29:42 +08:00
{
2022-09-13 10:42:58 +08:00
// Handle bottom case
// It's bottom if the width is wider than the height, and if it's below 50% of the window
const auto dockWidgetFrameGeometry = DockAreaWidget - > frameGeometry ( ) ;
2022-09-05 17:29:42 +08:00
const auto splitterCenter = rootSplitter ( ) - > mapToGlobal ( rootSplitter ( ) - > frameGeometry ( ) . center ( ) ) ;
2022-09-13 10:42:58 +08:00
const auto a = dockWidgetFrameGeometry . width ( ) ;
const auto b = dockWidgetFrameGeometry . height ( ) ;
const auto c = DockAreaWidget - > mapToGlobal ( dockWidgetFrameGeometry . topLeft ( ) ) . y ( ) ;
const auto d = splitterCenter . y ( ) ;
const auto e = CDockManager : : testConfigFlag ( CDockManager : : DockContainerHasBottomSideBar ) ;
if ( dockWidgetFrameGeometry . width ( ) > dockWidgetFrameGeometry . height ( )
& & DockAreaWidget - > mapToGlobal ( dockWidgetFrameGeometry . topLeft ( ) ) . y ( ) > splitterCenter . y ( )
& & CDockManager : : testConfigFlag ( CDockManager : : DockContainerHasBottomSideBar ) )
{
return CDockWidgetSideTab : : Bottom ;
}
// Then handle left and right
const auto dockWidgetCenter = DockAreaWidget - > mapToGlobal ( dockWidgetFrameGeometry . center ( ) ) ;
2022-09-15 12:51:59 +08:00
const auto calculatedPosition = dockWidgetCenter . x ( ) < = splitterCenter . x ( ) ? CDockWidgetSideTab : : LeftTop : CDockWidgetSideTab : : RightTop ;
if ( calculatedPosition = = CDockWidgetSideTab : : RightTop )
2022-09-05 17:29:42 +08:00
{
if ( CDockManager : : testConfigFlag ( CDockManager : : DockContainerHasRightSideBar ) )
{
2022-09-15 12:51:59 +08:00
return CDockWidgetSideTab : : RightTop ;
2022-09-05 17:29:42 +08:00
}
2022-09-13 10:42:58 +08:00
if ( CDockManager : : testConfigFlag ( CDockManager : : DockContainerHasLeftSideBar ) )
{
2022-09-15 12:51:59 +08:00
return CDockWidgetSideTab : : LeftTop ;
2022-09-13 10:42:58 +08:00
}
return CDockWidgetSideTab : : Bottom ;
2022-09-05 17:29:42 +08:00
}
2022-09-15 12:51:59 +08:00
if ( calculatedPosition = = CDockWidgetSideTab : : LeftTop )
2022-09-05 17:29:42 +08:00
{
if ( CDockManager : : testConfigFlag ( CDockManager : : DockContainerHasLeftSideBar ) )
{
2022-09-15 16:02:55 +08:00
// todo: cleanup - revert
return CDockWidgetSideTab : : LeftBottom ;
2022-09-05 17:29:42 +08:00
}
2022-09-13 10:42:58 +08:00
if ( CDockManager : : testConfigFlag ( CDockManager : : DockContainerHasRightSideBar ) )
{
2022-09-15 12:51:59 +08:00
return CDockWidgetSideTab : : RightTop ;
2022-09-13 10:42:58 +08:00
}
return CDockWidgetSideTab : : Bottom ;
2022-09-05 17:29:42 +08:00
}
2022-09-13 10:42:58 +08:00
Q_ASSERT_X ( false , " CDockContainerWidget::getDockAreaPosition " , " Unhandled branch. All positions should be accounted for. " ) ;
2022-09-15 12:51:59 +08:00
return CDockWidgetSideTab : : LeftTop ;
2022-09-05 17:29:42 +08:00
}
2019-05-15 20:47:58 +08:00
//============================================================================
void CDockContainerWidget : : removeDockWidget ( CDockWidget * Dockwidget )
{
CDockAreaWidget * Area = Dockwidget - > dockAreaWidget ( ) ;
if ( Area )
{
Area - > removeDockWidget ( Dockwidget ) ;
}
}
2017-03-23 17:23:53 +08:00
//============================================================================
unsigned int CDockContainerWidget : : zOrderIndex ( ) const
{
return d - > zOrderIndex ;
}
//============================================================================
bool CDockContainerWidget : : isInFrontOf ( CDockContainerWidget * Other ) const
{
return this - > zOrderIndex ( ) > Other - > zOrderIndex ( ) ;
}
//============================================================================
bool CDockContainerWidget : : event ( QEvent * e )
{
bool Result = QWidget : : event ( e ) ;
if ( e - > type ( ) = = QEvent : : WindowActivate )
{
d - > zOrderIndex = + + zOrderCounter ;
}
else if ( e - > type ( ) = = QEvent : : Show & & ! d - > zOrderIndex )
{
d - > zOrderIndex = + + zOrderCounter ;
}
return Result ;
}
2022-09-06 17:42:26 +08:00
//============================================================================
void CDockContainerWidget : : deleteOverlayWidgets ( )
{
for ( auto OverlayWidget : d - > OverlayWidgets )
{
OverlayWidget - > cleanupAndDelete ( ) ;
}
d - > OverlayWidgets . clear ( ) ;
}
//============================================================================
QList < COverlayDockContainer * > CDockContainerWidget : : overlayWidgets ( ) const
{
return d - > OverlayWidgets ;
}
2017-03-23 17:23:53 +08:00
//============================================================================
void CDockContainerWidget : : addDockArea ( CDockAreaWidget * DockAreaWidget ,
DockWidgetArea area )
{
CDockContainerWidget * Container = DockAreaWidget - > dockContainer ( ) ;
if ( Container & & Container ! = this )
{
Container - > removeDockArea ( DockAreaWidget ) ;
}
2017-03-29 18:18:49 +08:00
d - > addDockArea ( DockAreaWidget , area ) ;
2017-03-23 17:23:53 +08:00
}
//============================================================================
void CDockContainerWidget : : removeDockArea ( CDockAreaWidget * area )
{
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " CDockContainerWidget::removeDockArea " ) ;
2018-11-05 16:07:18 +08:00
area - > disconnect ( this ) ;
2017-03-23 17:23:53 +08:00
d - > DockAreas . removeAll ( area ) ;
2017-09-06 21:45:22 +08:00
CDockSplitter * Splitter = internal : : findParent < CDockSplitter * > ( area ) ;
2018-12-03 19:52:57 +08:00
// Remove are from parent splitter and recursively hide tree of parent
// splitters if it has no visible content
2019-01-26 00:28:36 +08:00
area - > setParent ( nullptr ) ;
2018-12-03 19:52:57 +08:00
internal : : hideEmptyParentSplitters ( Splitter ) ;
2017-09-06 21:45:22 +08:00
2019-05-15 21:20:08 +08:00
// Remove this area from cached areas
2020-06-29 03:07:17 +08:00
auto p = std : : find ( std : : begin ( d - > LastAddedAreaCache ) , std : : end ( d - > LastAddedAreaCache ) , area ) ;
if ( p ! = std : : end ( d - > LastAddedAreaCache ) ) {
* p = nullptr ;
2019-05-15 21:20:08 +08:00
}
2022-09-05 17:29:42 +08:00
if ( area - > isOverlayed ( ) )
{
// Removing an area from an overlay widget implies deleting the whole overlay widget
// So cleanup will be done when the overlay widget is deleted
// Note: there is no parent splitter
CDockWidget * TopLevelWidget = topLevelDockWidget ( ) ;
// Updated the title bar visibility of the dock widget if there is only
// one single visible dock widget
CDockWidget : : emitTopLevelEventForWidget ( TopLevelWidget , true ) ;
dumpLayout ( ) ;
d - > emitDockAreasRemoved ( ) ;
area - > setOverlayDockContainer ( nullptr ) ;
2022-09-09 14:43:59 +08:00
area - > updateAutoHideButtonCheckState ( ) ;
area - > updateTitleBarButtonToolTip ( ) ;
2022-09-05 17:29:42 +08:00
return ;
}
2017-09-06 21:45:22 +08:00
// If splitter has more than 1 widgets, we are finished and can leave
if ( Splitter - > count ( ) > 1 )
2017-03-23 17:23:53 +08:00
{
2017-09-06 21:45:22 +08:00
goto emitAndExit ;
}
// If this is the RootSplitter we need to remove empty splitters to
// avoid too many empty splitters
if ( Splitter = = d - > RootSplitter )
{
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " Removed from RootSplitter " ) ;
2017-09-06 21:45:22 +08:00
// If splitter is empty, we are finished
if ( ! Splitter - > count ( ) )
{
Splitter - > hide ( ) ;
goto emitAndExit ;
}
QWidget * widget = Splitter - > widget ( 0 ) ;
2020-02-14 01:56:04 +08:00
QSplitter * ChildSplitter = qobject_cast < QSplitter * > ( widget ) ;
2017-09-06 21:45:22 +08:00
// If the one and only content widget of the splitter is not a splitter
// then we are finished
if ( ! ChildSplitter )
{
goto emitAndExit ;
}
// We replace the superfluous RootSplitter with the ChildSplitter
2019-01-26 00:28:36 +08:00
ChildSplitter - > setParent ( nullptr ) ;
2017-09-06 21:45:22 +08:00
QLayoutItem * li = d - > Layout - > replaceWidget ( Splitter , ChildSplitter ) ;
d - > RootSplitter = ChildSplitter ;
delete li ;
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " RootSplitter replaced by child splitter " ) ;
2017-09-06 21:45:22 +08:00
}
else if ( Splitter - > count ( ) = = 1 )
{
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " Replacing splitter with content " ) ;
2019-01-14 20:58:40 +08:00
QSplitter * ParentSplitter = internal : : findParent < QSplitter * > ( Splitter ) ;
auto Sizes = ParentSplitter - > sizes ( ) ;
2017-09-06 21:45:22 +08:00
QWidget * widget = Splitter - > widget ( 0 ) ;
widget - > setParent ( this ) ;
internal : : replaceSplitterWidget ( ParentSplitter , Splitter , widget ) ;
2019-01-14 20:58:40 +08:00
ParentSplitter - > setSizes ( Sizes ) ;
2017-03-23 17:23:53 +08:00
}
delete Splitter ;
2020-08-20 22:36:02 +08:00
Splitter = nullptr ;
2017-09-06 21:45:22 +08:00
emitAndExit :
2020-08-20 22:36:02 +08:00
updateSplitterHandles ( Splitter ) ;
CDockWidget * TopLevelWidget = topLevelDockWidget ( ) ;
2018-09-26 15:57:36 +08:00
// Updated the title bar visibility of the dock widget if there is only
2018-09-14 19:21:29 +08:00
// one single visible dock widget
2018-09-26 15:57:36 +08:00
CDockWidget : : emitTopLevelEventForWidget ( TopLevelWidget , true ) ;
2017-03-28 14:48:44 +08:00
dumpLayout ( ) ;
2018-11-05 16:07:18 +08:00
d - > emitDockAreasRemoved ( ) ;
2017-03-23 17:23:53 +08:00
}
//============================================================================
CDockAreaWidget * CDockContainerWidget : : dockAreaAt ( const QPoint & GlobalPos ) const
{
for ( const auto & DockArea : d - > DockAreas )
{
2017-09-06 21:45:22 +08:00
if ( DockArea - > isVisible ( ) & & DockArea - > rect ( ) . contains ( DockArea - > mapFromGlobal ( GlobalPos ) ) )
2017-03-23 17:23:53 +08:00
{
return DockArea ;
}
}
2019-01-26 00:28:36 +08:00
return nullptr ;
2017-03-23 17:23:53 +08:00
}
//============================================================================
CDockAreaWidget * CDockContainerWidget : : dockArea ( int Index ) const
{
2019-01-26 00:28:36 +08:00
return ( Index < dockAreaCount ( ) ) ? d - > DockAreas [ Index ] : nullptr ;
2017-03-23 17:23:53 +08:00
}
//============================================================================
bool CDockContainerWidget : : isFloating ( ) const
{
return d - > isFloating ;
}
//============================================================================
int CDockContainerWidget : : dockAreaCount ( ) const
{
return d - > DockAreas . count ( ) ;
}
2017-03-29 21:43:18 +08:00
//============================================================================
int CDockContainerWidget : : visibleDockAreaCount ( ) const
{
int Result = 0 ;
for ( auto DockArea : d - > DockAreas )
{
2018-10-31 06:45:59 +08:00
Result + = DockArea - > isHidden ( ) ? 0 : 1 ;
2017-03-29 21:43:18 +08:00
}
return Result ;
2018-11-01 14:53:54 +08:00
// TODO Cache or precalculate this to speed it up because it is used during
// movement of floating widget
//return d->visibleDockAreaCount();
2017-03-29 21:43:18 +08:00
}
2017-03-23 17:23:53 +08:00
//============================================================================
void CDockContainerWidget : : dropFloatingWidget ( CFloatingDockContainer * FloatingWidget ,
const QPoint & TargetPos )
{
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " CDockContainerWidget::dropFloatingWidget " ) ;
2019-11-27 22:50:18 +08:00
CDockWidget * SingleDroppedDockWidget = FloatingWidget - > topLevelDockWidget ( ) ;
CDockWidget * SingleDockWidget = topLevelDockWidget ( ) ;
2017-03-23 17:23:53 +08:00
CDockAreaWidget * DockArea = dockAreaAt ( TargetPos ) ;
auto dropArea = InvalidDockWidgetArea ;
2017-09-01 22:14:43 +08:00
auto ContainerDropArea = d - > DockManager - > containerOverlay ( ) - > dropAreaUnderCursor ( ) ;
2019-12-10 19:47:55 +08:00
bool Dropped = false ;
2018-11-02 16:19:53 +08:00
2022-09-06 17:42:26 +08:00
auto overlayWidgets = FloatingWidget - > dockContainer ( ) - > overlayWidgets ( ) ;
for ( const auto overlayWidget : overlayWidgets )
{
2022-09-14 15:52:34 +08:00
createAndInitializeDockWidgetOverlayContainer ( overlayWidget - > sideTabBarArea ( ) , overlayWidget - > dockWidget ( ) , overlayWidget - > dockWidget ( ) - > overlayInsertOrder ( ) ) ;
2022-09-06 17:42:26 +08:00
}
2017-03-23 17:23:53 +08:00
if ( DockArea )
{
auto dropOverlay = d - > DockManager - > dockAreaOverlay ( ) ;
2020-02-02 22:56:31 +08:00
dropOverlay - > setAllowedAreas ( DockArea - > allowedAreas ( ) ) ;
2017-03-23 17:23:53 +08:00
dropArea = dropOverlay - > showOverlay ( DockArea ) ;
2017-09-06 21:45:22 +08:00
if ( ContainerDropArea ! = InvalidDockWidgetArea & &
ContainerDropArea ! = dropArea )
2017-09-01 22:14:43 +08:00
{
dropArea = InvalidDockWidgetArea ;
}
2017-03-23 17:23:53 +08:00
if ( dropArea ! = InvalidDockWidgetArea )
{
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " Dock Area Drop Content: " < < dropArea ) ;
2017-03-23 17:23:53 +08:00
d - > dropIntoSection ( FloatingWidget , DockArea , dropArea ) ;
2019-12-10 19:47:55 +08:00
Dropped = true ;
2017-03-23 17:23:53 +08:00
}
}
// mouse is over container
if ( InvalidDockWidgetArea = = dropArea )
{
2017-09-01 22:14:43 +08:00
dropArea = ContainerDropArea ;
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " Container Drop Content: " < < dropArea ) ;
2017-03-23 17:23:53 +08:00
if ( dropArea ! = InvalidDockWidgetArea )
{
d - > dropIntoContainer ( FloatingWidget , dropArea ) ;
2019-12-10 19:47:55 +08:00
Dropped = true ;
2017-03-23 17:23:53 +08:00
}
}
2018-09-07 17:10:14 +08:00
2019-12-10 19:47:55 +08:00
if ( Dropped )
2021-10-01 21:30:33 +08:00
{
// Fix https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/351
FloatingWidget - > hideAndDeleteLater ( ) ;
2019-12-10 19:47:55 +08:00
// If we dropped a floating widget with only one single dock widget, then we
// drop a top level widget that changes from floating to docked now
CDockWidget : : emitTopLevelEventForWidget ( SingleDroppedDockWidget , false ) ;
2019-11-27 22:50:18 +08:00
2019-12-10 19:47:55 +08:00
// If there was a top level widget before the drop, then it is not top
// level widget anymore
CDockWidget : : emitTopLevelEventForWidget ( SingleDockWidget , false ) ;
}
2020-05-20 20:20:27 +08:00
window ( ) - > activateWindow ( ) ;
2020-05-23 20:45:49 +08:00
if ( SingleDroppedDockWidget )
{
2020-06-05 13:27:44 +08:00
d - > DockManager - > notifyWidgetOrAreaRelocation ( SingleDroppedDockWidget ) ;
2020-05-23 20:45:49 +08:00
}
2020-06-05 02:40:23 +08:00
d - > DockManager - > notifyFloatingWidgetDrop ( FloatingWidget ) ;
2017-03-23 17:23:53 +08:00
}
2020-03-12 17:23:41 +08:00
//============================================================================
void CDockContainerWidget : : dropWidget ( QWidget * Widget , DockWidgetArea DropArea , CDockAreaWidget * TargetAreaWidget )
{
CDockWidget * SingleDockWidget = topLevelDockWidget ( ) ;
if ( TargetAreaWidget )
2019-11-26 21:40:56 +08:00
{
2020-03-12 17:23:41 +08:00
d - > moveToNewSection ( Widget , TargetAreaWidget , DropArea ) ;
}
else
{
d - > moveToContainer ( Widget , DropArea ) ;
2019-11-26 21:40:56 +08:00
}
// If there was a top level widget before the drop, then it is not top
// level widget anymore
2019-11-27 22:50:18 +08:00
CDockWidget : : emitTopLevelEventForWidget ( SingleDockWidget , false ) ;
2020-05-17 14:51:58 +08:00
2020-05-20 20:20:27 +08:00
window ( ) - > activateWindow ( ) ;
2020-06-05 13:27:44 +08:00
d - > DockManager - > notifyWidgetOrAreaRelocation ( Widget ) ;
2019-11-26 21:40:56 +08:00
}
2017-03-23 17:23:53 +08:00
//============================================================================
QList < CDockAreaWidget * > CDockContainerWidget : : openedDockAreas ( ) const
{
QList < CDockAreaWidget * > Result ;
for ( auto DockArea : d - > DockAreas )
{
2018-10-31 06:45:59 +08:00
if ( ! DockArea - > isHidden ( ) )
2017-03-23 17:23:53 +08:00
{
Result . append ( DockArea ) ;
}
}
return Result ;
}
2022-03-25 20:31:40 +08:00
//============================================================================
QList < CDockWidget * > CDockContainerWidget : : openedDockWidgets ( ) const
{
QList < CDockWidget * > DockWidgetList ;
for ( auto DockArea : d - > DockAreas )
{
if ( ! DockArea - > isHidden ( ) )
{
DockWidgetList . append ( DockArea - > openedDockWidgets ( ) ) ;
}
}
return DockWidgetList ;
}
2021-12-06 16:42:12 +08:00
//============================================================================
bool CDockContainerWidget : : hasOpenDockAreas ( ) const
{
for ( auto DockArea : d - > DockAreas )
{
if ( ! DockArea - > isHidden ( ) )
{
return true ;
}
}
return false ;
}
2017-03-23 22:57:15 +08:00
//============================================================================
2017-12-30 01:18:16 +08:00
void CDockContainerWidget : : saveState ( QXmlStreamWriter & s ) const
2017-03-23 22:57:15 +08:00
{
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " CDockContainerWidget::saveState isFloating "
< < isFloating ( ) ) ;
2017-12-30 01:18:16 +08:00
2018-12-11 22:19:59 +08:00
s . writeStartElement ( " Container " ) ;
2017-12-30 01:18:16 +08:00
s . writeAttribute ( " Floating " , QString : : number ( isFloating ( ) ? 1 : 0 ) ) ;
2017-03-23 22:57:15 +08:00
if ( isFloating ( ) )
{
2018-11-02 16:19:53 +08:00
CFloatingDockContainer * FloatingWidget = floatingWidget ( ) ;
2017-12-30 01:18:16 +08:00
QByteArray Geometry = FloatingWidget - > saveGeometry ( ) ;
2019-01-14 15:59:37 +08:00
# if QT_VERSION < 0x050900
s . writeTextElement ( " Geometry " , qByteArrayToHex ( Geometry , ' ' ) ) ;
# else
2017-12-30 01:18:16 +08:00
s . writeTextElement ( " Geometry " , Geometry . toHex ( ' ' ) ) ;
2019-01-14 15:59:37 +08:00
# endif
2017-03-23 22:57:15 +08:00
}
2017-12-30 01:18:16 +08:00
d - > saveChildNodesState ( s , d - > RootSplitter ) ;
2022-09-05 17:29:42 +08:00
d - > saveOverlayWidgetsState ( s ) ;
2017-12-30 01:18:16 +08:00
s . writeEndElement ( ) ;
2017-03-23 22:57:15 +08:00
}
//============================================================================
2019-11-29 22:56:57 +08:00
bool CDockContainerWidget : : restoreState ( CDockingStateReader & s , bool Testing )
2017-03-23 22:57:15 +08:00
{
2017-12-30 01:18:16 +08:00
bool IsFloating = s . attributes ( ) . value ( " Floating " ) . toInt ( ) ;
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " Restore CDockContainerWidget Floating " < < IsFloating ) ;
2017-03-24 17:18:25 +08:00
2017-12-30 01:18:16 +08:00
QWidget * NewRootSplitter { } ;
2017-03-27 16:41:27 +08:00
if ( ! Testing )
{
2018-11-01 14:53:54 +08:00
d - > VisibleDockAreaCount = - 1 ; // invalidate the dock area count
2017-03-27 16:41:27 +08:00
d - > DockAreas . clear ( ) ;
2019-05-15 23:13:55 +08:00
std : : fill ( std : : begin ( d - > LastAddedAreaCache ) , std : : end ( d - > LastAddedAreaCache ) , nullptr ) ;
2017-03-27 16:41:27 +08:00
}
if ( IsFloating )
2017-03-23 22:57:15 +08:00
{
2019-07-21 15:53:24 +08:00
ADS_PRINT ( " Restore floating widget " ) ;
2021-01-03 01:06:45 +08:00
if ( ! s . readNextStartElement ( ) | | s . name ( ) ! = QLatin1String ( " Geometry " ) )
2017-12-30 01:18:16 +08:00
{
return false ;
}
2019-11-29 22:56:57 +08:00
QByteArray GeometryString = s . readElementText ( CDockingStateReader : : ErrorOnUnexpectedElement ) . toLocal8Bit ( ) ;
2017-12-30 01:18:16 +08:00
QByteArray Geometry = QByteArray : : fromHex ( GeometryString ) ;
if ( Geometry . isEmpty ( ) )
{
return false ;
}
2017-03-27 16:41:27 +08:00
if ( ! Testing )
{
2018-11-02 16:19:53 +08:00
CFloatingDockContainer * FloatingWidget = floatingWidget ( ) ;
2021-12-04 00:01:16 +08:00
if ( FloatingWidget )
{
FloatingWidget - > restoreGeometry ( Geometry ) ;
}
2017-03-27 16:41:27 +08:00
}
}
2017-12-30 01:18:16 +08:00
if ( ! d - > restoreChildNodes ( s , NewRootSplitter , Testing ) )
2017-03-27 16:41:27 +08:00
{
return false ;
2017-03-24 23:17:55 +08:00
}
2017-03-27 16:41:27 +08:00
if ( Testing )
{
return true ;
}
2017-03-23 22:57:15 +08:00
2017-03-27 19:18:16 +08:00
// If the root splitter is empty, rostoreChildNodes returns a 0 pointer
// and we need to create a new empty root splitter
if ( ! NewRootSplitter )
{
2018-12-11 22:19:59 +08:00
NewRootSplitter = d - > newSplitter ( Qt : : Horizontal ) ;
2017-03-27 19:18:16 +08:00
}
2017-03-24 23:17:55 +08:00
d - > Layout - > replaceWidget ( d - > RootSplitter , NewRootSplitter ) ;
QSplitter * OldRoot = d - > RootSplitter ;
2020-02-14 01:56:04 +08:00
d - > RootSplitter = qobject_cast < QSplitter * > ( NewRootSplitter ) ;
2017-03-27 16:41:27 +08:00
OldRoot - > deleteLater ( ) ;
2017-03-27 19:18:16 +08:00
2017-03-23 22:57:15 +08:00
return true ;
}
2017-03-28 14:48:44 +08:00
//============================================================================
QSplitter * CDockContainerWidget : : rootSplitter ( ) const
{
return d - > RootSplitter ;
}
2018-12-11 22:19:59 +08:00
//============================================================================
void CDockContainerWidget : : createRootSplitter ( )
{
if ( d - > RootSplitter )
{
return ;
}
d - > RootSplitter = d - > newSplitter ( Qt : : Horizontal ) ;
2022-09-05 17:29:42 +08:00
d - > Layout - > addWidget ( d - > RootSplitter , 0 , 1 ) ; // Add it to the center - the 0 and 2 indexes are used for the SideTabBar widgets
}
//============================================================================
void CDockContainerWidget : : createSideTabBarWidgets ( )
{
if ( CDockManager : : testConfigFlag ( CDockManager : : DockContainerHasLeftSideBar ) )
{
2022-09-15 12:51:59 +08:00
auto leftLayout = new QVBoxLayout ( ) ;
d - > SideTabBarWidgets [ CDockWidgetSideTab : : LeftTop ] = new CSideTabBar ( this , Qt : : Vertical ) ;
leftLayout - > addWidget ( d - > SideTabBarWidgets [ CDockWidgetSideTab : : LeftTop ] ) ;
leftLayout - > addStretch ( 1 ) ;
d - > SideTabBarWidgets [ CDockWidgetSideTab : : LeftBottom ] = new CSideTabBar ( this , Qt : : Vertical ) ;
leftLayout - > addWidget ( d - > SideTabBarWidgets [ CDockWidgetSideTab : : LeftBottom ] ) ;
d - > Layout - > addLayout ( leftLayout , 0 , 0 ) ;
2022-09-05 17:29:42 +08:00
}
if ( CDockManager : : testConfigFlag ( CDockManager : : DockContainerHasRightSideBar ) )
{
2022-09-15 12:51:59 +08:00
auto rightLayout = new QVBoxLayout ( ) ;
d - > SideTabBarWidgets [ CDockWidgetSideTab : : RightTop ] = new CSideTabBar ( this , Qt : : Vertical ) ;
rightLayout - > addWidget ( d - > SideTabBarWidgets [ CDockWidgetSideTab : : RightTop ] ) ;
rightLayout - > addStretch ( 1 ) ;
d - > SideTabBarWidgets [ CDockWidgetSideTab : : RightBottom ] = new CSideTabBar ( this , Qt : : Vertical ) ;
rightLayout - > addWidget ( d - > SideTabBarWidgets [ CDockWidgetSideTab : : RightBottom ] ) ;
d - > Layout - > addLayout ( rightLayout , 0 , 2 ) ;
2022-09-05 17:29:42 +08:00
}
2022-09-13 10:42:58 +08:00
if ( CDockManager : : testConfigFlag ( CDockManager : : DockContainerHasBottomSideBar ) )
{
d - > SideTabBarWidgets [ CDockWidgetSideTab : : Bottom ] = new CSideTabBar ( this , Qt : : Horizontal ) ;
d - > Layout - > addWidget ( d - > SideTabBarWidgets [ CDockWidgetSideTab : : Bottom ] , 1 , 1 ) ;
}
2018-12-11 22:19:59 +08:00
}
2017-03-28 14:48:44 +08:00
//============================================================================
void CDockContainerWidget : : dumpLayout ( )
{
2018-09-14 14:46:10 +08:00
# if (ADS_DEBUG_LEVEL > 0)
2017-09-06 21:45:22 +08:00
qDebug ( " \n \n Dumping layout -------------------------- " ) ;
2018-12-03 19:52:57 +08:00
std : : cout < < " \n \n Dumping layout -------------------------- " < < std : : endl ;
2017-03-28 14:48:44 +08:00
d - > dumpRecursive ( 0 , d - > RootSplitter ) ;
2017-09-06 21:45:22 +08:00
qDebug ( " -------------------------- \n \n " ) ;
2018-12-03 19:52:57 +08:00
std : : cout < < " -------------------------- \n \n " < < std : : endl ;
2018-09-14 14:46:10 +08:00
# endif
2017-03-28 14:48:44 +08:00
}
2018-09-07 17:10:14 +08:00
//============================================================================
CDockAreaWidget * CDockContainerWidget : : lastAddedDockAreaWidget ( DockWidgetArea area ) const
{
return d - > LastAddedAreaCache [ areaIdToIndex ( area ) ] ;
}
2018-09-14 19:21:29 +08:00
//============================================================================
2018-09-26 15:57:36 +08:00
bool CDockContainerWidget : : hasTopLevelDockWidget ( ) const
2018-09-14 19:21:29 +08:00
{
auto DockAreas = openedDockAreas ( ) ;
if ( DockAreas . count ( ) ! = 1 )
{
return false ;
}
return DockAreas [ 0 ] - > openDockWidgetsCount ( ) = = 1 ;
}
//============================================================================
2018-09-26 15:57:36 +08:00
CDockWidget * CDockContainerWidget : : topLevelDockWidget ( ) const
2018-09-14 19:21:29 +08:00
{
2018-11-02 16:19:53 +08:00
auto TopLevelDockArea = topLevelDockArea ( ) ;
if ( ! TopLevelDockArea )
2018-09-14 19:21:29 +08:00
{
return nullptr ;
}
2018-11-02 16:19:53 +08:00
auto DockWidgets = TopLevelDockArea - > openedDockWidgets ( ) ;
2018-09-14 19:21:29 +08:00
if ( DockWidgets . count ( ) ! = 1 )
{
return nullptr ;
}
return DockWidgets [ 0 ] ;
2018-11-02 16:19:53 +08:00
}
//============================================================================
CDockAreaWidget * CDockContainerWidget : : topLevelDockArea ( ) const
{
auto DockAreas = openedDockAreas ( ) ;
if ( DockAreas . count ( ) ! = 1 )
{
return nullptr ;
}
return DockAreas [ 0 ] ;
2018-09-14 19:21:29 +08:00
}
2018-10-11 14:54:32 +08:00
//============================================================================
QList < CDockWidget * > CDockContainerWidget : : dockWidgets ( ) const
{
QList < CDockWidget * > Result ;
for ( const auto DockArea : d - > DockAreas )
{
Result . append ( DockArea - > dockWidgets ( ) ) ;
}
return Result ;
}
2020-08-20 22:36:02 +08:00
//============================================================================
void CDockContainerWidget : : updateSplitterHandles ( QSplitter * splitter )
{
d - > updateSplitterHandles ( splitter ) ;
}
2022-09-06 17:42:26 +08:00
//============================================================================
void CDockContainerWidget : : registerOverlayWidget ( COverlayDockContainer * OverlayWidget )
{
d - > OverlayWidgets . append ( OverlayWidget ) ;
Q_EMIT overlayWidgetCreated ( OverlayWidget ) ;
ADS_PRINT ( " d->OverlayWidgets.count() " < < d - > OverlayWidgets . count ( ) ) ;
}
//============================================================================
void CDockContainerWidget : : removeOverlayWidget ( COverlayDockContainer * OverlayWidget )
{
d - > OverlayWidgets . removeAll ( OverlayWidget ) ;
}
2020-08-20 22:36:02 +08:00
2018-10-12 21:18:05 +08:00
//============================================================================
CDockWidget : : DockWidgetFeatures CDockContainerWidget : : features ( ) const
{
2018-10-15 14:29:30 +08:00
CDockWidget : : DockWidgetFeatures Features ( CDockWidget : : AllDockWidgetFeatures ) ;
2018-10-12 21:18:05 +08:00
for ( const auto DockArea : d - > DockAreas )
{
Features & = DockArea - > features ( ) ;
}
return Features ;
}
2018-11-02 16:19:53 +08:00
//============================================================================
CFloatingDockContainer * CDockContainerWidget : : floatingWidget ( ) const
{
return internal : : findParent < CFloatingDockContainer * > ( this ) ;
}
2018-12-20 22:29:38 +08:00
//============================================================================
void CDockContainerWidget : : closeOtherAreas ( CDockAreaWidget * KeepOpenArea )
{
for ( const auto DockArea : d - > DockAreas )
{
2020-01-06 18:42:36 +08:00
if ( DockArea = = KeepOpenArea )
2018-12-20 22:29:38 +08:00
{
2020-01-06 18:42:36 +08:00
continue ;
}
if ( ! DockArea - > features ( BitwiseAnd ) . testFlag ( CDockWidget : : DockWidgetClosable ) )
{
continue ;
2018-12-20 22:29:38 +08:00
}
2020-01-06 18:42:36 +08:00
// We do not close areas with widgets with custom close handling
if ( DockArea - > features ( BitwiseOr ) . testFlag ( CDockWidget : : CustomCloseHandling ) )
{
continue ;
}
DockArea - > closeArea ( ) ;
2018-12-20 22:29:38 +08:00
}
}
2022-09-05 17:29:42 +08:00
//============================================================================
2022-09-08 11:30:56 +08:00
CSideTabBar * CDockContainerWidget : : sideTabBar ( CDockWidgetSideTab : : SideTabBarArea area ) const
2022-09-05 17:29:42 +08:00
{
return d - > SideTabBarWidgets [ area ] ;
}
2017-03-23 17:23:53 +08:00
} // namespace ads
//---------------------------------------------------------------------------
// EOF DockContainerWidget.cpp