Skip to content

Commit 0e8e563

Browse files
authored
Add dockindock example (#308)
* Add dockdepth1 example * Fix compilation (include assert.h) * Replace dockdepth1 by dockindock
1 parent 2f041a0 commit 0e8e563

14 files changed

+1427
-1
lines changed

examples/dockindock/CMakeLists.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
cmake_minimum_required(VERSION 3.5)
2+
project(ads_example_simple VERSION ${VERSION_SHORT})
3+
find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED)
4+
set(CMAKE_INCLUDE_CURRENT_DIR ON)
5+
add_executable(DockInDock WIN32
6+
dockindock.cpp
7+
dockindockmanager.cpp
8+
perspectiveactions.cpp
9+
perspectives.cpp
10+
main.cpp
11+
mainframe.cpp
12+
)
13+
target_include_directories(SimpleExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
14+
target_link_libraries(SimpleExample PRIVATE qtadvanceddocking)
15+
target_link_libraries(SimpleExample PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets)
16+
set_target_properties(SimpleExample PROPERTIES
17+
AUTOMOC ON
18+
AUTORCC ON
19+
AUTOUIC ON
20+
CXX_STANDARD 14
21+
CXX_STANDARD_REQUIRED ON
22+
CXX_EXTENSIONS OFF
23+
VERSION ${VERSION_SHORT}
24+
EXPORT_NAME "Qt Advanced Docking System Simple Example"
25+
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
26+
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
27+
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/bin"
28+
)

examples/dockindock/dockindock.cpp

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
#include "dockindock.h"
2+
#include "perspectives.h"
3+
#include "dockindockmanager.h"
4+
#include "perspectiveactions.h"
5+
6+
#include <QMenu>
7+
#include <QDir>
8+
#include <QVBoxLayout>
9+
#include <QMainWindow>
10+
#include <QMessageBox>
11+
#include <QInputDialog>
12+
13+
#include <set>
14+
#include <assert.h>
15+
16+
using namespace QtAdsUtl;
17+
18+
DockInDockWidget::DockInDockWidget( QWidget* parent, bool canCreateNewGroups, PerspectivesManager* perspectivesManager ) :
19+
DockInDockWidget( parent, (DockInDockWidget*)NULL, perspectivesManager )
20+
{
21+
m_canCreateNewGroups = canCreateNewGroups;
22+
m_topLevelDockWidget = this;
23+
}
24+
25+
DockInDockWidget::DockInDockWidget( QWidget* parent, DockInDockWidget* topLevelDockWidget, PerspectivesManager* perspectivesManager ) :
26+
baseClass( parent ),
27+
m_topLevelDockWidget( topLevelDockWidget ),
28+
m_canCreateNewGroups( (topLevelDockWidget) ? topLevelDockWidget->m_canCreateNewGroups : false ),
29+
m_perspectivesManager( perspectivesManager )
30+
{
31+
QVBoxLayout* layout = new QVBoxLayout(this);
32+
layout->setContentsMargins( 0,0,0,0 );
33+
layout->addWidget( m_mgr = new DockInDockManager(*this) );
34+
}
35+
36+
DockInDockWidget::~DockInDockWidget()
37+
{
38+
39+
}
40+
41+
ads::CDockAreaWidget* DockInDockWidget::addTabWidget( QWidget* widget, const QString& name, ads::CDockAreaWidget* after )
42+
{
43+
return addTabWidget( widget, name, QIcon(), after );
44+
}
45+
46+
ads::CDockAreaWidget* DockInDockWidget::addTabWidget( QWidget* widget, const QString& name, QIcon icon, ads::CDockAreaWidget* after )
47+
{
48+
for ( auto existing : getTopLevelDockWidget()->getManager()->allDockWidgets(true,true) )
49+
{
50+
if ( existing.second->objectName() == name )
51+
{
52+
QMessageBox::critical( this, "Error", "Name '" + name + "' already in use" );
53+
return NULL;
54+
}
55+
}
56+
57+
ads::CDockWidget* DockWidget = new ads::CDockWidget(name);
58+
DockWidget->setWidget(widget);
59+
DockWidget->setIcon( icon );
60+
61+
// Add the dock widget to the top dock widget area
62+
return m_mgr->addDockWidget(ads::CenterDockWidgetArea, DockWidget, after);
63+
}
64+
65+
bool DockInDockWidget::isTopLevel()
66+
{
67+
return objectName().isEmpty();
68+
}
69+
70+
QString DockInDockWidget::getGroupNameError( const QString& groupName )
71+
{
72+
if ( groupName.isEmpty() )
73+
{
74+
return "Group must have a non-empty name";
75+
}
76+
77+
std::vector<DockInDockManager*> dockManagers = m_mgr->allManagers( true, true );
78+
for ( auto mgr : dockManagers )
79+
{
80+
if ( mgr->getGroupName() == groupName )
81+
return "Group name '" + groupName + "' already used";
82+
}
83+
84+
return "";
85+
}
86+
87+
DockInDockWidget* DockInDockWidget::createGroup( const QString& groupName, ads::CDockAreaWidget*& insertPos )
88+
{
89+
return createGroup( groupName, QIcon(), insertPos );
90+
}
91+
92+
DockInDockWidget* DockInDockWidget::createGroup( const QString& groupName, QIcon icon, ads::CDockAreaWidget*& insertPos )
93+
{
94+
QString error = getGroupNameError( groupName );
95+
if ( !error.isEmpty() )
96+
{
97+
QMessageBox::critical( NULL, "Error", error );
98+
return NULL;
99+
}
100+
101+
DockInDockWidget* child = new DockInDockWidget( this, m_topLevelDockWidget, m_perspectivesManager );
102+
child->setObjectName( groupName );
103+
104+
ads::CDockWidget* DockWidget = new ads::CDockWidget(groupName);
105+
DockWidget->setWidget(child);
106+
DockWidget->setIcon(icon);
107+
108+
insertPos = m_mgr->addDockWidget(ads::CenterDockWidgetArea, DockWidget, insertPos);
109+
110+
return child;
111+
}
112+
113+
void DockInDockWidget::destroyGroup( DockInDockWidget* widgetToRemove )
114+
{
115+
auto topLevelWidget = widgetToRemove->getTopLevelDockWidget();
116+
117+
if ( topLevelWidget && topLevelWidget != widgetToRemove )
118+
{
119+
// reaffect all child docks to top-level
120+
for ( auto dockwidget : widgetToRemove->getManager()->getWidgetsInGUIOrder() ) // don't use allDockWidgets to preserve sub-groups
121+
{
122+
MoveDockWidgetAction::move( dockwidget, topLevelWidget->getManager() );
123+
}
124+
assert( widgetToRemove->getManager()->allDockWidgets( true, true ).empty() );
125+
126+
// find widget's parent:
127+
for ( auto dockwidget : topLevelWidget->getManager()->allDockWidgets( true, true ) )
128+
{
129+
if ( dockwidget.second->widget() == widgetToRemove )
130+
{
131+
dockwidget.first->removeDockWidget( dockwidget.second );
132+
delete dockwidget.second;
133+
//delete widgetToRemove; automatically deleted when dockWidget is deleted
134+
widgetToRemove = NULL;
135+
break;
136+
}
137+
}
138+
139+
assert( widgetToRemove == NULL );
140+
}
141+
else
142+
{
143+
assert( false );
144+
}
145+
}
146+
147+
void DockInDockWidget::attachViewMenu( QMenu* menu )
148+
{
149+
connect( menu, SIGNAL(aboutToShow()), this, SLOT(autoFillAttachedViewMenu()) );
150+
}
151+
152+
void DockInDockWidget::autoFillAttachedViewMenu()
153+
{
154+
QMenu* menu = dynamic_cast<QMenu*>( QObject::sender() );
155+
156+
if ( menu )
157+
{
158+
menu->clear();
159+
setupViewMenu( menu );
160+
}
161+
else
162+
{
163+
assert( false );
164+
}
165+
}
166+
167+
void DockInDockWidget::setupViewMenu( QMenu* menu )
168+
{
169+
std::vector<DockInDockManager*> dockManagers = m_mgr->allManagers( true, true );
170+
171+
bool hasPerspectivesMenu = false;
172+
if ( getTopLevelDockWidget() == this )
173+
hasPerspectivesMenu = (m_perspectivesManager != NULL);
174+
else
175+
assert( false );
176+
177+
QMenu* organize = menu;
178+
if ( hasPerspectivesMenu )
179+
organize = menu->addMenu( "Organize" );
180+
181+
setupMenu( organize, dockManagers );
182+
183+
if ( hasPerspectivesMenu )
184+
{
185+
QMenu* perspectives = menu->addMenu( "Perspectives" );
186+
fillPerspectivesMenu( perspectives );
187+
}
188+
}
189+
190+
void DockInDockWidget::setupMenu( QMenu* menu, const std::vector<DockInDockManager*>& moveTo )
191+
{
192+
m_mgr->fillViewMenu( menu, moveTo );
193+
menu->addSeparator();
194+
auto moveMenu = menu->addMenu( "Move" );
195+
m_mgr->fillMoveMenu( moveMenu, moveTo );
196+
}
197+
198+
void DockInDockWidget::fillPerspectivesMenu( QMenu* menu )
199+
{
200+
menu->addAction( "Create perspective...", this, SLOT(createPerspective()) );
201+
202+
QStringList perspectiveNames;
203+
if ( m_perspectivesManager )
204+
perspectiveNames = m_perspectivesManager->perspectiveNames();
205+
206+
if ( !perspectiveNames.isEmpty() )
207+
{
208+
QMenu* load = menu->addMenu( "Load perspective" );
209+
for ( auto name : perspectiveNames )
210+
load->addAction( new LoadPerspectiveAction( load, name, *this ) );
211+
QMenu* remove = menu->addMenu( "Remove perspective" );
212+
for ( auto name : perspectiveNames )
213+
remove->addAction( new RemovePerspectiveAction( remove, name, *this ) );
214+
}
215+
}
216+
217+
void DockInDockWidget::setNewPerspectiveDefaultName( const QString& defaultName )
218+
{
219+
m_newPerspectiveDefaultName = defaultName;
220+
}
221+
222+
void DockInDockWidget::createPerspective()
223+
{
224+
if ( !m_perspectivesManager )
225+
return;
226+
227+
QString name = m_newPerspectiveDefaultName;
228+
if ( !m_newPerspectiveDefaultName.isEmpty() )
229+
{
230+
int index = 2;
231+
while ( m_perspectivesManager->perspectiveNames().contains( name ) )
232+
{
233+
name = m_newPerspectiveDefaultName + " (" + QString::number(index) + ")";
234+
++index;
235+
}
236+
}
237+
238+
while ( true )
239+
{
240+
bool ok = false;
241+
name = QInputDialog::getText( NULL, "Create perspective", "Enter perspective name", QLineEdit::Normal, name, &ok );
242+
if ( ok )
243+
{
244+
if ( name.isEmpty() )
245+
{
246+
QMessageBox::critical( NULL, "Error", "Perspective name cannot be empty" );
247+
continue;
248+
}
249+
else if ( m_perspectivesManager->perspectiveNames().contains( name ) )
250+
{
251+
if ( QMessageBox::critical( NULL, "Error", "Perspective '" + name + "' already exists, overwrite it?", QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) == QMessageBox::No )
252+
continue;
253+
}
254+
255+
m_perspectivesManager->addPerspective( name, *this );
256+
break;
257+
}
258+
else
259+
{
260+
break;
261+
}
262+
}
263+
}
264+
265+
static void dumpStatus( std::ostream& str, ads::CDockWidget* widget, const std::string& tab, std::string suffix )
266+
{
267+
DockInDockManager* asMgr = DockInDockManager::dockInAManager( widget );
268+
if ( asMgr )
269+
{
270+
asMgr->parent().dumpStatus( str, tab );
271+
}
272+
else
273+
{
274+
str << tab << widget->objectName().toStdString() << suffix << std::endl;
275+
}
276+
}
277+
278+
void DockInDockWidget::dumpStatus( std::ostream& str, std::string tab )
279+
{
280+
str << tab << "Group: " << getManager()->getGroupName().toStdString() << std::endl;
281+
tab += " ";
282+
std::set<ads::CDockWidget*> visibleWidgets;
283+
for ( auto widget : getManager()->getWidgetsInGUIOrder() )
284+
{
285+
visibleWidgets.insert( widget );
286+
::dumpStatus( str, widget, tab, "" );
287+
}
288+
289+
for ( auto closed : getManager()->dockWidgetsMap() )
290+
{
291+
if ( visibleWidgets.find( closed ) == visibleWidgets.end() )
292+
{
293+
::dumpStatus( str, closed, tab, " (closed)" );
294+
}
295+
}
296+
}

0 commit comments

Comments
 (0)