diff --git a/.gitignore b/.gitignore index f9e79be..05aa783 100644 --- a/.gitignore +++ b/.gitignore @@ -382,3 +382,4 @@ MigrationBackup/ FodyWeavers.xsd / build /Settings.ini +.vscode/settings.json 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..aa69603 --- /dev/null +++ b/examples/centralWidget/CMakeLists.txt @@ -0,0 +1,25 @@ +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 +) +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..9c00fd6 --- /dev/null +++ b/examples/centralWidget/centralWidget.pro @@ -0,0 +1,54 @@ +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 += \ + main.cpp \ + mainwindow.cpp + +HEADERS += \ + 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/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..285de5b --- /dev/null +++ b/examples/centralWidget/mainwindow.cpp @@ -0,0 +1,226 @@ +#include "mainwindow.h" +#include "ui_mainwindow.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); + auto* CentralDockArea = DockManager->setCentralWidget(CentralDockWidget); + CentralDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas); + + 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("Test 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->setFeature(CDockWidget::DockWidgetClosable, false); + TimelineDockWidget->setFeature(CDockWidget::DockWidgetMovable, false); + TimelineDockWidget->setFeature(CDockWidget::DockWidgetFloatable, false); + TimelineDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); + TimelineDockWidget->setMinimumSize(QSize(50, 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); + 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); + CDockWidget* StatusDockWidget = new CDockWidget("Status"); + StatusDockWidget->setWidget(statusWidget); + StatusDockWidget->setFeature(CDockWidget::DockWidgetClosable, false); + StatusDockWidget->setFeature(CDockWidget::DockWidgetMovable, false); + StatusDockWidget->setFeature(CDockWidget::DockWidgetFloatable, false); + StatusDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); + StatusDockWidget->setMinimumSize(QSize(50, 50)); + StatusDockArea = DockManager->addDockWidget(DockWidgetArea::BottomDockWidgetArea, StatusDockWidget); + StatusDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas); + StatusDockArea->setDockAreaFlag(ads::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 78c4e5e..2fb345c 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -452,6 +452,7 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget, DockWidget->toggleViewInternal(true); } d->updateTitleBarButtonStates(); + updateTitleBarVisibility(); } @@ -966,6 +967,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 55b1a39..231af91 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -154,7 +154,7 @@ public: }; Q_DECLARE_FLAGS(DockAreaFlags, eDockAreaFlag) - /** + /** * Default Constructor */ CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent); @@ -307,6 +307,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..171a8e0 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,57 @@ 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(DockManager->centralWidget()) + { + 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 +955,10 @@ bool DockContainerWidgetPrivate::restoreSplitter(CDockingStateReader& s, Splitter->addWidget(ChildNode); Visible |= ChildNode->isVisibleTo(Splitter); } + if(!Testing) + { + updateSplitterHandles(Splitter); + } if (Sizes.count() != WidgetCount) { @@ -1069,7 +1136,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 +1150,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 +1245,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); @@ -1190,9 +1261,11 @@ CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToDockArea(DockWidgetA NewSplitter->addWidget(TargetDockArea); 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 +1454,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 +1807,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 f75ff71..503a122 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 @@ -406,6 +407,7 @@ bool DockManagerPrivate::restoreState(const QByteArray& State, int version) return false; } + CentralWidget = nullptr; // Hide updates of floating widgets from use hideFloatingWidgets(); markDockWidgetsDirty(); @@ -829,6 +831,33 @@ void CDockManager::loadPerspectives(QSettings& Settings) Settings.endArray(); } +CDockWidget* CDockManager::centralWidget() +{ + return d->CentralWidget; +} + +//============================================================================ +CDockAreaWidget* CDockManager::setCentralWidget(CDockWidget* widget, CDockWidget* oldCentralWidget, DockWidgetArea oldCentralWidgetArea) +{ + oldCentralWidget = d->CentralWidget; + if(oldCentralWidget) + { + addDockWidget(oldCentralWidgetArea, oldCentralWidget); + } + + if(widget) + { + widget->setFeature(CDockWidget::DockWidgetClosable, false); + widget->setFeature(CDockWidget::DockWidgetMovable, false); + widget->setFeature(CDockWidget::DockWidgetFloatable, false); + d->CentralWidget = widget; + CDockAreaWidget* CentralArea = addDockWidget(CenterDockWidgetArea, widget); + CentralArea->setDockAreaFlag(CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); + return CentralArea; + } + return nullptr; +} + //============================================================================ QAction* CDockManager::addToggleViewActionToMenu(QAction* ToggleViewAction, const QString& Group, const QIcon& GroupIcon) diff --git a/src/DockManager.h b/src/DockManager.h index b682c43..07f735c 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -378,7 +378,21 @@ 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. + * If a central widget does exist, it will be docked to oldCentralWidgetArea + * and returned in oldCentralWidget. + */ + CDockAreaWidget* setCentralWidget(CDockWidget* widget, CDockWidget* oldCentralWidget = nullptr, DockWidgetArea oldCentralWidgetArea = DockWidgetArea::RightDockWidgetArea); + + /** * 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 83cb613..22b282b 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -463,6 +463,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 ccae27e..b574fa4 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