mirror of
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
synced 2024-12-26 08:01:32 +08:00
Replace dockdepth1 by dockindock
This commit is contained in:
parent
bac0698581
commit
2c7b5982b5
@ -1,63 +0,0 @@
|
|||||||
#include "../../examples/dockdepth1/MainWindow.h"
|
|
||||||
#include "../../examples/dockdepth1/innertabs.h"
|
|
||||||
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QMenuBar>
|
|
||||||
|
|
||||||
#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()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
|||||||
#ifndef MAINWINDOW_H
|
|
||||||
#define MAINWINDOW_H
|
|
||||||
|
|
||||||
#include <QMainWindow>
|
|
||||||
|
|
||||||
class MainWindow : public QMainWindow
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit MainWindow(QWidget *parent = 0);
|
|
||||||
~MainWindow();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MAINWINDOW_H
|
|
@ -1,173 +0,0 @@
|
|||||||
#include "innertabs.h"
|
|
||||||
|
|
||||||
#include "DockAreaWidget.h"
|
|
||||||
|
|
||||||
#include <QInputDialog>
|
|
||||||
#include <QMenu>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/////////////////////////////////////
|
|
||||||
// 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<ads::CDockAreaWidget*> 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<ads::CDockContainerWidget*>( widget->widget() );
|
|
||||||
if ( subArea )
|
|
||||||
deleteAllChildren( subArea );
|
|
||||||
delete widget;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete area;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DockManagerWithInnerTabs::~DockManagerWithInnerTabs()
|
|
||||||
{
|
|
||||||
deleteAllChildren( this );
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<ads::CDockWidget*,ads::CDockContainerWidget*> 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<QMenu*>( 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<ads::CDockWidget*> widgets;
|
|
||||||
|
|
||||||
ads::CDockManager* dockManager = dynamic_cast<ads::CDockManager*>( 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<ads::CDockContainerWidget*>( 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 );
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "DockManager.h"
|
|
||||||
|
|
||||||
#include <QAction>
|
|
||||||
|
|
||||||
class DockManagerWithInnerTabs : public ads::CDockManager
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
using ads::CDockManager::CDockManager;
|
|
||||||
|
|
||||||
~DockManagerWithInnerTabs() override;
|
|
||||||
|
|
||||||
std::pair<ads::CDockWidget*,ads::CDockContainerWidget*> 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -2,11 +2,13 @@ cmake_minimum_required(VERSION 3.5)
|
|||||||
project(ads_example_simple VERSION ${VERSION_SHORT})
|
project(ads_example_simple VERSION ${VERSION_SHORT})
|
||||||
find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED)
|
find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED)
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
add_executable(DockDepth1 WIN32
|
add_executable(DockInDock WIN32
|
||||||
innertabs.cpp
|
dockindock.cpp
|
||||||
|
dockindockmanager.cpp
|
||||||
|
perspectiveactions.cpp
|
||||||
|
perspectives.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
MainWindow.cpp
|
mainframe.cpp
|
||||||
MainWindow.ui
|
|
||||||
)
|
)
|
||||||
target_include_directories(SimpleExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
|
target_include_directories(SimpleExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
|
||||||
target_link_libraries(SimpleExample PRIVATE qtadvanceddocking)
|
target_link_libraries(SimpleExample PRIVATE qtadvanceddocking)
|
296
examples/dockindock/dockindock.cpp
Normal file
296
examples/dockindock/dockindock.cpp
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
#include "dockindock.h"
|
||||||
|
#include "perspectives.h"
|
||||||
|
#include "dockindockmanager.h"
|
||||||
|
#include "perspectiveactions.h"
|
||||||
|
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QInputDialog>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
using namespace QtAdsUtl;
|
||||||
|
|
||||||
|
DockInDockWidget::DockInDockWidget( QWidget* parent, bool canCreateNewGroups, PerspectivesManager* perspectivesManager ) :
|
||||||
|
DockInDockWidget( parent, (DockInDockWidget*)NULL, perspectivesManager )
|
||||||
|
{
|
||||||
|
m_canCreateNewGroups = canCreateNewGroups;
|
||||||
|
m_topLevelDockWidget = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DockInDockWidget::DockInDockWidget( QWidget* parent, DockInDockWidget* topLevelDockWidget, PerspectivesManager* perspectivesManager ) :
|
||||||
|
baseClass( parent ),
|
||||||
|
m_topLevelDockWidget( topLevelDockWidget ),
|
||||||
|
m_canCreateNewGroups( (topLevelDockWidget) ? topLevelDockWidget->m_canCreateNewGroups : false ),
|
||||||
|
m_perspectivesManager( perspectivesManager )
|
||||||
|
{
|
||||||
|
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||||
|
layout->setContentsMargins( 0,0,0,0 );
|
||||||
|
layout->addWidget( m_mgr = new DockInDockManager(*this) );
|
||||||
|
}
|
||||||
|
|
||||||
|
DockInDockWidget::~DockInDockWidget()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ads::CDockAreaWidget* DockInDockWidget::addTabWidget( QWidget* widget, const QString& name, ads::CDockAreaWidget* after )
|
||||||
|
{
|
||||||
|
return addTabWidget( widget, name, QIcon(), after );
|
||||||
|
}
|
||||||
|
|
||||||
|
ads::CDockAreaWidget* DockInDockWidget::addTabWidget( QWidget* widget, const QString& name, QIcon icon, ads::CDockAreaWidget* after )
|
||||||
|
{
|
||||||
|
for ( auto existing : getTopLevelDockWidget()->getManager()->allDockWidgets(true,true) )
|
||||||
|
{
|
||||||
|
if ( existing.second->objectName() == name )
|
||||||
|
{
|
||||||
|
QMessageBox::critical( this, "Error", "Name '" + name + "' already in use" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ads::CDockWidget* DockWidget = new ads::CDockWidget(name);
|
||||||
|
DockWidget->setWidget(widget);
|
||||||
|
DockWidget->setIcon( icon );
|
||||||
|
|
||||||
|
// Add the dock widget to the top dock widget area
|
||||||
|
return m_mgr->addDockWidget(ads::CenterDockWidgetArea, DockWidget, after);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DockInDockWidget::isTopLevel()
|
||||||
|
{
|
||||||
|
return objectName().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DockInDockWidget::getGroupNameError( const QString& groupName )
|
||||||
|
{
|
||||||
|
if ( groupName.isEmpty() )
|
||||||
|
{
|
||||||
|
return "Group must have a non-empty name";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<DockInDockManager*> dockManagers = m_mgr->allManagers( true, true );
|
||||||
|
for ( auto mgr : dockManagers )
|
||||||
|
{
|
||||||
|
if ( mgr->getGroupName() == groupName )
|
||||||
|
return "Group name '" + groupName + "' already used";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
DockInDockWidget* DockInDockWidget::createGroup( const QString& groupName, ads::CDockAreaWidget*& insertPos )
|
||||||
|
{
|
||||||
|
return createGroup( groupName, QIcon(), insertPos );
|
||||||
|
}
|
||||||
|
|
||||||
|
DockInDockWidget* DockInDockWidget::createGroup( const QString& groupName, QIcon icon, ads::CDockAreaWidget*& insertPos )
|
||||||
|
{
|
||||||
|
QString error = getGroupNameError( groupName );
|
||||||
|
if ( !error.isEmpty() )
|
||||||
|
{
|
||||||
|
QMessageBox::critical( NULL, "Error", error );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DockInDockWidget* child = new DockInDockWidget( this, m_topLevelDockWidget, m_perspectivesManager );
|
||||||
|
child->setObjectName( groupName );
|
||||||
|
|
||||||
|
ads::CDockWidget* DockWidget = new ads::CDockWidget(groupName);
|
||||||
|
DockWidget->setWidget(child);
|
||||||
|
DockWidget->setIcon(icon);
|
||||||
|
|
||||||
|
insertPos = m_mgr->addDockWidget(ads::CenterDockWidgetArea, DockWidget, insertPos);
|
||||||
|
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockWidget::destroyGroup( DockInDockWidget* widgetToRemove )
|
||||||
|
{
|
||||||
|
auto topLevelWidget = widgetToRemove->getTopLevelDockWidget();
|
||||||
|
|
||||||
|
if ( topLevelWidget && topLevelWidget != widgetToRemove )
|
||||||
|
{
|
||||||
|
// reaffect all child docks to top-level
|
||||||
|
for ( auto dockwidget : widgetToRemove->getManager()->getWidgetsInGUIOrder() ) // don't use allDockWidgets to preserve sub-groups
|
||||||
|
{
|
||||||
|
MoveDockWidgetAction::move( dockwidget, topLevelWidget->getManager() );
|
||||||
|
}
|
||||||
|
assert( widgetToRemove->getManager()->allDockWidgets( true, true ).empty() );
|
||||||
|
|
||||||
|
// find widget's parent:
|
||||||
|
for ( auto dockwidget : topLevelWidget->getManager()->allDockWidgets( true, true ) )
|
||||||
|
{
|
||||||
|
if ( dockwidget.second->widget() == widgetToRemove )
|
||||||
|
{
|
||||||
|
dockwidget.first->removeDockWidget( dockwidget.second );
|
||||||
|
delete dockwidget.second;
|
||||||
|
//delete widgetToRemove; automatically deleted when dockWidget is deleted
|
||||||
|
widgetToRemove = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert( widgetToRemove == NULL );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockWidget::attachViewMenu( QMenu* menu )
|
||||||
|
{
|
||||||
|
connect( menu, SIGNAL(aboutToShow()), this, SLOT(autoFillAttachedViewMenu()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockWidget::autoFillAttachedViewMenu()
|
||||||
|
{
|
||||||
|
QMenu* menu = dynamic_cast<QMenu*>( QObject::sender() );
|
||||||
|
|
||||||
|
if ( menu )
|
||||||
|
{
|
||||||
|
menu->clear();
|
||||||
|
setupViewMenu( menu );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockWidget::setupViewMenu( QMenu* menu )
|
||||||
|
{
|
||||||
|
std::vector<DockInDockManager*> dockManagers = m_mgr->allManagers( true, true );
|
||||||
|
|
||||||
|
bool hasPerspectivesMenu = false;
|
||||||
|
if ( getTopLevelDockWidget() == this )
|
||||||
|
hasPerspectivesMenu = (m_perspectivesManager != NULL);
|
||||||
|
else
|
||||||
|
assert( false );
|
||||||
|
|
||||||
|
QMenu* organize = menu;
|
||||||
|
if ( hasPerspectivesMenu )
|
||||||
|
organize = menu->addMenu( "Organize" );
|
||||||
|
|
||||||
|
setupMenu( organize, dockManagers );
|
||||||
|
|
||||||
|
if ( hasPerspectivesMenu )
|
||||||
|
{
|
||||||
|
QMenu* perspectives = menu->addMenu( "Perspectives" );
|
||||||
|
fillPerspectivesMenu( perspectives );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockWidget::setupMenu( QMenu* menu, const std::vector<DockInDockManager*>& moveTo )
|
||||||
|
{
|
||||||
|
m_mgr->fillViewMenu( menu, moveTo );
|
||||||
|
menu->addSeparator();
|
||||||
|
auto moveMenu = menu->addMenu( "Move" );
|
||||||
|
m_mgr->fillMoveMenu( moveMenu, moveTo );
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockWidget::fillPerspectivesMenu( QMenu* menu )
|
||||||
|
{
|
||||||
|
menu->addAction( "Create perspective...", this, SLOT(createPerspective()) );
|
||||||
|
|
||||||
|
QStringList perspectiveNames;
|
||||||
|
if ( m_perspectivesManager )
|
||||||
|
perspectiveNames = m_perspectivesManager->perspectiveNames();
|
||||||
|
|
||||||
|
if ( !perspectiveNames.isEmpty() )
|
||||||
|
{
|
||||||
|
QMenu* load = menu->addMenu( "Load perspective" );
|
||||||
|
for ( auto name : perspectiveNames )
|
||||||
|
load->addAction( new LoadPerspectiveAction( load, name, *this ) );
|
||||||
|
QMenu* remove = menu->addMenu( "Remove perspective" );
|
||||||
|
for ( auto name : perspectiveNames )
|
||||||
|
remove->addAction( new RemovePerspectiveAction( remove, name, *this ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockWidget::setNewPerspectiveDefaultName( const QString& defaultName )
|
||||||
|
{
|
||||||
|
m_newPerspectiveDefaultName = defaultName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockWidget::createPerspective()
|
||||||
|
{
|
||||||
|
if ( !m_perspectivesManager )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString name = m_newPerspectiveDefaultName;
|
||||||
|
if ( !m_newPerspectiveDefaultName.isEmpty() )
|
||||||
|
{
|
||||||
|
int index = 2;
|
||||||
|
while ( m_perspectivesManager->perspectiveNames().contains( name ) )
|
||||||
|
{
|
||||||
|
name = m_newPerspectiveDefaultName + " (" + QString::number(index) + ")";
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
name = QInputDialog::getText( NULL, "Create perspective", "Enter perspective name", QLineEdit::Normal, name, &ok );
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
if ( name.isEmpty() )
|
||||||
|
{
|
||||||
|
QMessageBox::critical( NULL, "Error", "Perspective name cannot be empty" );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if ( m_perspectivesManager->perspectiveNames().contains( name ) )
|
||||||
|
{
|
||||||
|
if ( QMessageBox::critical( NULL, "Error", "Perspective '" + name + "' already exists, overwrite it?", QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) == QMessageBox::No )
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_perspectivesManager->addPerspective( name, *this );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dumpStatus( std::ostream& str, ads::CDockWidget* widget, const std::string& tab, std::string suffix )
|
||||||
|
{
|
||||||
|
DockInDockManager* asMgr = DockInDockManager::dockInAManager( widget );
|
||||||
|
if ( asMgr )
|
||||||
|
{
|
||||||
|
asMgr->parent().dumpStatus( str, tab );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str << tab << widget->objectName().toStdString() << suffix << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockWidget::dumpStatus( std::ostream& str, std::string tab )
|
||||||
|
{
|
||||||
|
str << tab << "Group: " << getManager()->getGroupName().toStdString() << std::endl;
|
||||||
|
tab += " ";
|
||||||
|
std::set<ads::CDockWidget*> visibleWidgets;
|
||||||
|
for ( auto widget : getManager()->getWidgetsInGUIOrder() )
|
||||||
|
{
|
||||||
|
visibleWidgets.insert( widget );
|
||||||
|
::dumpStatus( str, widget, tab, "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( auto closed : getManager()->dockWidgetsMap() )
|
||||||
|
{
|
||||||
|
if ( visibleWidgets.find( closed ) == visibleWidgets.end() )
|
||||||
|
{
|
||||||
|
::dumpStatus( str, closed, tab, " (closed)" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
80
examples/dockindock/dockindock.h
Normal file
80
examples/dockindock/dockindock.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
class QMenu;
|
||||||
|
|
||||||
|
namespace ads
|
||||||
|
{
|
||||||
|
class CDockAreaWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace QtAdsUtl
|
||||||
|
{
|
||||||
|
|
||||||
|
class DockInDockManager;
|
||||||
|
class PerspectivesManager;
|
||||||
|
// tab of tab example for https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/306
|
||||||
|
class DockInDockWidget : public QWidget
|
||||||
|
{
|
||||||
|
typedef QWidget baseClass;
|
||||||
|
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
DockInDockWidget( QWidget* parent, bool canCreateNewGroups, PerspectivesManager* perspectivesManager );
|
||||||
|
~DockInDockWidget() override;
|
||||||
|
|
||||||
|
ads::CDockAreaWidget* addTabWidget( QWidget* widget, const QString& name, ads::CDockAreaWidget* after );
|
||||||
|
DockInDockWidget* createGroup( const QString& groupName, ads::CDockAreaWidget*& insertPos );
|
||||||
|
|
||||||
|
ads::CDockAreaWidget* addTabWidget( QWidget* widget, const QString& name, QIcon icon, ads::CDockAreaWidget* after );
|
||||||
|
DockInDockWidget* createGroup( const QString& groupName, QIcon icon, ads::CDockAreaWidget*& insertPos );
|
||||||
|
|
||||||
|
QString getGroupNameError( const QString& groupName );
|
||||||
|
void destroyGroup( DockInDockWidget* widget );
|
||||||
|
|
||||||
|
/** Manually fill a given view menu */
|
||||||
|
void setupViewMenu( QMenu* menu );
|
||||||
|
|
||||||
|
/** Attach a view menu that will be automatically fill */
|
||||||
|
void attachViewMenu( QMenu* menu );
|
||||||
|
|
||||||
|
bool isTopLevel();
|
||||||
|
void setupMenu( QMenu* menu, const std::vector<DockInDockManager*>& moveTo );
|
||||||
|
|
||||||
|
inline DockInDockManager* getManager() { return m_mgr; }
|
||||||
|
inline DockInDockWidget* getTopLevelDockWidget() { return m_topLevelDockWidget; }
|
||||||
|
|
||||||
|
inline bool canCreateNewGroups() const { return m_canCreateNewGroups; }
|
||||||
|
|
||||||
|
void dumpStatus( std::ostream& str, std::string tab = "" );
|
||||||
|
|
||||||
|
inline PerspectivesManager* getPerspectivesManager() { return m_perspectivesManager; }
|
||||||
|
|
||||||
|
void setNewPerspectiveDefaultName( const QString& defaultName );
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void autoFillAttachedViewMenu();
|
||||||
|
void createPerspective();
|
||||||
|
|
||||||
|
private:
|
||||||
|
DockInDockManager* m_mgr;
|
||||||
|
DockInDockWidget* m_topLevelDockWidget;
|
||||||
|
|
||||||
|
bool m_canCreateNewGroups;
|
||||||
|
|
||||||
|
DockInDockWidget( QWidget* parent, DockInDockWidget* topLevelDockWidget, PerspectivesManager* perspectivesManager );
|
||||||
|
|
||||||
|
PerspectivesManager* m_perspectivesManager;
|
||||||
|
QString m_newPerspectiveDefaultName;
|
||||||
|
|
||||||
|
void fillPerspectivesMenu( QMenu* menu );
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ ADS_OUT_ROOT = $${OUT_PWD}/../..
|
|||||||
|
|
||||||
QT += core gui widgets
|
QT += core gui widgets
|
||||||
|
|
||||||
TARGET = DockDepth1
|
TARGET = DockInDock
|
||||||
DESTDIR = $${ADS_OUT_ROOT}/lib
|
DESTDIR = $${ADS_OUT_ROOT}/lib
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
CONFIG += c++14
|
CONFIG += c++14
|
||||||
@ -14,13 +14,19 @@ adsBuildStatic {
|
|||||||
DEFINES += QT_DEPRECATED_WARNINGS
|
DEFINES += QT_DEPRECATED_WARNINGS
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
innertabs.cpp \
|
dockindock.cpp \
|
||||||
|
dockindockmanager.cpp \
|
||||||
|
perspectiveactions.cpp \
|
||||||
|
perspectives.cpp \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
MainWindow.cpp
|
mainframe.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
innertabs.h \
|
dockindock.h \
|
||||||
MainWindow.h
|
dockindockmanager.h \
|
||||||
|
perspectiveactions.h \
|
||||||
|
perspectives.h \
|
||||||
|
mainframe.h
|
||||||
|
|
||||||
LIBS += -L$${ADS_OUT_ROOT}/lib
|
LIBS += -L$${ADS_OUT_ROOT}/lib
|
||||||
include(../../ads.pri)
|
include(../../ads.pri)
|
359
examples/dockindock/dockindockmanager.cpp
Normal file
359
examples/dockindock/dockindockmanager.cpp
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
#include "dockindockmanager.h"
|
||||||
|
#include "dockindock.h"
|
||||||
|
|
||||||
|
#include "DockAreaWidget.h"
|
||||||
|
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QInputDialog>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
using namespace QtAdsUtl;
|
||||||
|
|
||||||
|
/////////////////////////////////////
|
||||||
|
// DockInDockManager
|
||||||
|
/////////////////////////////////////
|
||||||
|
void deleteAllChildrenToPreventLeak( ads::CDockContainerWidget* areaWidget )
|
||||||
|
{
|
||||||
|
// fix leaks: https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/307
|
||||||
|
|
||||||
|
std::vector<ads::CDockAreaWidget*> areas;
|
||||||
|
for ( int i = 0; i != areaWidget->dockAreaCount(); ++i )
|
||||||
|
{
|
||||||
|
areas.push_back( areaWidget->dockArea(i) );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> deleted;
|
||||||
|
for ( auto area : areas )
|
||||||
|
{
|
||||||
|
for ( auto widget : area->dockWidgets() )
|
||||||
|
{
|
||||||
|
ads::CDockContainerWidget* subArea = dynamic_cast<ads::CDockContainerWidget*>( widget->widget() );
|
||||||
|
if ( subArea )
|
||||||
|
deleteAllChildrenToPreventLeak( subArea );
|
||||||
|
delete widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DockInDockManager::DockInDockManager( DockInDockWidget& parent ) :
|
||||||
|
baseClass( &parent ),
|
||||||
|
m_parent( parent )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DockInDockManager::~DockInDockManager()
|
||||||
|
{
|
||||||
|
deleteAllChildrenToPreventLeak( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockManager::fillViewMenu( QMenu* menu, const std::vector<DockInDockManager*>& moveTo )
|
||||||
|
{
|
||||||
|
auto widgetsMap = dockWidgetsMap();
|
||||||
|
for ( auto iter = widgetsMap.begin(); iter != widgetsMap.end(); ++iter )
|
||||||
|
{
|
||||||
|
auto widget = iter.value()->widget();
|
||||||
|
auto action = iter.value()->toggleViewAction();
|
||||||
|
|
||||||
|
DockInDockWidget* asMgr = dynamic_cast<DockInDockWidget*>( widget );
|
||||||
|
if ( asMgr )
|
||||||
|
{
|
||||||
|
auto subMenu = menu->addMenu( iter.key() );
|
||||||
|
|
||||||
|
subMenu->addAction( action );
|
||||||
|
subMenu->addSeparator();
|
||||||
|
|
||||||
|
asMgr->setupMenu( subMenu, moveTo );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
menu->addAction(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( parent().canCreateNewGroups() )
|
||||||
|
{
|
||||||
|
// see how this works, to create it in the right place,
|
||||||
|
// and also to have load perspective work when some groups are missing
|
||||||
|
menu->addSeparator();
|
||||||
|
menu->addAction( new QtAdsUtl::CreateChildDockAction( m_parent, menu ) );
|
||||||
|
|
||||||
|
if ( parent().getTopLevelDockWidget()->getManager() != this )
|
||||||
|
menu->addAction( new QtAdsUtl::DestroyGroupAction( &m_parent, menu ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockManager::fillMoveMenu( QMenu* menu, const std::vector<DockInDockManager*>& moveTo )
|
||||||
|
{
|
||||||
|
auto widgetsMap = dockWidgetsMap();
|
||||||
|
for ( auto iter = widgetsMap.begin(); iter != widgetsMap.end(); ++iter )
|
||||||
|
{
|
||||||
|
auto subMenu = menu->addMenu( iter.key() );
|
||||||
|
|
||||||
|
for ( auto mgr : moveTo )
|
||||||
|
{
|
||||||
|
// iterate over all possible target managers
|
||||||
|
if ( mgr == this )
|
||||||
|
{
|
||||||
|
// if dock is already in mgr, no reason to move it there
|
||||||
|
}
|
||||||
|
else if ( mgr == dockInAManager( iter.value() ) )
|
||||||
|
{
|
||||||
|
// if target is the group itself, can't move it there, would make no sense
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
subMenu->addAction( new MoveDockWidgetAction( iter.value(), mgr, subMenu ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockManager::addPerspectiveRec( const QString& name )
|
||||||
|
{
|
||||||
|
std::vector<DockInDockManager*> managers = allManagers( true, true );
|
||||||
|
|
||||||
|
for ( auto child : managers )
|
||||||
|
child->addPerspective( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockManager::openPerspectiveRec( const QString& name )
|
||||||
|
{
|
||||||
|
std::vector<DockInDockManager*> managers = allManagers( true, true );
|
||||||
|
|
||||||
|
for ( auto child : managers )
|
||||||
|
child->openPerspective( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DockInDockManager::getGroupName()
|
||||||
|
{
|
||||||
|
return parent().objectName();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CHILD_PREFIX QString("Child-")
|
||||||
|
QString DockInDockManager::getPersistGroupName()
|
||||||
|
{
|
||||||
|
QString group = "Top";
|
||||||
|
if ( !getGroupName().isEmpty() )
|
||||||
|
group = CHILD_PREFIX + getGroupName();
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DockInDockManager::getGroupNameFromPersistGroupName( QString persistGroupName )
|
||||||
|
{
|
||||||
|
if ( persistGroupName.startsWith( CHILD_PREFIX ) )
|
||||||
|
{
|
||||||
|
persistGroupName = persistGroupName.mid( CHILD_PREFIX.size() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
}
|
||||||
|
return persistGroupName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockManager::loadPerspectivesRec(QSettings& Settings)
|
||||||
|
{
|
||||||
|
std::vector<DockInDockManager*> children = allManagers( true, true );
|
||||||
|
|
||||||
|
for ( auto mgr : children )
|
||||||
|
{
|
||||||
|
Settings.beginGroup(mgr->getPersistGroupName());
|
||||||
|
mgr->loadPerspectives( Settings );
|
||||||
|
Settings.endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockManager::savePerspectivesRec(QSettings& Settings) const
|
||||||
|
{
|
||||||
|
std::vector<DockInDockManager*> children = allManagers( true, true );
|
||||||
|
|
||||||
|
for ( auto mgr : children )
|
||||||
|
{
|
||||||
|
Settings.beginGroup(mgr->getPersistGroupName());
|
||||||
|
mgr->savePerspectives( Settings );
|
||||||
|
Settings.endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockManager::removePerspectivesRec()
|
||||||
|
{
|
||||||
|
std::vector<DockInDockManager*> managers = allManagers( true, true );
|
||||||
|
|
||||||
|
for ( auto child : managers )
|
||||||
|
child->removePerspectives( child->perspectiveNames() );
|
||||||
|
}
|
||||||
|
|
||||||
|
DockInDockManager* DockInDockManager::dockInAManager( ads::CDockWidget* widget )
|
||||||
|
{
|
||||||
|
DockInDockWidget* dockWidget = widget ? dynamic_cast<DockInDockWidget*>( widget->widget() ) : NULL;
|
||||||
|
return ( dockWidget ) ? dockWidget->getManager() : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockInDockManager::childManagers( std::vector<DockInDockManager*>& managers, bool rec ) const
|
||||||
|
{
|
||||||
|
auto widgets = getWidgetsInGUIOrder();
|
||||||
|
for ( auto widget : widgets )
|
||||||
|
{
|
||||||
|
DockInDockManager* asMgr = dockInAManager( widget );
|
||||||
|
if ( asMgr )
|
||||||
|
{
|
||||||
|
managers.push_back( asMgr );
|
||||||
|
if ( rec )
|
||||||
|
asMgr->childManagers( managers, rec );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<DockInDockManager*> DockInDockManager::allManagers( bool includeThis, bool rec ) const
|
||||||
|
{
|
||||||
|
std::vector<DockInDockManager*> managers;
|
||||||
|
if ( includeThis )
|
||||||
|
managers.push_back( const_cast<DockInDockManager*>(this) );
|
||||||
|
childManagers( managers, rec );
|
||||||
|
return managers;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<DockInDockManager*,ads::CDockWidget*>> DockInDockManager::allDockWidgets( bool includeThis, bool rec ) const
|
||||||
|
{
|
||||||
|
std::vector<std::pair<DockInDockManager*,ads::CDockWidget*>> widgets;
|
||||||
|
for ( auto mgr : allManagers( includeThis, rec ) )
|
||||||
|
{
|
||||||
|
for ( auto widget : mgr->getWidgetsInGUIOrder() )
|
||||||
|
widgets.push_back( std::make_pair(mgr, widget) );
|
||||||
|
}
|
||||||
|
return widgets;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString,QStringList> DockInDockManager::getGroupContents()
|
||||||
|
{
|
||||||
|
QMap<QString,QStringList> result;
|
||||||
|
std::vector<DockInDockManager*> managers = allManagers( true, true );
|
||||||
|
for ( auto mgr : managers )
|
||||||
|
{
|
||||||
|
result[mgr->getPersistGroupName()] = mgr->dockWidgetsMap().keys();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ads::CDockAreaWidget* DockInDockManager::getInsertDefaultPos()
|
||||||
|
{
|
||||||
|
ads::CDockAreaWidget* defaultPos = NULL;
|
||||||
|
if ( dockAreaCount() != 0 )
|
||||||
|
defaultPos = dockArea(dockAreaCount()-1);
|
||||||
|
return defaultPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ads::CDockWidget*> DockInDockManager::getWidgetsInGUIOrder() const
|
||||||
|
{
|
||||||
|
std::vector<ads::CDockWidget*> result;
|
||||||
|
result.reserve( dockWidgetsMap().size() );
|
||||||
|
for ( int i = 0; i != dockAreaCount(); ++i )
|
||||||
|
{
|
||||||
|
for ( auto widget : dockArea(i)->dockWidgets() )
|
||||||
|
result.push_back( widget );
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////
|
||||||
|
// CreateChildDockAction
|
||||||
|
/////////////////////////////////////
|
||||||
|
CreateChildDockAction::CreateChildDockAction( DockInDockWidget& dockInDock, QMenu* menu ) :
|
||||||
|
QAction("New group...", menu),
|
||||||
|
m_dockInDock( dockInDock )
|
||||||
|
{
|
||||||
|
connect( this, SIGNAL(triggered()), this, SLOT(createGroup()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateChildDockAction::createGroup()
|
||||||
|
{
|
||||||
|
QString name = "";
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
name = QInputDialog::getText( NULL, this->text(), "Enter group name", QLineEdit::Normal, name, &ok );
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
QString error = "";
|
||||||
|
if ( m_dockInDock.getTopLevelDockWidget() )
|
||||||
|
error = m_dockInDock.getTopLevelDockWidget()->getGroupNameError( name );
|
||||||
|
else
|
||||||
|
assert( false );
|
||||||
|
|
||||||
|
if ( error.isEmpty() )
|
||||||
|
{
|
||||||
|
ads::CDockAreaWidget* insertPos = NULL;
|
||||||
|
m_dockInDock.createGroup( name, insertPos );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMessageBox::critical( NULL, "Error", error );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////
|
||||||
|
// DestroyGroupAction
|
||||||
|
/////////////////////////////////////
|
||||||
|
DestroyGroupAction::DestroyGroupAction( DockInDockWidget* widget, QMenu* menu ) :
|
||||||
|
QAction("Destroy " + widget->getManager()->getGroupName(), menu),
|
||||||
|
m_widget( widget )
|
||||||
|
{
|
||||||
|
connect( this, SIGNAL(triggered()), this, SLOT(destroyGroup()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void DestroyGroupAction::destroyGroup()
|
||||||
|
{
|
||||||
|
m_widget->getTopLevelDockWidget()->destroyGroup( m_widget );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////
|
||||||
|
// MoveDockWidgetAction
|
||||||
|
/////////////////////////////////////
|
||||||
|
MoveDockWidgetAction::MoveDockWidgetAction( ads::CDockWidget* widget, DockInDockManager* moveTo, QMenu* menu ) :
|
||||||
|
QAction(menu),
|
||||||
|
m_widget( widget ),
|
||||||
|
m_moveTo( moveTo )
|
||||||
|
{
|
||||||
|
if ( moveTo->parent().isTopLevel() )
|
||||||
|
{
|
||||||
|
setText( "To top" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setText( "To " + moveTo->parent().objectName() );
|
||||||
|
}
|
||||||
|
connect( this, SIGNAL(triggered()), this, SLOT(move()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveDockWidgetAction::move()
|
||||||
|
{
|
||||||
|
move( m_widget, m_moveTo );
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveDockWidgetAction::move( ads::CDockWidget* widget, DockInDockManager* moveTo )
|
||||||
|
{
|
||||||
|
if ( widget && moveTo )
|
||||||
|
{
|
||||||
|
widget->dockManager()->removeDockWidget( widget );
|
||||||
|
moveTo->addDockWidget(ads::CenterDockWidgetArea, widget, moveTo->getInsertDefaultPos());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
}
|
||||||
|
}
|
96
examples/dockindock/dockindockmanager.h
Normal file
96
examples/dockindock/dockindockmanager.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DockManager.h"
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
namespace QtAdsUtl
|
||||||
|
{
|
||||||
|
|
||||||
|
class DockInDockWidget;
|
||||||
|
class DockInDockManager : public ads::CDockManager
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
typedef ads::CDockManager baseClass;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DockInDockManager( DockInDockWidget& parent );
|
||||||
|
~DockInDockManager() override;
|
||||||
|
|
||||||
|
void fillViewMenu( QMenu* menu, const std::vector<DockInDockManager*>& moveTo );
|
||||||
|
void fillMoveMenu( QMenu* menu, const std::vector<DockInDockManager*>& moveTo );
|
||||||
|
|
||||||
|
void addPerspectiveRec( const QString& name );
|
||||||
|
void openPerspectiveRec( const QString& name );
|
||||||
|
void removePerspectivesRec();
|
||||||
|
void loadPerspectivesRec(QSettings& Settings);
|
||||||
|
void savePerspectivesRec(QSettings& Settings) const;
|
||||||
|
|
||||||
|
static DockInDockManager* dockInAManager( ads::CDockWidget* widget );
|
||||||
|
|
||||||
|
inline DockInDockWidget& parent() { return m_parent; }
|
||||||
|
|
||||||
|
void childManagers( std::vector<DockInDockManager*>& managers, bool rec ) const;
|
||||||
|
std::vector<DockInDockManager*> allManagers( bool includeThis, bool rec ) const;
|
||||||
|
std::vector<std::pair<DockInDockManager*,ads::CDockWidget*>> allDockWidgets( bool includeThis, bool rec ) const;
|
||||||
|
|
||||||
|
QString getGroupName();
|
||||||
|
QString getPersistGroupName();
|
||||||
|
static QString getGroupNameFromPersistGroupName( QString persistGroupName );
|
||||||
|
|
||||||
|
QMap<QString,QStringList> getGroupContents();
|
||||||
|
|
||||||
|
ads::CDockAreaWidget* getInsertDefaultPos();
|
||||||
|
|
||||||
|
std::vector<ads::CDockWidget*> getWidgetsInGUIOrder() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DockInDockWidget& m_parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CreateChildDockAction : public QAction
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CreateChildDockAction( DockInDockWidget& dockInDock, QMenu* menu );
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void createGroup();
|
||||||
|
|
||||||
|
private:
|
||||||
|
DockInDockWidget& m_dockInDock;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DestroyGroupAction : public QAction
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
DestroyGroupAction( DockInDockWidget* widget, QMenu* menu );
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void destroyGroup();
|
||||||
|
|
||||||
|
private:
|
||||||
|
DockInDockWidget* m_widget;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MoveDockWidgetAction : public QAction
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
MoveDockWidgetAction( ads::CDockWidget* widget, DockInDockManager* moveTo, QMenu* menu );
|
||||||
|
|
||||||
|
static void move( ads::CDockWidget* widget, DockInDockManager* moveTo );
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void move();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ads::CDockWidget* m_widget;
|
||||||
|
DockInDockManager* m_moveTo;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
76
examples/dockindock/mainframe.cpp
Normal file
76
examples/dockindock/mainframe.cpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#include "mainframe.h"
|
||||||
|
|
||||||
|
#include "dockindock.h"
|
||||||
|
#include "perspectives.h"
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QMenuBar>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget *parent) :
|
||||||
|
QMainWindow(parent),
|
||||||
|
m_perspectivesManager( new QtAdsUtl::PerspectivesManager( "persist" ) )
|
||||||
|
{
|
||||||
|
resize( 400, 400 );
|
||||||
|
|
||||||
|
setCentralWidget( m_dockManager = new QtAdsUtl::DockInDockWidget(this,true,m_perspectivesManager.get()) );
|
||||||
|
|
||||||
|
m_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. ");
|
||||||
|
|
||||||
|
previousDockWidget = m_dockManager->addTabWidget( l, "Top label " + QString::number(i), previousDockWidget );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lastTopLevelDock = previousDockWidget;
|
||||||
|
|
||||||
|
for ( int j = 0; j != 2; ++j )
|
||||||
|
{
|
||||||
|
QtAdsUtl::DockInDockWidget* groupManager = m_dockManager->createGroup( "Group " + QString::number(j), lastTopLevelDock );
|
||||||
|
|
||||||
|
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. ");
|
||||||
|
|
||||||
|
previousDockWidget = groupManager->addTabWidget( l, "ZInner " + QString::number(j) + "/" + QString::number(i), previousDockWidget );
|
||||||
|
}
|
||||||
|
|
||||||
|
// create sub-group
|
||||||
|
auto subGroup = groupManager->createGroup( "SubGroup " + QString::number(j), previousDockWidget );
|
||||||
|
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. ");
|
||||||
|
|
||||||
|
previousDockWidget = subGroup->addTabWidget( l, "SubInner " + QString::number(j) + "/" + QString::number(i), previousDockWidget );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_perspectivesManager->loadPerspectives();
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow()
|
||||||
|
{
|
||||||
|
m_perspectivesManager->savePerspectives();
|
||||||
|
}
|
||||||
|
|
30
examples/dockindock/mainframe.h
Normal file
30
examples/dockindock/mainframe.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QAction>
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
namespace QtAdsUtl
|
||||||
|
{
|
||||||
|
class DockInDockWidget;
|
||||||
|
class PerspectivesManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MainWindow(QWidget *parent = 0);
|
||||||
|
~MainWindow();
|
||||||
|
|
||||||
|
QtAdsUtl::DockInDockWidget* m_dockManager;
|
||||||
|
std::unique_ptr<QtAdsUtl::PerspectivesManager> m_perspectivesManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
39
examples/dockindock/perspectiveactions.cpp
Normal file
39
examples/dockindock/perspectiveactions.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include "perspectiveactions.h"
|
||||||
|
#include "dockindock.h"
|
||||||
|
#include "perspectives.h"
|
||||||
|
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
|
using namespace QtAdsUtl;
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// LoadPerspectiveAction
|
||||||
|
//////////////////////////////
|
||||||
|
LoadPerspectiveAction::LoadPerspectiveAction( QMenu* parent, const QString& name, QtAdsUtl::DockInDockWidget& dockManager ) :
|
||||||
|
QAction( name, parent ),
|
||||||
|
name( name ),
|
||||||
|
dockManager( dockManager )
|
||||||
|
{
|
||||||
|
connect( this, SIGNAL(triggered()), this, SLOT(load()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadPerspectiveAction::load()
|
||||||
|
{
|
||||||
|
dockManager.getPerspectivesManager()->openPerspective( name, dockManager );
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// RemovePerspectiveAction
|
||||||
|
//////////////////////////////
|
||||||
|
RemovePerspectiveAction::RemovePerspectiveAction( QMenu* parent, const QString& name, QtAdsUtl::DockInDockWidget& dockManager ) :
|
||||||
|
QAction( name, parent ),
|
||||||
|
name( name ),
|
||||||
|
dockManager( dockManager )
|
||||||
|
{
|
||||||
|
connect( this, SIGNAL(triggered()), this, SLOT(remove()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemovePerspectiveAction::remove()
|
||||||
|
{
|
||||||
|
dockManager.getPerspectivesManager()->removePerspective( name );
|
||||||
|
}
|
38
examples/dockindock/perspectiveactions.h
Normal file
38
examples/dockindock/perspectiveactions.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
|
||||||
|
namespace QtAdsUtl
|
||||||
|
{
|
||||||
|
|
||||||
|
class DockInDockWidget;
|
||||||
|
class LoadPerspectiveAction : public QAction
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
LoadPerspectiveAction( QMenu* parent, const QString& name, QtAdsUtl::DockInDockWidget& dockManager );
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void load();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString name;
|
||||||
|
QtAdsUtl::DockInDockWidget& dockManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RemovePerspectiveAction : public QAction
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
RemovePerspectiveAction( QMenu* parent, const QString& name, QtAdsUtl::DockInDockWidget& dockManager );
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void remove();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString name;
|
||||||
|
QtAdsUtl::DockInDockWidget& dockManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
278
examples/dockindock/perspectives.cpp
Normal file
278
examples/dockindock/perspectives.cpp
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
#include "perspectives.h"
|
||||||
|
#include "dockindock.h"
|
||||||
|
#include "dockindockmanager.h"
|
||||||
|
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define GROUP_PREFIX QString("Group")
|
||||||
|
|
||||||
|
using namespace QtAdsUtl;
|
||||||
|
|
||||||
|
PerspectivesManager::PerspectivesManager( const QString& perspectivesFolder ) :
|
||||||
|
m_perspectivesFolder( perspectivesFolder )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PerspectivesManager::~PerspectivesManager()
|
||||||
|
{
|
||||||
|
// remove temp files:
|
||||||
|
for ( auto perspective : m_perspectives )
|
||||||
|
{
|
||||||
|
QString fileName = perspective.settings->fileName();
|
||||||
|
perspective.settings.reset();
|
||||||
|
QFile::remove(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QStringList PerspectivesManager::perspectiveNames() const
|
||||||
|
{
|
||||||
|
return m_perspectives.keys();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PerspectivesManager::addPerspective( const QString& name, DockInDockWidget& widget )
|
||||||
|
{
|
||||||
|
if ( !m_perspectivesFolder.isEmpty() )
|
||||||
|
{
|
||||||
|
m_perspectives[name].settings = getSettingsObject( getSettingsFileName( name, true ) );
|
||||||
|
m_perspectives[name].groups = widget.getManager()->getGroupContents();
|
||||||
|
|
||||||
|
// save perspective internally
|
||||||
|
widget.getManager()->addPerspectiveRec( name );
|
||||||
|
// store it in QSettings object
|
||||||
|
widget.getManager()->savePerspectivesRec( *(m_perspectives[name].settings) );
|
||||||
|
// remove internal perspectives
|
||||||
|
widget.getManager()->removePerspectives( widget.getManager()->perspectiveNames() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
emit perspectivesListChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ads::CDockWidget* findWidget( QString name, const std::vector<DockInDockManager*>& managers )
|
||||||
|
{
|
||||||
|
for ( auto mgr : managers )
|
||||||
|
{
|
||||||
|
auto widget = mgr->findDockWidget(name);
|
||||||
|
if ( widget )
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PerspectivesManager::openPerspective( const QString& name, DockInDockWidget& widget )
|
||||||
|
{
|
||||||
|
assert( widget.getTopLevelDockWidget() == &widget );
|
||||||
|
|
||||||
|
if ( !m_perspectivesFolder.isEmpty() )
|
||||||
|
{
|
||||||
|
if ( m_perspectives.contains( name ) )
|
||||||
|
{
|
||||||
|
emit openingPerspective();
|
||||||
|
|
||||||
|
if ( widget.canCreateNewGroups() )
|
||||||
|
{
|
||||||
|
auto curGroups = widget.getManager()->allManagers(true,true);
|
||||||
|
for ( auto group : m_perspectives[name].groups.keys() )
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for ( auto curgroup : curGroups )
|
||||||
|
{
|
||||||
|
if ( curgroup->getPersistGroupName() == group )
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !found )
|
||||||
|
{
|
||||||
|
group = DockInDockManager::getGroupNameFromPersistGroupName( group );
|
||||||
|
|
||||||
|
// restore group in file but not in GUI yet
|
||||||
|
ads::CDockAreaWidget* insertPos = NULL;
|
||||||
|
widget.createGroup( group, insertPos );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curGroups = widget.getManager()->allManagers(false,true);
|
||||||
|
for ( auto curgroup : curGroups )
|
||||||
|
{
|
||||||
|
if ( !m_perspectives[name].groups.keys().contains( curgroup->getPersistGroupName() ) )
|
||||||
|
{
|
||||||
|
widget.destroyGroup( &curgroup->parent() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto managers = widget.getManager()->allManagers(true,true);
|
||||||
|
for ( auto group : m_perspectives[name].groups.keys() )
|
||||||
|
{
|
||||||
|
for ( auto mgr : managers )
|
||||||
|
{
|
||||||
|
if ( mgr->getPersistGroupName() == group )
|
||||||
|
{
|
||||||
|
for ( QString widgetName : m_perspectives[name].groups[group] )
|
||||||
|
{
|
||||||
|
ads::CDockWidget* widget = findWidget( widgetName, { mgr } );
|
||||||
|
if ( widget )
|
||||||
|
{
|
||||||
|
// OK, widget is already in the good manager!
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
widget = findWidget( widgetName, managers );
|
||||||
|
if ( widget )
|
||||||
|
{
|
||||||
|
// move dock widget in the same group as it used to be when perspective was saved
|
||||||
|
// this guarantee load/open perspectives will work smartly
|
||||||
|
MoveDockWidgetAction::move( widget, mgr );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// internally load perspectives from QSettings
|
||||||
|
widget.getManager()->loadPerspectivesRec( *(m_perspectives[name].settings) );
|
||||||
|
// load perspective (update GUI)
|
||||||
|
widget.getManager()->openPerspectiveRec( name );
|
||||||
|
// remove internal perspectives
|
||||||
|
widget.getManager()->removePerspectives( widget.getManager()->perspectiveNames() );
|
||||||
|
|
||||||
|
emit openedPerspective();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PerspectivesManager::removePerspectives()
|
||||||
|
{
|
||||||
|
m_perspectives.clear();
|
||||||
|
emit perspectivesListChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PerspectivesManager::removePerspective( const QString& name )
|
||||||
|
{
|
||||||
|
m_perspectives.remove( name );
|
||||||
|
emit perspectivesListChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PerspectivesManager::getSettingsFileName( const QString& perspective, bool temp ) const
|
||||||
|
{
|
||||||
|
auto name = ( perspective.isEmpty() ) ? "perspectives.ini" : "perspective_" + perspective + (temp?".tmp":".ini");
|
||||||
|
|
||||||
|
return m_perspectivesFolder + "/" + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<QSettings> PerspectivesManager::getSettingsObject( const QString& filePath ) const
|
||||||
|
{
|
||||||
|
return std::make_shared<QSettings>(filePath, QSettings::IniFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PerspectivesManager::loadPerspectives()
|
||||||
|
{
|
||||||
|
if ( !m_perspectivesFolder.isEmpty() )
|
||||||
|
{
|
||||||
|
QDir().mkpath( m_perspectivesFolder );
|
||||||
|
|
||||||
|
m_perspectives.clear();
|
||||||
|
|
||||||
|
auto mainSettings = getSettingsObject( getSettingsFileName( "", false ) );
|
||||||
|
std::string debug = mainSettings->fileName().toStdString();
|
||||||
|
|
||||||
|
int Size = mainSettings->beginReadArray("Perspectives");
|
||||||
|
|
||||||
|
for (int i = 0; i < Size; ++i)
|
||||||
|
{
|
||||||
|
mainSettings->setArrayIndex(i);
|
||||||
|
QString perspective = mainSettings->value("Name").toString();
|
||||||
|
|
||||||
|
if ( !perspective.isEmpty() )
|
||||||
|
{
|
||||||
|
// load perspective file:
|
||||||
|
auto toLoad = getSettingsFileName( perspective, false );
|
||||||
|
auto loaded = getSettingsFileName( perspective, true );
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
std::string debug1 = loaded.toStdString();
|
||||||
|
std::string debug2 = toLoad.toStdString();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QFile::remove( loaded );
|
||||||
|
if ( !QFile::copy( toLoad, loaded ) )
|
||||||
|
assert( false );
|
||||||
|
|
||||||
|
m_perspectives[perspective].settings = getSettingsObject( loaded );
|
||||||
|
|
||||||
|
// load group info:
|
||||||
|
mainSettings->beginGroup(GROUP_PREFIX);
|
||||||
|
for ( auto key : mainSettings->allKeys() )
|
||||||
|
m_perspectives[perspective].groups[key] = mainSettings->value( key ).toStringList();
|
||||||
|
mainSettings->endGroup();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mainSettings->endArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
emit perspectivesListChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PerspectivesManager::savePerspectives() const
|
||||||
|
{
|
||||||
|
if ( !m_perspectivesFolder.isEmpty() )
|
||||||
|
{
|
||||||
|
auto mainSettings = getSettingsObject( getSettingsFileName( "", false ) );
|
||||||
|
|
||||||
|
// Save list of perspective and group organization
|
||||||
|
mainSettings->beginWriteArray("Perspectives", m_perspectives.size());
|
||||||
|
int i = 0;
|
||||||
|
for ( auto perspective : m_perspectives.keys() )
|
||||||
|
{
|
||||||
|
mainSettings->setArrayIndex(i);
|
||||||
|
mainSettings->setValue("Name", perspective);
|
||||||
|
mainSettings->beginGroup(GROUP_PREFIX);
|
||||||
|
for ( auto group : m_perspectives[perspective].groups.keys() )
|
||||||
|
{
|
||||||
|
mainSettings->setValue( group, m_perspectives[perspective].groups[group] );
|
||||||
|
}
|
||||||
|
mainSettings->endGroup();
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
mainSettings->endArray();
|
||||||
|
|
||||||
|
// Save perspectives themselves
|
||||||
|
for ( auto perspectiveName : m_perspectives.keys() )
|
||||||
|
{
|
||||||
|
auto toSave = getSettingsFileName( perspectiveName, false );
|
||||||
|
QSettings& settings = *(m_perspectives[perspectiveName].settings);
|
||||||
|
settings.sync();
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
std::string debug1 = settings.fileName().toStdString();
|
||||||
|
std::string debug2 = toSave.toStdString();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QFile::remove( toSave );
|
||||||
|
if ( !QFile::copy( settings.fileName(), toSave ) )
|
||||||
|
assert( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
59
examples/dockindock/perspectives.h
Normal file
59
examples/dockindock/perspectives.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class QMenu;
|
||||||
|
class QSettings;
|
||||||
|
|
||||||
|
namespace QtAdsUtl
|
||||||
|
{
|
||||||
|
|
||||||
|
class DockInDockWidget;
|
||||||
|
class PerspectivesManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
PerspectivesManager( const QString& perspectivesFolder );
|
||||||
|
virtual ~PerspectivesManager();
|
||||||
|
|
||||||
|
QStringList perspectiveNames() const;
|
||||||
|
|
||||||
|
void addPerspective( const QString& name, DockInDockWidget& widget );
|
||||||
|
void openPerspective( const QString& name, DockInDockWidget& widget );
|
||||||
|
void removePerspectives();
|
||||||
|
void removePerspective( const QString& name );
|
||||||
|
|
||||||
|
void loadPerspectives();
|
||||||
|
void savePerspectives() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void perspectivesListChanged();
|
||||||
|
void openingPerspective();
|
||||||
|
void openedPerspective();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Partially bypass ADS perspective management, store list here
|
||||||
|
// and then ADS will only have one perspective loaded
|
||||||
|
// this is because all docking widgets must exist when a perspective is loaded
|
||||||
|
// we will guarantee that!
|
||||||
|
class PerspectiveInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::shared_ptr<QSettings> settings;
|
||||||
|
QMap<QString,QStringList> groups;
|
||||||
|
};
|
||||||
|
QMap<QString,PerspectiveInfo> m_perspectives;
|
||||||
|
|
||||||
|
QString m_perspectivesFolder;
|
||||||
|
QString getSettingsFileName( const QString& perspective, bool temp ) const;
|
||||||
|
std::shared_ptr<QSettings> getSettingsObject( const QString& filePath ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -6,4 +6,4 @@ SUBDIRS = \
|
|||||||
sidebar \
|
sidebar \
|
||||||
deleteonclose \
|
deleteonclose \
|
||||||
emptydockarea \
|
emptydockarea \
|
||||||
dockdepth1
|
dockindock
|
||||||
|
Loading…
Reference in New Issue
Block a user