From 1a11e5ddcdf82f62eab98b40fc7a2cf2a27ef3a8 Mon Sep 17 00:00:00 2001 From: hulswit Date: Thu, 20 Aug 2020 16:36:02 +0200 Subject: [PATCH] Central Widget concept added Adde option to set a dock widget as central widget. It influences resizing behavior of the splitters. The central widget will be stretched with the main window and remaing dock widgets and threir respective areas will be resized only vertically if docked left or right and horizontaly if docked top or bottom --- examples/CMakeLists.txt | 3 +- examples/centralWidget/CMakeLists.txt | 26 +++ examples/centralWidget/centralWidget.pro | 56 ++++++ examples/centralWidget/digitalclock.cpp | 27 +++ examples/centralWidget/digitalclock.h | 17 ++ examples/centralWidget/main.cpp | 11 ++ examples/centralWidget/mainwindow.cpp | 237 +++++++++++++++++++++++ examples/centralWidget/mainwindow.h | 32 +++ examples/centralWidget/mainwindow.ui | 30 +++ examples/examples.pro | 1 + src/DockAreaWidget.cpp | 11 ++ src/DockAreaWidget.h | 7 +- src/DockContainerWidget.cpp | 132 ++++++++++--- src/DockContainerWidget.h | 6 + src/DockManager.cpp | 18 ++ src/DockManager.h | 14 +- src/DockSplitter.cpp | 14 ++ src/DockSplitter.h | 5 + src/DockWidget.cpp | 6 + src/DockWidget.h | 5 + 20 files changed, 629 insertions(+), 29 deletions(-) create mode 100644 examples/centralWidget/CMakeLists.txt create mode 100644 examples/centralWidget/centralWidget.pro create mode 100644 examples/centralWidget/digitalclock.cpp create mode 100644 examples/centralWidget/digitalclock.h create mode 100644 examples/centralWidget/main.cpp create mode 100644 examples/centralWidget/mainwindow.cpp create mode 100644 examples/centralWidget/mainwindow.h create mode 100644 examples/centralWidget/mainwindow.ui diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d1a4516..3b24252 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -2,4 +2,5 @@ cmake_minimum_required(VERSION 3.5) project(QtADSExamples LANGUAGES CXX VERSION ${VERSION_SHORT}) add_subdirectory(simple) add_subdirectory(sidebar) -add_subdirectory(deleteonclose) \ No newline at end of file +add_subdirectory(deleteonclose) +add_subdirectory(centralWidget) \ No newline at end of file diff --git a/examples/centralWidget/CMakeLists.txt b/examples/centralWidget/CMakeLists.txt new file mode 100644 index 0000000..4cc7de9 --- /dev/null +++ b/examples/centralWidget/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.5) +project(ads_example_centralwidget VERSION ${VERSION_SHORT}) +find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +add_executable(CentralWidgetExample WIN32 + main.cpp + mainwindow.cpp + mainwindow.ui + digitalclock.cpp +) +target_include_directories(CentralWidgetExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src") +target_link_libraries(CentralWidgetExample PRIVATE qtadvanceddocking) +target_link_libraries(CentralWidgetExample PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets) +set_target_properties(CentralWidgetExample PROPERTIES + AUTOMOC ON + AUTORCC ON + AUTOUIC ON + CXX_STANDARD 14 + CXX_STANDARD_REQUIRED ON + CXX_EXTENSIONS OFF + VERSION ${VERSION_SHORT} + EXPORT_NAME "Qt Advanced Docking System Central Widget Example" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/bin" +) diff --git a/examples/centralWidget/centralWidget.pro b/examples/centralWidget/centralWidget.pro new file mode 100644 index 0000000..f39896d --- /dev/null +++ b/examples/centralWidget/centralWidget.pro @@ -0,0 +1,56 @@ +ADS_OUT_ROOT = $${OUT_PWD}/../.. + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = CentralWidgetExample +DESTDIR = $${ADS_OUT_ROOT}/lib +TEMPLATE = app +CONFIG += c++14 +CONFIG += debug_and_release + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + digitalclock.cpp \ + main.cpp \ + mainwindow.cpp + +HEADERS += \ + digitalclock.h \ + mainwindow.h + +FORMS += \ + mainwindow.ui + +LIBS += -L$${ADS_OUT_ROOT}/lib + +# Dependency: AdvancedDockingSystem (shared) +CONFIG(debug, debug|release){ + win32 { + LIBS += -lqtadvanceddockingd + } + else:mac { + LIBS += -lqtadvanceddocking_debug + } + else { + LIBS += -lqtadvanceddocking + } +} +else{ + LIBS += -lqtadvanceddocking +} + +INCLUDEPATH += ../../src +DEPENDPATH += ../../src + diff --git a/examples/centralWidget/digitalclock.cpp b/examples/centralWidget/digitalclock.cpp new file mode 100644 index 0000000..2752d6b --- /dev/null +++ b/examples/centralWidget/digitalclock.cpp @@ -0,0 +1,27 @@ +#include "digitalclock.h" + +#include +#include + +CDigitalClock::CDigitalClock(QWidget *parent) + : QLCDNumber(parent) +{ + setDigitCount(8); + setSegmentStyle(Filled); + + QTimer *timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, &CDigitalClock::showTime); + timer->start(1000); + + showTime(); + + setWindowTitle(tr("Digital Clock")); + resize(150, 60); +} + +void CDigitalClock::showTime() +{ + QTime time = QTime::currentTime(); + QString text = time.toString("hh:mm:ss"); + display(text); +} diff --git a/examples/centralWidget/digitalclock.h b/examples/centralWidget/digitalclock.h new file mode 100644 index 0000000..4c155d3 --- /dev/null +++ b/examples/centralWidget/digitalclock.h @@ -0,0 +1,17 @@ +#ifndef DIGITALCLOCK_H +#define DIGITALCLOCK_H + +#include + +class CDigitalClock : public QLCDNumber +{ + Q_OBJECT + +public: + CDigitalClock(QWidget *parent = nullptr); + +private slots: + void showTime(); +}; + +#endif // DIGITALCLOCK_H diff --git a/examples/centralWidget/main.cpp b/examples/centralWidget/main.cpp new file mode 100644 index 0000000..3f073f3 --- /dev/null +++ b/examples/centralWidget/main.cpp @@ -0,0 +1,11 @@ +#include "mainwindow.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + CMainWindow w; + w.show(); + return a.exec(); +} diff --git a/examples/centralWidget/mainwindow.cpp b/examples/centralWidget/mainwindow.cpp new file mode 100644 index 0000000..cc4a8d9 --- /dev/null +++ b/examples/centralWidget/mainwindow.cpp @@ -0,0 +1,237 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "digitalclock.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DockAreaWidget.h" +#include "DockAreaTitleBar.h" +#include "DockAreaTabBar.h" +#include "FloatingDockContainer.h" +#include "DockComponentsFactory.h" + +using namespace ads; + +const QString CMainWindow::kTableTopLayout = "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "344 272 " + "" + "" + "" + "" + "" + "" + "" + "258 758 258 " + "" + "" + "" + "" + "52 621 52 " + "" + "" + ""; + +const QString CMainWindow::kTableBottomLayout = "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "258 758 258 " + "" + "" + "" + "" + "" + "" + "" + "621 52 52 " + "" + "" + ""; + +CMainWindow::CMainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CMainWindow) +{ + ui->setupUi(this); + CDockManager::setConfigFlag(CDockManager::OpaqueSplitterResize, true); + CDockManager::setConfigFlag(CDockManager::XmlCompressionEnabled, false); + DockManager = new CDockManager(this); + QCalendarWidget* calendar = new QCalendarWidget(); + CDockWidget* CentralDockWidget = new CDockWidget("CentralWidget"); + CentralDockWidget->setWidget(calendar); + CentralDockWidget->setFeature(CDockWidget::DockWidgetClosable, false); + CentralDockWidget->setFeature(CDockWidget::DockWidgetMovable, false); + CentralDockWidget->setFeature(CDockWidget::DockWidgetFloatable, false); + auto* CentralDockArea = DockManager->setCentralWidget(CentralDockWidget); + CentralDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas); + CentralDockArea->setDockAreaFlag(CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); + + QTreeView* fileTree = new QTreeView(); + fileTree->setFrameShape(QFrame::NoFrame); + QFileSystemModel* fileModel = new QFileSystemModel(fileTree); + fileModel->setRootPath(QDir::currentPath()); + fileTree->setModel(fileModel); + CDockWidget* DataDockWidget = new CDockWidget("File system"); + DataDockWidget->setWidget(fileTree); + DataDockWidget->resize(150, 250); + DataDockWidget->setMinimumSize(100, 250); + auto* fileArea = DockManager->addDockWidget(DockWidgetArea::LeftDockWidgetArea, DataDockWidget, CentralDockArea); + + QTableWidget* table = new QTableWidget(); + table->setColumnCount(3); + table->setRowCount(10); + CDockWidget* TableDockWidget = new CDockWidget("Table"); + TableDockWidget->setWidget(table); + TableDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); + TableDockWidget->resize(250, 150); + TableDockWidget->setMinimumSize(200,150); + DockManager->addDockWidget(DockWidgetArea::BottomDockWidgetArea, TableDockWidget, fileArea); + + QTableWidget* propertiesTable = new QTableWidget(); + table->setColumnCount(3); + table->setRowCount(10); + CDockWidget* PropertiesDockWidget = new CDockWidget("Properties"); + PropertiesDockWidget->setWidget(propertiesTable); + PropertiesDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); + PropertiesDockWidget->resize(250, 150); + PropertiesDockWidget->setMinimumSize(200,150); + DockManager->addDockWidget(DockWidgetArea::RightDockWidgetArea, PropertiesDockWidget, CentralDockArea); + + QWidget* timeLineWidget = new QWidget(); + QHBoxLayout* timelineLayout = new QHBoxLayout(timeLineWidget); + QRadioButton* radioDockTop = new QRadioButton("Top", timeLineWidget); + QRadioButton* radioDockBottom = new QRadioButton("Bottom", timeLineWidget); + radioDockTop->setChecked(true); + timelineLayout->addWidget(new QLabel("Fixed height Dock widget.")); + timelineLayout->addStretch(1); + timelineLayout->addWidget(new QLabel("Apply predefined perspective: ", this)); + timelineLayout->addWidget(radioDockTop); + timelineLayout->addWidget(radioDockBottom); + TimelineDockWidget = new CDockWidget("Timeline"); + TimelineDockWidget->setWidget(timeLineWidget); +// TimelineDockWidget->setResizeMode(CDockWidget::eResizeMode::ResizeHorizontal); + TimelineDockWidget->setFeature(CDockWidget::DockWidgetClosable, false); + TimelineDockWidget->setFeature(CDockWidget::DockWidgetMovable, false); + TimelineDockWidget->setFeature(CDockWidget::DockWidgetFloatable, false); + TimelineDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); + TimelineDockWidget->setMinimumSize(QSize(50, 50)); + TimelineDockWidget->setFixedHeight(50); + auto *TimelineDockArea = DockManager->addDockWidget(DockWidgetArea::TopDockWidgetArea, TimelineDockWidget); + TimelineDockArea->setDockAreaFlag(CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); + TimelineDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas); + connect(radioDockTop, &QRadioButton::toggled, [this](bool checked){ + bool ok = true; + if(!checked) + { + ok = DockManager->restoreState(kTableBottomLayout.toUtf8()); + } + else + { + ok = DockManager->restoreState(kTableTopLayout.toUtf8()); + } + if(!ok) + { + QMessageBox msgBox; + msgBox.setText("Failed to apply perspective!"); + msgBox.exec(); + } + }); + + QWidget* statusWidget = new QWidget(); + QHBoxLayout* statusLayout = new QHBoxLayout(statusWidget); + statusLayout->setSpacing(10); + CDigitalClock* clock = new CDigitalClock(statusWidget); + statusLayout->addWidget(new QLabel("Status Bar")); + QPushButton* OpenPerspectiveButton = new QPushButton("Open Perspective", statusWidget); + connect(OpenPerspectiveButton, &QPushButton::clicked, [this](){ + QString PerspectiveName = QFileDialog::getOpenFileName(this, "Open Perspective", "", "Perspective files (*.xml)"); + if (PerspectiveName.isEmpty()) + { + return; + } + + QFile stateFile(PerspectiveName); + stateFile.open(QIODevice::ReadOnly); + QByteArray state = stateFile.readAll(); + stateFile.close(); + if(!DockManager->restoreState(state)) + { + QMessageBox msgBox; + msgBox.setText("Failed to apply perspective " + stateFile.fileName()); + msgBox.exec(); + } + }); + QPushButton* SavePerspectiveButton = new QPushButton("Create Perspective", statusWidget); + connect(SavePerspectiveButton, &QPushButton::clicked, [this](){ + QString PerspectiveName = QInputDialog::getText(this, "Save Perspective", "Enter unique name:"); + if (PerspectiveName.isEmpty()) + { + return; + } + + QByteArray state = DockManager->saveState(); + QFile stateFile(PerspectiveName + ".xml"); + stateFile.open(QIODevice::WriteOnly); + stateFile.write(state); + stateFile.close(); + }); + statusLayout->addWidget(OpenPerspectiveButton); + statusLayout->addWidget(SavePerspectiveButton); + statusLayout->addStretch(1); + statusLayout->addWidget(clock); + CDockWidget* StatusDockWidget = new CDockWidget("Status"); + StatusDockWidget->setWidget(statusWidget); +// StatusDockWidget->setResizeMode(CDockWidget::eResizeMode::ResizeHorizontal); + StatusDockWidget->setFeature(CDockWidget::DockWidgetClosable, false); + StatusDockWidget->setFeature(CDockWidget::DockWidgetMovable, false); + StatusDockWidget->setFeature(CDockWidget::DockWidgetFloatable, false); + StatusDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); + StatusDockWidget->setMinimumSize(QSize(50, 50)); + StatusDockWidget->setFixedHeight(50); + StatusDockArea = DockManager->addDockWidget(DockWidgetArea::BottomDockWidgetArea, StatusDockWidget); + StatusDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas); + StatusDockArea->setDockAreaFlag(CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); +} + +CMainWindow::~CMainWindow() +{ + delete ui; +} + diff --git a/examples/centralWidget/mainwindow.h b/examples/centralWidget/mainwindow.h new file mode 100644 index 0000000..cbd05b0 --- /dev/null +++ b/examples/centralWidget/mainwindow.h @@ -0,0 +1,32 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +#include "DockManager.h" +#include "DockAreaWidget.h" +#include "DockWidget.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CMainWindow; } +QT_END_NAMESPACE + +class CMainWindow : public QMainWindow +{ + Q_OBJECT + +public: + CMainWindow(QWidget *parent = nullptr); + ~CMainWindow(); + +private: + static const QString kTableTopLayout; + static const QString kTableBottomLayout; + + Ui::CMainWindow *ui; + + ads::CDockManager* DockManager; + ads::CDockAreaWidget* StatusDockArea; + ads::CDockWidget* TimelineDockWidget; +}; +#endif // MAINWINDOW_H diff --git a/examples/centralWidget/mainwindow.ui b/examples/centralWidget/mainwindow.ui new file mode 100644 index 0000000..73ae7b1 --- /dev/null +++ b/examples/centralWidget/mainwindow.ui @@ -0,0 +1,30 @@ + + + CMainWindow + + + + 0 + 0 + 1284 + 757 + + + + MainWindow + + + + + + 0 + 0 + 1284 + 21 + + + + + + + diff --git a/examples/examples.pro b/examples/examples.pro index 68419c9..de8cf7f 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -1,6 +1,7 @@ TEMPLATE = subdirs SUBDIRS = \ + centralwidget \ simple \ sidebar \ deleteonclose diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 092f997..6d3b8c9 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -440,6 +440,7 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget, DockWidget->toggleViewInternal(true); } d->updateTitleBarButtonStates(); + updateTitleBarVisibility(); } @@ -946,6 +947,16 @@ CDockAreaTitleBar* CDockAreaWidget::titleBar() const } +//============================================================================ +bool CDockAreaWidget::isCentralWidgetArea() +{ + if(dockWidgetsCount()!=1) + return false; + + return dockManager()->centralWidget()==dockWidgets()[0]; +} + + //============================================================================ QSize CDockAreaWidget::minimumSizeHint() const { diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index 337eac2..0c4653a 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -153,7 +153,7 @@ public: }; Q_DECLARE_FLAGS(DockAreaFlags, eDockAreaFlag) - /** + /** * Default Constructor */ CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent); @@ -306,6 +306,11 @@ public: */ void setDockAreaFlag(eDockAreaFlag Flag, bool On); + /** + * Returns true if the area contains the central widget of it's manager. + */ + bool isCentralWidgetArea(); + public slots: /** * This activates the tab for the given tab index. diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 4d716c6..56aef07 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -322,6 +322,17 @@ public: Splitter->setSizes(SplitterSizes); } + /** + * This finction forces the dock container widget to update handles of splitters + * based on resize modes of dock widgets aontained in the container. + */ + void updateSplitterHandles(QSplitter* splitter); + + /** + * This function returns true if the area is not allowed to resize in the direstion + * of the splitter. Otherwise returns true. + */ + bool widgetResizesWithContainer(QWidget* widget); // private slots: ------------------------------------------------------------ void onDockAreaViewToggled(bool Visible) @@ -421,7 +432,8 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter); NewSplitter->addWidget(Splitter); - Splitter = NewSplitter; + updateSplitterHandles(NewSplitter); + Splitter = NewSplitter; delete li; } @@ -430,19 +442,21 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float if (FloatingSplitter->count() == 1) { insertWidgetIntoSplitter(Splitter, FloatingSplitter->widget(0), InsertParam.append()); - } + updateSplitterHandles(Splitter); + } else if (FloatingSplitter->orientation() == InsertParam.orientation()) { int InsertIndex = InsertParam.append() ? Splitter->count() : 0; while (FloatingSplitter->count()) { Splitter->insertWidget(InsertIndex++, FloatingSplitter->widget(0)); - } - } + updateSplitterHandles(Splitter); + } + } else { insertWidgetIntoSplitter(Splitter, FloatingSplitter, InsertParam.append()); - } + } RootSplitter = Splitter; addDockAreasToList(NewDockAreas); @@ -453,7 +467,7 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float if (!Splitter->isVisible()) { Splitter->show(); - } + } _this->dumpLayout(); } @@ -515,7 +529,8 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin QSplitter* Splitter = newSplitter(InsertParam.orientation()); Layout->replaceWidget(TargetArea, Splitter); Splitter->addWidget(TargetArea); - TargetAreaSplitter = Splitter; + updateSplitterHandles(Splitter); + TargetAreaSplitter = Splitter; } int AreaIndex = TargetAreaSplitter->indexOf(TargetArea); auto Widget = FloatingWidget->dockContainer()->findChild(QString(), Qt::FindDirectChildrenOnly); @@ -529,7 +544,8 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1) { TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), Widget); - } + updateSplitterHandles(TargetAreaSplitter); + } else { AdjustSplitterSizes = (FloatingSplitter->count() == 1); @@ -537,8 +553,9 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin while (FloatingSplitter->count()) { TargetAreaSplitter->insertWidget(InsertIndex++, FloatingSplitter->widget(0)); - } - } + updateSplitterHandles(TargetAreaSplitter); + } + } if (AdjustSplitterSizes) { @@ -557,28 +574,32 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1) { NewSplitter->addWidget(Widget); - } + updateSplitterHandles(NewSplitter); + } else { AdjustSplitterSizes = (FloatingSplitter->count() == 1); while (FloatingSplitter->count()) { NewSplitter->addWidget(FloatingSplitter->widget(0)); - } - } + updateSplitterHandles(NewSplitter); + } + } // Save the sizes before insertion and restore it later to prevent // shrinking of existing area auto Sizes = TargetAreaSplitter->sizes(); insertWidgetIntoSplitter(NewSplitter, TargetArea, !InsertParam.append()); - if (AdjustSplitterSizes) + updateSplitterHandles(NewSplitter); + if (AdjustSplitterSizes) { int Size = TargetAreaSize / 2; NewSplitter->setSizes({Size, Size}); } TargetAreaSplitter->insertWidget(AreaIndex, NewSplitter); TargetAreaSplitter->setSizes(Sizes); - } + updateSplitterHandles(TargetAreaSplitter); + } addDockAreasToList(NewDockAreas); _this->dumpLayout(); @@ -663,7 +684,8 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg { int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height(); TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), NewDockArea); - int Size = (TargetAreaSize - TargetAreaSplitter->handleWidth()) / 2; + updateSplitterHandles(TargetAreaSplitter); + int Size = (TargetAreaSize - TargetAreaSplitter->handleWidth()) / 2; Sizes[AreaIndex] = Size; Sizes.insert(AreaIndex, Size); } @@ -674,16 +696,54 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); NewSplitter->addWidget(TargetArea); insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append()); - int Size = TargetAreaSize / 2; + updateSplitterHandles(NewSplitter); + int Size = TargetAreaSize / 2; NewSplitter->setSizes({Size, Size}); TargetAreaSplitter->insertWidget(AreaIndex, NewSplitter); - } + updateSplitterHandles(TargetAreaSplitter); + } TargetAreaSplitter->setSizes(Sizes); addDockAreasToList({NewDockArea}); } +//============================================================================ +void DockContainerWidgetPrivate::updateSplitterHandles( QSplitter* splitter ) +{ + if( splitter ) + { + for( int index = 0; index < splitter->count(); index++ ) + { + splitter->setStretchFactor(index, widgetResizesWithContainer(splitter->widget(index)) ? 1 : 0); + } + } +} + + +//============================================================================ +bool DockContainerWidgetPrivate::widgetResizesWithContainer(QWidget* widget) +{ + if(!DockManager->centralWidget()) + return true; + + CDockAreaWidget* Area = dynamic_cast< CDockAreaWidget* >( widget ); + if(Area) + { + return Area->isCentralWidgetArea(); + } + + CDockSplitter* innerSplitter = dynamic_cast< CDockSplitter* >( widget ); + if(innerSplitter) + { + return innerSplitter->resizeWithContainer(); + } + + return false; +} + + + //============================================================================ void DockContainerWidgetPrivate::moveToContainer(QWidget* Widget, DockWidgetArea area) { @@ -892,6 +952,10 @@ bool DockContainerWidgetPrivate::restoreSplitter(CDockingStateReader& s, Splitter->addWidget(ChildNode); Visible |= ChildNode->isVisibleTo(Splitter); } + if(!Testing) + { + updateSplitterHandles(Splitter); + } if (Sizes.count() != WidgetCount) { @@ -1069,7 +1133,8 @@ void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockW if (Splitter->orientation() == InsertParam.orientation()) { insertWidgetIntoSplitter(Splitter, NewDockArea, InsertParam.append()); - if (Splitter->isHidden()) + updateSplitterHandles(Splitter); + if (Splitter->isHidden()) { Splitter->show(); } @@ -1082,14 +1147,16 @@ void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockW QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter); NewSplitter->addWidget(Splitter); NewSplitter->addWidget(NewDockArea); - delete li; + updateSplitterHandles(NewSplitter); + delete li; } else { NewSplitter->addWidget(NewDockArea); QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter); NewSplitter->addWidget(Splitter); - delete li; + updateSplitterHandles(NewSplitter); + delete li; } RootSplitter = NewSplitter; } @@ -1175,7 +1242,8 @@ CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToDockArea(DockWidgetA { ADS_PRINT("TargetAreaSplitter->orientation() == InsertParam.orientation()"); TargetAreaSplitter->insertWidget(index + InsertParam.insertOffset(), NewDockArea); - // do nothing, if flag is not enabled + updateSplitterHandles(TargetAreaSplitter); + // do nothing, if flag is not enabled if (CDockManager::testConfigFlag(CDockManager::EqualSplitOnInsertion)) { adjustSplitterSizesOnInsertion(TargetAreaSplitter); @@ -1188,11 +1256,14 @@ CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToDockArea(DockWidgetA auto TargetAreaSizes = TargetAreaSplitter->sizes(); QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); NewSplitter->addWidget(TargetDockArea); +// updateSplitterHandles(NewSplitter); insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append()); - TargetAreaSplitter->insertWidget(index, NewSplitter); - if (CDockManager::testConfigFlag(CDockManager::EqualSplitOnInsertion)) - { + updateSplitterHandles(NewSplitter); + TargetAreaSplitter->insertWidget(index, NewSplitter); + updateSplitterHandles(TargetAreaSplitter); + if (CDockManager::testConfigFlag(CDockManager::EqualSplitOnInsertion)) + { TargetAreaSplitter->setSizes(TargetAreaSizes); adjustSplitterSizesOnInsertion(NewSplitter); } @@ -1381,9 +1452,11 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area) } delete Splitter; + Splitter = nullptr; emitAndExit: - CDockWidget* TopLevelWidget = topLevelDockWidget(); + updateSplitterHandles(Splitter); + CDockWidget* TopLevelWidget = topLevelDockWidget(); // Updated the title bar visibility of the dock widget if there is only // one single visible dock widget @@ -1732,6 +1805,13 @@ QList CDockContainerWidget::dockWidgets() const } +//============================================================================ +void CDockContainerWidget::updateSplitterHandles(QSplitter* splitter) +{ + d->updateSplitterHandles(splitter); +} + + //============================================================================ CDockWidget::DockWidgetFeatures CDockContainerWidget::features() const { diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index 1ce2a9e..5e8b8cb 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -155,6 +155,12 @@ protected: */ QList dockWidgets() const; + /** + * This finction forces the dock container widget to update handles of splitters + * based on resize modes of dock widgets aontained in the container. + */ + void updateSplitterHandles(QSplitter* splitter); + public: /** * Default Constructor diff --git a/src/DockManager.cpp b/src/DockManager.cpp index 95e4fac..717ffde 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -108,6 +108,7 @@ struct DockManagerPrivate bool RestoringState = false; QVector UninitializedFloatingWidgets; CDockFocusController* FocusController = nullptr; + CDockWidget* CentralWidget = nullptr; /** * Private data constructor @@ -816,6 +817,23 @@ void CDockManager::loadPerspectives(QSettings& Settings) Settings.endArray(); } +CDockWidget* CDockManager::centralWidget() +{ + return d->CentralWidget; +} + +//============================================================================ +CDockAreaWidget* CDockManager::setCentralWidget(CDockWidget* widget) +{ + if(d->CentralWidget) + { + addDockWidget(RightDockWidgetArea, d->CentralWidget); + } + + d->CentralWidget = widget; + return addDockWidget(CenterDockWidgetArea, widget); +} + //============================================================================ QAction* CDockManager::addToggleViewActionToMenu(QAction* ToggleViewAction, const QString& Group, const QIcon& GroupIcon) diff --git a/src/DockManager.h b/src/DockManager.h index b682c43..7808a43 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -378,7 +378,19 @@ public: */ void loadPerspectives(QSettings& Settings); - /** + /** + * This function returns managers central widget or nullptr if no central widget is set. + */ + CDockWidget* centralWidget(); + + /** + * Adds dockwidget into the central area and marks it as central widget. + * If central widget is set, it will be the only dock widget + * that will resize with the dock container. + */ + CDockAreaWidget* setCentralWidget(CDockWidget* widget); + + /** * 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 diff --git a/src/DockSplitter.cpp b/src/DockSplitter.cpp index 92f988d..2be1f07 100644 --- a/src/DockSplitter.cpp +++ b/src/DockSplitter.cpp @@ -102,6 +102,20 @@ QWidget* CDockSplitter::lastWidget() const return (count() > 0) ? widget(count() - 1) : nullptr; } +//============================================================================ +bool CDockSplitter::resizeWithContainer() +{ + QList areas = findChildren(); + + for(int i=0; iisCentralWidgetArea()) + return true; + } + return false; +} + } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/DockSplitter.h b/src/DockSplitter.h index 24abc40..9dacdf8 100644 --- a/src/DockSplitter.h +++ b/src/DockSplitter.h @@ -71,6 +71,11 @@ public: * Returns last widget of nullptr is splitter is empty */ QWidget* lastWidget() const; + + /** + * Returns true if the splitter contains central widget of dock manager. + */ + bool resizeWithContainer(); }; // class CDockSplitter } // namespace ads diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index 56c697e..1c3d521 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -461,6 +461,12 @@ void CDockWidget::setMinimumSizeHintMode(eMinimumSizeHintMode Mode) } +bool CDockWidget::isCentralWidget() +{ + return dockManager()->centralWidget() == this; +} + + //============================================================================ void CDockWidget::toggleView(bool Open) { diff --git a/src/DockWidget.h b/src/DockWidget.h index 72f2341..ef8be51 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -360,6 +360,11 @@ public: */ void setMinimumSizeHintMode(eMinimumSizeHintMode Mode); + /** + * Returns true if the dock wisget is set as central widget of it's dock manager + */ + bool isCentralWidget(); + /** * Sets the dock widget icon that is shown in tabs and in toggle view * actions