From be3180df6f495a4a6fae0b5961fc2c6e85061fa2 Mon Sep 17 00:00:00 2001 From: Jean Porcherot Date: Wed, 7 Apr 2021 16:51:46 +0200 Subject: [PATCH] Add dockdepth1 example --- examples/dockdepth1/CMakeLists.txt | 26 +++++ examples/dockdepth1/MainWindow.cpp | 63 +++++++++++ examples/dockdepth1/MainWindow.h | 15 +++ examples/dockdepth1/dockdepth1.pro | 29 +++++ examples/dockdepth1/innertabs.cpp | 171 +++++++++++++++++++++++++++++ examples/dockdepth1/innertabs.h | 45 ++++++++ examples/dockdepth1/main.cpp | 11 ++ examples/examples.pro | 3 +- 8 files changed, 362 insertions(+), 1 deletion(-) create mode 100644 examples/dockdepth1/CMakeLists.txt create mode 100644 examples/dockdepth1/MainWindow.cpp create mode 100644 examples/dockdepth1/MainWindow.h create mode 100644 examples/dockdepth1/dockdepth1.pro create mode 100644 examples/dockdepth1/innertabs.cpp create mode 100644 examples/dockdepth1/innertabs.h create mode 100644 examples/dockdepth1/main.cpp diff --git a/examples/dockdepth1/CMakeLists.txt b/examples/dockdepth1/CMakeLists.txt new file mode 100644 index 0000000..6ca354a --- /dev/null +++ b/examples/dockdepth1/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.5) +project(ads_example_simple VERSION ${VERSION_SHORT}) +find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +add_executable(DockDepth1 WIN32 + innertabs.cpp + main.cpp + MainWindow.cpp + MainWindow.ui +) +target_include_directories(SimpleExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src") +target_link_libraries(SimpleExample PRIVATE qtadvanceddocking) +target_link_libraries(SimpleExample PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets) +set_target_properties(SimpleExample 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 Simple 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/dockdepth1/MainWindow.cpp b/examples/dockdepth1/MainWindow.cpp new file mode 100644 index 0000000..31b056c --- /dev/null +++ b/examples/dockdepth1/MainWindow.cpp @@ -0,0 +1,63 @@ +#include "../../examples/dockdepth1/MainWindow.h" +#include "../../examples/dockdepth1/innertabs.h" + +#include +#include + +#include "DockAreaWidget.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent) +{ + resize( 400, 400 ); + + DockManagerWithInnerTabs* dockManager = new DockManagerWithInnerTabs(this); + + dockManager->attachViewMenu( menuBar()->addMenu( "View" ) ); + + ads::CDockAreaWidget* previousDockWidget = NULL; + for ( int i = 0; i != 3; ++i ) + { + // Create example content label - this can be any application specific + // widget + QLabel* l = new QLabel(); + l->setWordWrap(true); + l->setAlignment(Qt::AlignTop | Qt::AlignLeft); + l->setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. "); + + // Create a dock widget with the title Label 1 and set the created label + // as the dock widget content + ads::CDockWidget* DockWidget = new ads::CDockWidget("Label " + QString::number(i)); + DockWidget->setWidget(l); + + // Add the dock widget to the top dock widget area + previousDockWidget = dockManager->addDockWidget(ads::CenterDockWidgetArea, DockWidget, previousDockWidget); + } + + ads::CDockContainerWidget* groupManager = dockManager->createGroup( "Group", previousDockWidget ).second; + + previousDockWidget = NULL; + for ( int i = 0; i != 3; ++i ) + { + // Create example content label - this can be any application specific + // widget + QLabel* l = new QLabel(); + l->setWordWrap(true); + l->setAlignment(Qt::AlignTop | Qt::AlignLeft); + l->setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. "); + + // Create a dock widget with the title Label 1 and set the created label + // as the dock widget content + ads::CDockWidget* DockWidget = new ads::CDockWidget("Inner " + QString::number(i)); + DockWidget->setWidget(l); + + // Add the dock widget to the top dock widget area + previousDockWidget = groupManager->addDockWidget(ads::CenterDockWidgetArea, DockWidget, previousDockWidget); + } +} + +MainWindow::~MainWindow() +{ + +} + diff --git a/examples/dockdepth1/MainWindow.h b/examples/dockdepth1/MainWindow.h new file mode 100644 index 0000000..f834c00 --- /dev/null +++ b/examples/dockdepth1/MainWindow.h @@ -0,0 +1,15 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); +}; + +#endif // MAINWINDOW_H diff --git a/examples/dockdepth1/dockdepth1.pro b/examples/dockdepth1/dockdepth1.pro new file mode 100644 index 0000000..a8ae279 --- /dev/null +++ b/examples/dockdepth1/dockdepth1.pro @@ -0,0 +1,29 @@ +ADS_OUT_ROOT = $${OUT_PWD}/../.. + +QT += core gui widgets + +TARGET = DockDepth1 +DESTDIR = $${ADS_OUT_ROOT}/lib +TEMPLATE = app +CONFIG += c++14 +CONFIG += debug_and_release +adsBuildStatic { + DEFINES += ADS_STATIC +} + +DEFINES += QT_DEPRECATED_WARNINGS + +SOURCES += \ + innertabs.cpp \ + main.cpp \ + MainWindow.cpp + +HEADERS += \ + innertabs.h \ + MainWindow.h + +LIBS += -L$${ADS_OUT_ROOT}/lib +include(../../ads.pri) +INCLUDEPATH += ../../src +DEPENDPATH += ../../src + diff --git a/examples/dockdepth1/innertabs.cpp b/examples/dockdepth1/innertabs.cpp new file mode 100644 index 0000000..1476134 --- /dev/null +++ b/examples/dockdepth1/innertabs.cpp @@ -0,0 +1,171 @@ +#include "innertabs.h" + +#include "DockAreaWidget.h" + +#include +#include + +///////////////////////////////////// +// DockManagerWithInnerTabs +///////////////////////////////////// +void deleteAllChildren( ads::CDockContainerWidget* areaWidget ) +{ + // fix crash on close by manually deleting children + // maybe due to this issue: https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/307 + + std::vector areas; + for ( int i = 0; i != areaWidget->dockAreaCount(); ++i ) + { + areas.push_back( areaWidget->dockArea(i) ); + } + + for ( auto area : areas ) + { + for ( auto widget : area->dockWidgets() ) + { + ads::CDockContainerWidget* subArea = dynamic_cast( widget->widget() ); + if ( subArea ) + deleteAllChildren( subArea ); + delete widget; + } + + delete area; + } +} + +DockManagerWithInnerTabs::~DockManagerWithInnerTabs() +{ + deleteAllChildren( this ); +} + +std::pair DockManagerWithInnerTabs::createGroup( const QString& groupName, ads::CDockAreaWidget*& insertPos ) +{ + ads::CDockWidget* groupedDockWidget = new ads::CDockWidget(groupName); + + ads::CDockContainerWidget* groupManager = new ads::CDockContainerWidget(this); + groupedDockWidget->setWidget(groupManager); + + insertPos = this->addDockWidget(ads::CenterDockWidgetArea, groupedDockWidget, insertPos); + + return { groupedDockWidget, groupManager }; +} + +void DockManagerWithInnerTabs::attachViewMenu( QMenu* menu ) +{ + connect( menu, SIGNAL(aboutToShow()), this, SLOT(autoFillAttachedViewMenu()) ); +} + +void DockManagerWithInnerTabs::autoFillAttachedViewMenu() +{ + QMenu* menu = dynamic_cast( QObject::sender() ); + + if ( menu ) + { + menu->clear(); + setupViewMenu( menu ); + } + else + { + assert( false ); + } +} + +bool SortFunc( ads::CDockWidget* left, ads::CDockWidget* right ) +{ + if ( left->windowTitle() == right->windowTitle() ) + { + assert( false ); + return left < right; + } + else + { + return left->windowTitle() < right->windowTitle(); + } +} + +void DockManagerWithInnerTabs::setupMenu( QMenu* menu, ads::CDockContainerWidget* areaWidget ) +{ + std::vector widgets; + + ads::CDockManager* dockManager = dynamic_cast( areaWidget ); + if ( dockManager ) + { + for ( ads::CFloatingDockContainer* floating : dockManager->floatingWidgets() ) + { + for ( auto floated : floating->dockWidgets() ) + widgets.push_back( floated ); + } + } + + for ( int i = 0; i != areaWidget->dockAreaCount(); ++i ) + { + for ( auto docked : areaWidget->dockArea(i)->dockWidgets() ) + widgets.push_back( docked ); + } + + std::sort( widgets.begin(), widgets.end(), SortFunc ); + + for ( auto widget : widgets ) + { + auto action = widget->toggleViewAction(); + + ads::CDockContainerWidget* subArea = dynamic_cast( widget->widget() ); + if ( subArea ) + { + auto subMenu = menu->addMenu( widget->windowTitle() ); + + subMenu->addAction( action ); + subMenu->addSeparator(); + + setupMenu( subMenu, subArea ); + } + else + { + menu->addAction(action); + } + } + + if ( dockManager ) + { + menu->addSeparator(); + int count = areaWidget->dockAreaCount(); + if ( count == 0 ) + { + menu->addAction( new CreateGroupAction( this, NULL, menu ) ); + } + else + { + for ( int i = 0; i != count; ++i ) + { + menu->addAction( new CreateGroupAction( this, areaWidget->dockArea(i), menu ) ); + } + } + } + // else, don't permit to add groups in groups + // that would be nice, but it's not handled correctly upon drag/drop of a widget, it cannot be dropped in the inner docking area +} + +void DockManagerWithInnerTabs::setupViewMenu( QMenu* menu ) +{ + setupMenu( menu, this ); +} + +///////////////////////////////////// +// CreateGroupAction +///////////////////////////////////// +CreateGroupAction::CreateGroupAction( DockManagerWithInnerTabs* manager, ads::CDockAreaWidget* insertPos, QMenu* menu ) : + QAction("New group...", menu), + m_manager( manager), + m_insertPos( insertPos ) +{ + connect( this, SIGNAL(triggered()), this, SLOT(createGroup()) ); +} + +void CreateGroupAction::createGroup() +{ + QString name = QInputDialog::getText( NULL, text(), "Enter group name" ); + if ( !name.isEmpty() ) + { + m_manager->createGroup( name, m_insertPos ); + } +} diff --git a/examples/dockdepth1/innertabs.h b/examples/dockdepth1/innertabs.h new file mode 100644 index 0000000..097ac14 --- /dev/null +++ b/examples/dockdepth1/innertabs.h @@ -0,0 +1,45 @@ +#pragma once + +#include "DockManager.h" + +#include + +class DockManagerWithInnerTabs : public ads::CDockManager +{ + Q_OBJECT + +public: + using ads::CDockManager::CDockManager; + + ~DockManagerWithInnerTabs() override; + + std::pair createGroup( const QString& groupName, ads::CDockAreaWidget*& insertPos ); + + /** Manually fill a given view menu */ + void setupViewMenu( QMenu* menu ); + + /** Attach a view menu that will be automatically fill */ + void attachViewMenu( QMenu* menu ); + +private slots: + void autoFillAttachedViewMenu(); + +private: + void setupMenu( QMenu* menu, ads::CDockContainerWidget* areaWidget ); +}; + +class CreateGroupAction : public QAction +{ + Q_OBJECT +public: + CreateGroupAction( DockManagerWithInnerTabs* manager, ads::CDockAreaWidget* insertIn, QMenu* menu ); + +public slots: + void createGroup(); + +private: + DockManagerWithInnerTabs* m_manager; + ads::CDockAreaWidget* m_insertPos; +}; + + diff --git a/examples/dockdepth1/main.cpp b/examples/dockdepth1/main.cpp new file mode 100644 index 0000000..83e8bb7 --- /dev/null +++ b/examples/dockdepth1/main.cpp @@ -0,0 +1,11 @@ +#include +#include "../../examples/simple/MainWindow.h" + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/examples/examples.pro b/examples/examples.pro index 86ac5b0..9e579df 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -5,4 +5,5 @@ SUBDIRS = \ simple \ sidebar \ deleteonclose \ - emptydockarea + emptydockarea \ + dockdepth1