Revision: 76174
          http://sourceforge.net/p/brlcad/code/76174
Author:   starseeker
Date:     2020-06-22 02:33:25 +0000 (Mon, 22 Jun 2020)
Log Message:
-----------
Replace QDockWidget with 
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System for improved 
docking behavior.  Still doesn't give us full top level windows when we undock, 
but the improved flexibility and feature set of this system looks like it will 
still be very much worthwhile.

Modified Paths:
--------------
    brlcad/branches/qtged/src/qged/CMakeLists.txt
    brlcad/branches/qtged/src/qged/TODO.qt
    brlcad/branches/qtged/src/qged/main.cxx
    brlcad/branches/qtged/src/qged/main_window.cxx
    brlcad/branches/qtged/src/qged/main_window.h

Added Paths:
-----------
    brlcad/branches/qtged/src/qged/qtads/
    brlcad/branches/qtged/src/qged/qtads/CMakeLists.txt
    brlcad/branches/qtged/src/qged/qtads/DockAreaTabBar.cpp
    brlcad/branches/qtged/src/qged/qtads/DockAreaTabBar.h
    brlcad/branches/qtged/src/qged/qtads/DockAreaTitleBar.cpp
    brlcad/branches/qtged/src/qged/qtads/DockAreaTitleBar.h
    brlcad/branches/qtged/src/qged/qtads/DockAreaTitleBar_p.h
    brlcad/branches/qtged/src/qged/qtads/DockAreaWidget.cpp
    brlcad/branches/qtged/src/qged/qtads/DockAreaWidget.h
    brlcad/branches/qtged/src/qged/qtads/DockComponentsFactory.cpp
    brlcad/branches/qtged/src/qged/qtads/DockComponentsFactory.h
    brlcad/branches/qtged/src/qged/qtads/DockContainerWidget.cpp
    brlcad/branches/qtged/src/qged/qtads/DockContainerWidget.h
    brlcad/branches/qtged/src/qged/qtads/DockFocusController.cpp
    brlcad/branches/qtged/src/qged/qtads/DockFocusController.h
    brlcad/branches/qtged/src/qged/qtads/DockManager.cpp
    brlcad/branches/qtged/src/qged/qtads/DockManager.h
    brlcad/branches/qtged/src/qged/qtads/DockOverlay.cpp
    brlcad/branches/qtged/src/qged/qtads/DockOverlay.h
    brlcad/branches/qtged/src/qged/qtads/DockSplitter.cpp
    brlcad/branches/qtged/src/qged/qtads/DockSplitter.h
    brlcad/branches/qtged/src/qged/qtads/DockWidget.cpp
    brlcad/branches/qtged/src/qged/qtads/DockWidget.h
    brlcad/branches/qtged/src/qged/qtads/DockWidgetTab.cpp
    brlcad/branches/qtged/src/qged/qtads/DockWidgetTab.h
    brlcad/branches/qtged/src/qged/qtads/DockingStateReader.cpp
    brlcad/branches/qtged/src/qged/qtads/DockingStateReader.h
    brlcad/branches/qtged/src/qged/qtads/ElidingLabel.cpp
    brlcad/branches/qtged/src/qged/qtads/ElidingLabel.h
    brlcad/branches/qtged/src/qged/qtads/FloatingDockContainer.cpp
    brlcad/branches/qtged/src/qged/qtads/FloatingDockContainer.h
    brlcad/branches/qtged/src/qged/qtads/FloatingDragPreview.cpp
    brlcad/branches/qtged/src/qged/qtads/FloatingDragPreview.h
    brlcad/branches/qtged/src/qged/qtads/IconProvider.cpp
    brlcad/branches/qtged/src/qged/qtads/IconProvider.h
    brlcad/branches/qtged/src/qged/qtads/LICENSE
    brlcad/branches/qtged/src/qged/qtads/README.md
    brlcad/branches/qtged/src/qged/qtads/ads.qrc
    brlcad/branches/qtged/src/qged/qtads/ads_globals.cpp
    brlcad/branches/qtged/src/qged/qtads/ads_globals.h
    brlcad/branches/qtged/src/qged/qtads/examples/
    brlcad/branches/qtged/src/qged/qtads/examples/CMakeLists.txt
    brlcad/branches/qtged/src/qged/qtads/examples/deleteonclose/
    brlcad/branches/qtged/src/qged/qtads/examples/deleteonclose/CMakeLists.txt
    brlcad/branches/qtged/src/qged/qtads/examples/deleteonclose/main.cpp
    brlcad/branches/qtged/src/qged/qtads/examples/demo/
    brlcad/branches/qtged/src/qged/qtads/examples/demo/CMakeLists.txt
    brlcad/branches/qtged/src/qged/qtads/examples/demo/MainWindow.cpp
    brlcad/branches/qtged/src/qged/qtads/examples/demo/MainWindow.h
    brlcad/branches/qtged/src/qged/qtads/examples/demo/StatusDialog.cpp
    brlcad/branches/qtged/src/qged/qtads/examples/demo/StatusDialog.h
    brlcad/branches/qtged/src/qged/qtads/examples/demo/StatusDialog.ui
    brlcad/branches/qtged/src/qged/qtads/examples/demo/app.css
    brlcad/branches/qtged/src/qged/qtads/examples/demo/demo.qrc
    brlcad/branches/qtged/src/qged/qtads/examples/demo/images/
    
brlcad/branches/qtged/src/qged/qtads/examples/demo/images/create_floating_editor.svg
    
brlcad/branches/qtged/src/qged/qtads/examples/demo/images/create_floating_table.svg
    
brlcad/branches/qtged/src/qged/qtads/examples/demo/images/custom-menu-button.svg
    brlcad/branches/qtged/src/qged/qtads/examples/demo/images/date_range.svg
    brlcad/branches/qtged/src/qged/qtads/examples/demo/images/docked_editor.svg
    brlcad/branches/qtged/src/qged/qtads/examples/demo/images/edit.svg
    brlcad/branches/qtged/src/qged/qtads/examples/demo/images/folder.svg
    brlcad/branches/qtged/src/qged/qtads/examples/demo/images/folder_open.svg
    brlcad/branches/qtged/src/qged/qtads/examples/demo/images/fullscreen.svg
    brlcad/branches/qtged/src/qged/qtads/examples/demo/images/grid_on.svg
    brlcad/branches/qtged/src/qged/qtads/examples/demo/images/help_outline.svg
    
brlcad/branches/qtged/src/qged/qtads/examples/demo/images/material_icons_license.txt
    brlcad/branches/qtged/src/qged/qtads/examples/demo/images/note_add.svg
    
brlcad/branches/qtged/src/qged/qtads/examples/demo/images/picture_in_picture.svg
    brlcad/branches/qtged/src/qged/qtads/examples/demo/images/plus.svg
    brlcad/branches/qtged/src/qged/qtads/examples/demo/images/restore.svg
    brlcad/branches/qtged/src/qged/qtads/examples/demo/images/save.svg
    brlcad/branches/qtged/src/qged/qtads/examples/demo/main.cpp
    brlcad/branches/qtged/src/qged/qtads/examples/demo/mainwindow.ui
    brlcad/branches/qtged/src/qged/qtads/examples/sidebar/
    brlcad/branches/qtged/src/qged/qtads/examples/sidebar/CMakeLists.txt
    brlcad/branches/qtged/src/qged/qtads/examples/sidebar/MainWindow.cpp
    brlcad/branches/qtged/src/qged/qtads/examples/sidebar/MainWindow.h
    brlcad/branches/qtged/src/qged/qtads/examples/sidebar/MainWindow.ui
    brlcad/branches/qtged/src/qged/qtads/examples/sidebar/main.cpp
    brlcad/branches/qtged/src/qged/qtads/examples/simple/
    brlcad/branches/qtged/src/qged/qtads/examples/simple/CMakeLists.txt
    brlcad/branches/qtged/src/qged/qtads/examples/simple/MainWindow.cpp
    brlcad/branches/qtged/src/qged/qtads/examples/simple/MainWindow.h
    brlcad/branches/qtged/src/qged/qtads/examples/simple/MainWindow.ui
    brlcad/branches/qtged/src/qged/qtads/examples/simple/main.cpp
    brlcad/branches/qtged/src/qged/qtads/images/
    brlcad/branches/qtged/src/qged/qtads/images/close-button-disabled.svg
    brlcad/branches/qtged/src/qged/qtads/images/close-button-focused.svg
    brlcad/branches/qtged/src/qged/qtads/images/close-button.svg
    brlcad/branches/qtged/src/qged/qtads/images/detach-button-disabled.svg
    brlcad/branches/qtged/src/qged/qtads/images/detach-button.svg
    brlcad/branches/qtged/src/qged/qtads/images/tabs-menu-button.svg
    brlcad/branches/qtged/src/qged/qtads/linux/
    brlcad/branches/qtged/src/qged/qtads/linux/FloatingWidgetTitleBar.cpp
    brlcad/branches/qtged/src/qged/qtads/linux/FloatingWidgetTitleBar.h
    brlcad/branches/qtged/src/qged/qtads/qtadvanceddockingConfig.cmake
    brlcad/branches/qtged/src/qged/qtads/stylesheets/
    brlcad/branches/qtged/src/qged/qtads/stylesheets/default.css
    brlcad/branches/qtged/src/qged/qtads/stylesheets/default_linux.css
    brlcad/branches/qtged/src/qged/qtads/stylesheets/focus_highlighting.css
    
brlcad/branches/qtged/src/qged/qtads/stylesheets/focus_highlighting_linux.css

Modified: brlcad/branches/qtged/src/qged/CMakeLists.txt
===================================================================
--- brlcad/branches/qtged/src/qged/CMakeLists.txt       2020-06-21 19:35:50 UTC 
(rev 76173)
+++ brlcad/branches/qtged/src/qged/CMakeLists.txt       2020-06-22 02:33:25 UTC 
(rev 76174)
@@ -13,6 +13,8 @@
   add_definitions(${Qt5Widgets_DEFINITIONS})
 endif(BRLCAD_ENABLE_QT)
 
+add_subdirectory(qtads)
+
 # NOTE: We can't use the CMake global values for automoc et. al.
 # because most of BRL-CAD's targets are not Qt targets.  We don't
 # want to run the automatic moc logic for all of them.
@@ -65,7 +67,7 @@
 
   add_executable(qged ${qged_srcs} ${moc_srcs} ${cad_qrc})
   qt5_use_modules(qged Widgets OpenGL)
-  target_link_libraries(qged libbu librt libged ${QT_LIBRARIES} 
${OPENGL_LIBRARIES})
+  target_link_libraries(qged libbu librt libged qtadvanceddocking 
${QT_LIBRARIES} ${OPENGL_LIBRARIES})
   target_compile_definitions(qged PRIVATE BRLCADBUILD HAVE_CONFIG_H)
   install(TARGETS qged
     RUNTIME DESTINATION ${BIN_DIR}

Modified: brlcad/branches/qtged/src/qged/TODO.qt
===================================================================
--- brlcad/branches/qtged/src/qged/TODO.qt      2020-06-21 19:35:50 UTC (rev 
76173)
+++ brlcad/branches/qtged/src/qged/TODO.qt      2020-06-22 02:33:25 UTC (rev 
76174)
@@ -19,12 +19,3 @@
 https://doc.qt.io/qt-5/qml-qtquick-controls-treeview.html
 http://doc.qt.io/qt-5/qml-qtwebview-webview.html
 
-
-
-
-Look into replacing current window docking system with:
-
-https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System
-
-which (if I'm reading this right) would give us toplevel windows
-when we undock, among other goodies.

Modified: brlcad/branches/qtged/src/qged/main.cxx
===================================================================
--- brlcad/branches/qtged/src/qged/main.cxx     2020-06-21 19:35:50 UTC (rev 
76173)
+++ brlcad/branches/qtged/src/qged/main.cxx     2020-06-22 02:33:25 UTC (rev 
76174)
@@ -93,7 +93,8 @@
     }
 
     // TODO - this needs to be a setting that is saved and restored
-    mainWin.resize(1100, 800);
+    //mainWin.resize(1100, 800);
+    mainWin.restore_settings();
 
     // Set up the command prompt's commands
     cad_register_commands(&app);

Modified: brlcad/branches/qtged/src/qged/main_window.cxx
===================================================================
--- brlcad/branches/qtged/src/qged/main_window.cxx      2020-06-21 19:35:50 UTC 
(rev 76173)
+++ brlcad/branches/qtged/src/qged/main_window.cxx      2020-06-22 02:33:25 UTC 
(rev 76174)
@@ -41,6 +41,10 @@
     connect(cad_open, SIGNAL(triggered()), this, SLOT(open_file()));
     file_menu->addAction(cad_open);
 
+    cad_save_settings = new QAction("Save Settings", this);
+    connect(cad_save_settings, SIGNAL(triggered()), this, 
SLOT(save_settings()));
+    file_menu->addAction(cad_save_settings);
+
     cad_exit = new QAction("Exit", this);
     connect(cad_exit, SIGNAL(triggered()), this, SLOT(close()));
     file_menu->addAction(cad_exit);
@@ -51,41 +55,27 @@
 
     help_menu = menuBar()->addMenu("Help");
 
-    // Set up OpenGL canvas
-    canvas = new QGLWidget();  //TODO - will need to subclass this so 
libdm/libfb updates are done correctly
-    setCentralWidget(canvas);
 
-
     // Define dock layout
-    console_dock = new QDockWidget("Console", this);
-    addDockWidget(Qt::BottomDockWidgetArea, console_dock);
-    console_dock->setAllowedAreas(Qt::BottomDockWidgetArea);
-    view_menu->addAction(console_dock->toggleViewAction());
+    dock = new ads::CDockManager(this);
 
-    tree_dock = new QDockWidget("Hierarchy", this);
-    addDockWidget(Qt::LeftDockWidgetArea, tree_dock);
-    tree_dock->setAllowedAreas(Qt::LeftDockWidgetArea | 
Qt::RightDockWidgetArea);
-    view_menu->addAction(tree_dock->toggleViewAction());
+    // Set up OpenGL canvas
+    view_dock = new ads::CDockWidget("Scene");
+    view_menu->addAction(view_dock->toggleViewAction());
+    canvas = new QGLWidget();  //TODO - will need to subclass this so 
libdm/libfb updates are done correctly
+    view_dock->setWidget(canvas);
+    dock->addDockWidget(ads::CenterDockWidgetArea, view_dock);
 
-    panel_dock = new QDockWidget("Edit Panel", this);
-    addDockWidget(Qt::RightDockWidgetArea, panel_dock);
-    panel_dock->setAllowedAreas(Qt::LeftDockWidgetArea | 
Qt::RightDockWidgetArea);
-    view_menu->addAction(panel_dock->toggleViewAction());
-
-    /* Because the console usually doesn't need a huge amount of
-     * horizontal space and the tree can use all the vertical space
-     * it can get, give the bottom corners to the left/right docks */
-    setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
-    setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
-
-
-    /***** Create and add the widgets that inhabit the dock *****/
-
     /* Console */
+    console_dock = new ads::CDockWidget("Console");
+    view_menu->addAction(console_dock->toggleViewAction());
     console = new CADConsole(console_dock);
     console_dock->setWidget(console);
+    dock->addDockWidget(ads::BottomDockWidgetArea, console_dock);
 
-    /* Geometry Tree */
+   /* Geometry Tree */
+    tree_dock = new ads::CDockWidget("Hierarchy");
+    view_menu->addAction(tree_dock->toggleViewAction());
     treemodel = new CADTreeModel();
     treeview = new CADTreeView(tree_dock);
     tree_dock->setWidget(treeview);
@@ -102,11 +92,17 @@
     QObject::connect(treeview, SIGNAL(customContextMenuRequested(const 
QPoint&)), treeview, SLOT(context_menu(const QPoint&)));
     treemodel->populate(DBI_NULL);
     ((CADApp *)qApp)->cadtreeview = (CADTreeView *)treeview;
+    dock->addDockWidget(ads::LeftDockWidgetArea, tree_dock);
 
     /* Edit panel */
+    panel_dock = new ads::CDockWidget("Edit Panel");
+    view_menu->addAction(panel_dock->toggleViewAction());
     panel = new CADAccordion(panel_dock);
     panel_dock->setWidget(panel);
+    dock->addDockWidget(ads::RightDockWidgetArea, panel_dock);
 
+    /***** Create and add the widgets that inhabit the dock *****/
+
     //stdpropview->setMinimumHeight(340);
     QObject::connect(treeview, SIGNAL(clicked(const QModelIndex &)), 
panel->stdpropmodel, SLOT(refresh(const QModelIndex &)));
 
@@ -154,6 +150,26 @@
     }
 }
 
+void
+BRLCAD_MainWindow::save_settings()
+{
+    QSettings Settings("Settings.ini", QSettings::IniFormat);
+    Settings.setValue("mainWindow/Geometry", this->saveGeometry());
+    Settings.setValue("mainWindow/State", this->saveState());
+    Settings.setValue("mainWindow/DockingState", dock->saveState());
+}
+
+void
+BRLCAD_MainWindow::restore_settings()
+{
+    if (bu_file_exists("Settings.ini", NULL)) {
+       QSettings Settings("Settings.ini", QSettings::IniFormat);
+       
this->restoreGeometry(Settings.value("mainWindow/Geometry").toByteArray());
+       this->restoreState(Settings.value("mainWindow/State").toByteArray());
+       
dock->restoreState(Settings.value("mainWindow/DockingState").toByteArray());
+    }
+}
+
 /*
  * Local Variables:
  * mode: C++

Modified: brlcad/branches/qtged/src/qged/main_window.h
===================================================================
--- brlcad/branches/qtged/src/qged/main_window.h        2020-06-21 19:35:50 UTC 
(rev 76173)
+++ brlcad/branches/qtged/src/qged/main_window.h        2020-06-22 02:33:25 UTC 
(rev 76174)
@@ -47,8 +47,6 @@
 #undef Success
 #include <QGLWidget>
 #undef Success
-#include <QDockWidget>  //TODO - this will need to be replaced with a 
customized version that makes detached windows full toplevel windows
-#undef Success
 #include <QMenu>
 #undef Success
 #include <QMenuBar>
@@ -71,6 +69,7 @@
 #  pragma clang diagnostic pop
 #endif
 
+#include "qtads/DockManager.h"
 #include "cadconsole.h"
 #include "cadtreemodel.h"
 #include "cadaccordion.h"
@@ -80,22 +79,28 @@
     Q_OBJECT
     public:
        BRLCAD_MainWindow();
+       void restore_settings();
 
        QGLWidget *canvas;
 
     private slots:
        void open_file();
+       void save_settings();
 
     private:
        QMenu *file_menu;
        QAction *cad_open;
+       QAction *cad_save_settings;
+       QAction *cad_restore_settings;
        QAction *cad_exit;
        QMenu *view_menu;
        QMenu *help_menu;
 
-       QDockWidget *console_dock;
-       QDockWidget *tree_dock;
-       QDockWidget *panel_dock;
+       ads::CDockManager *dock;
+       ads::CDockWidget *view_dock;
+       ads::CDockWidget *console_dock;
+       ads::CDockWidget *tree_dock;
+       ads::CDockWidget *panel_dock;
 
        CADConsole *console;
        CADTreeModel *treemodel;

Added: brlcad/branches/qtged/src/qged/qtads/CMakeLists.txt
===================================================================
--- brlcad/branches/qtged/src/qged/qtads/CMakeLists.txt                         
(rev 0)
+++ brlcad/branches/qtged/src/qged/qtads/CMakeLists.txt 2020-06-22 02:33:25 UTC 
(rev 76174)
@@ -0,0 +1,101 @@
+find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED)
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(ads_SRCS
+    ads_globals.cpp
+    DockAreaTabBar.cpp
+    DockAreaTitleBar.cpp
+    DockAreaWidget.cpp
+    DockContainerWidget.cpp
+    DockManager.cpp
+    DockOverlay.cpp
+    DockSplitter.cpp
+    DockWidget.cpp
+    DockWidgetTab.cpp
+    DockingStateReader.cpp
+    DockFocusController.cpp
+    ElidingLabel.cpp
+    FloatingDockContainer.cpp
+    FloatingDragPreview.cpp
+    IconProvider.cpp
+    DockComponentsFactory.cpp
+    ads.qrc
+)
+set(ads_HEADERS
+    ads_globals.h
+    DockAreaTabBar.h
+    DockAreaTitleBar.h
+    DockAreaTitleBar_p.h
+    DockAreaWidget.h
+    DockContainerWidget.h
+    DockManager.h
+    DockOverlay.h
+    DockSplitter.h
+    DockWidget.h
+    DockWidgetTab.h
+    DockingStateReader.h
+    DockFocusController.h
+    ElidingLabel.h
+    FloatingDockContainer.h
+    FloatingDragPreview.h
+    IconProvider.h
+    DockComponentsFactory.h
+)
+if (UNIX)
+    set(ads_SRCS linux/FloatingWidgetTitleBar.cpp ${ads_SRCS})
+    set(ads_HEADERS linux/FloatingWidgetTitleBar.h ${ads_HEADERS})
+endif()
+if(BUILD_STATIC)
+    add_library(qtadvanceddocking STATIC ${ads_SRCS} ${ads_HEADERS})
+    target_compile_definitions(qtadvanceddocking PUBLIC ADS_STATIC)
+else()
+    add_library(qtadvanceddocking SHARED ${ads_SRCS} ${ads_HEADERS})
+    target_compile_definitions(qtadvanceddocking PRIVATE ADS_SHARED_EXPORT)
+endif()
+target_link_libraries(qtadvanceddocking PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets)
+set_target_properties(qtadvanceddocking PROPERTIES 
+    AUTOMOC ON
+    AUTORCC ON
+    CXX_STANDARD 14
+    CXX_STANDARD_REQUIRED ON
+    CXX_EXTENSIONS OFF
+    VERSION 1
+    EXPORT_NAME "qtadvanceddocking"
+    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"
+)
+include(CMakePackageConfigHelpers)
+install(FILES ${ads_HEADERS}
+    DESTINATION include 
+    COMPONENT headers
+)
+install(FILES 
+    "${CMAKE_SOURCE_DIR}/LICENSE"
+    "${CMAKE_SOURCE_DIR}/gnu-lgpl-v2.1.md"
+    DESTINATION license
+    COMPONENT license
+)
+install(TARGETS qtadvanceddocking
+    EXPORT adsTargets
+    RUNTIME DESTINATION bin
+    LIBRARY DESTINATION lib
+    ARCHIVE DESTINATION lib
+    INCLUDES DESTINATION include
+)
+
+install(EXPORT adsTargets
+    FILE adsTargets.cmake
+    NAMESPACE ads::
+    DESTINATION lib/cmake/qtadvanceddocking
+)
+install(FILES qtadvanceddockingConfig.cmake 
"${CMAKE_CURRENT_BINARY_DIR}/qtadvanceddockingConfigVersion.cmake"
+    DESTINATION lib/cmake/qtadvanceddocking
+)
+
+target_include_directories(qtadvanceddocking PUBLIC
+    $<INSTALL_INTERFACE:include>
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+)
+
+add_subdirectory(examples)


Property changes on: brlcad/branches/qtged/src/qged/qtads/CMakeLists.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/branches/qtged/src/qged/qtads/DockAreaTabBar.cpp
===================================================================
--- brlcad/branches/qtged/src/qged/qtads/DockAreaTabBar.cpp                     
        (rev 0)
+++ brlcad/branches/qtged/src/qged/qtads/DockAreaTabBar.cpp     2020-06-22 
02:33:25 UTC (rev 76174)
@@ -0,0 +1,498 @@
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file   DockAreaTabBar.cpp
+/// \author Uwe Kindler
+/// \date   24.08.2018
+/// \brief  Implementation of CDockAreaTabBar class
+//============================================================================
+
+//============================================================================
+//                                   INCLUDES
+//============================================================================
+#include "FloatingDragPreview.h"
+#include "DockAreaTabBar.h"
+
+#include <QMouseEvent>
+#include <QScrollBar>
+#include <QDebug>
+#include <QBoxLayout>
+#include <QApplication>
+#include <QtGlobal>
+
+#include "FloatingDockContainer.h"
+#include "DockAreaWidget.h"
+#include "DockOverlay.h"
+#include "DockManager.h"
+#include "DockWidget.h"
+#include "DockWidgetTab.h"
+
+#include <iostream>
+
+
+namespace ads
+{
+/**
+ * Private data class of CDockAreaTabBar class (pimpl)
+ */
+struct DockAreaTabBarPrivate
+{
+       CDockAreaTabBar* _this;
+       CDockAreaWidget* DockArea;
+       QWidget* TabsContainerWidget;
+       QBoxLayout* TabsLayout;
+       int CurrentIndex = -1;
+
+       /**
+        * Private data constructor
+        */
+       DockAreaTabBarPrivate(CDockAreaTabBar* _public);
+
+       /**
+        * Update tabs after current index changed or when tabs are removed.
+        * The function reassigns the stylesheet to update the tabs
+        */
+       void updateTabs();
+
+       /**
+        * Convenience function to access first tab
+        */
+       CDockWidgetTab* firstTab() const {return _this->tab(0);}
+
+       /**
+        * Convenience function to access last tab
+        */
+       CDockWidgetTab* lastTab() const {return _this->tab(_this->count() - 1);}
+};
+// struct DockAreaTabBarPrivate
+
+//============================================================================
+DockAreaTabBarPrivate::DockAreaTabBarPrivate(CDockAreaTabBar* _public) :
+       _this(_public)
+{
+
+}
+
+
+//============================================================================
+void DockAreaTabBarPrivate::updateTabs()
+{
+       // Set active TAB and update all other tabs to be inactive
+       for (int i = 0; i < _this->count(); ++i)
+       {
+               auto TabWidget = _this->tab(i);
+               if (!TabWidget)
+               {
+                       continue;
+               }
+
+               if (i == CurrentIndex)
+               {
+                       TabWidget->show();
+                       TabWidget->setActiveTab(true);
+                       _this->ensureWidgetVisible(TabWidget);
+               }
+               else
+               {
+                       TabWidget->setActiveTab(false);
+               }
+       }
+}
+
+
+//============================================================================
+CDockAreaTabBar::CDockAreaTabBar(CDockAreaWidget* parent) :
+       QScrollArea(parent),
+       d(new DockAreaTabBarPrivate(this))
+{
+       d->DockArea = parent;
+       setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+       setFrameStyle(QFrame::NoFrame);
+       setWidgetResizable(true);
+       setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+       setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+
+       d->TabsContainerWidget = new QWidget();
+       d->TabsContainerWidget->setSizePolicy(QSizePolicy::Preferred, 
QSizePolicy::Preferred);
+       d->TabsContainerWidget->setObjectName("tabsContainerWidget");
+       d->TabsLayout = new QBoxLayout(QBoxLayout::LeftToRight);
+       d->TabsLayout->setContentsMargins(0, 0, 0, 0);
+       d->TabsLayout->setSpacing(0);
+       d->TabsLayout->addStretch(1);
+       d->TabsContainerWidget->setLayout(d->TabsLayout);
+       setWidget(d->TabsContainerWidget);
+}
+
+
+//============================================================================
+CDockAreaTabBar::~CDockAreaTabBar()
+{
+       delete d;
+}
+
+
+//============================================================================
+void CDockAreaTabBar::wheelEvent(QWheelEvent* Event)
+{
+       Event->accept();
+       const int direction = Event->angleDelta().y();
+       if (direction < 0)
+       {
+               horizontalScrollBar()->setValue(horizontalScrollBar()->value() 
+ 20);
+       }
+       else
+       {
+               horizontalScrollBar()->setValue(horizontalScrollBar()->value() 
- 20);
+       }
+}
+
+
+//============================================================================
+void CDockAreaTabBar::setCurrentIndex(int index)
+{
+       if (index == d->CurrentIndex)
+       {
+               return;
+       }
+
+       if (index < -1 || index > (count() - 1))
+       {
+               qWarning() << Q_FUNC_INFO << "Invalid index" << index;
+               return;
+    }
+
+    emit currentChanging(index);
+       d->CurrentIndex = index;
+       d->updateTabs();
+       updateGeometry();
+       emit currentChanged(index);
+}
+
+
+//============================================================================
+int CDockAreaTabBar::count() const
+{
+       // The tab bar contains a stretch item as last item
+       return d->TabsLayout->count() - 1;
+}
+
+
+//===========================================================================
+void CDockAreaTabBar::insertTab(int Index, CDockWidgetTab* Tab)
+{
+       d->TabsLayout->insertWidget(Index, Tab);
+       connect(Tab, SIGNAL(clicked()), this, SLOT(onTabClicked()));
+       connect(Tab, SIGNAL(closeRequested()), this, 
SLOT(onTabCloseRequested()));
+       connect(Tab, SIGNAL(closeOtherTabsRequested()), this, 
SLOT(onCloseOtherTabsRequested()));
+       connect(Tab, SIGNAL(moved(const QPoint&)), this, 
SLOT(onTabWidgetMoved(const QPoint&)));
+       connect(Tab, SIGNAL(elidedChanged(bool)), this, 
SIGNAL(elidedChanged(bool)));
+       Tab->installEventFilter(this);
+       emit tabInserted(Index);
+    if (Index <= d->CurrentIndex)
+       {
+               setCurrentIndex(d->CurrentIndex + 1);
+    }
+    else if (d->CurrentIndex == -1)
+    {
+       setCurrentIndex(Index);
+    }
+
+       updateGeometry();
+}
+
+
+//===========================================================================
+void CDockAreaTabBar::removeTab(CDockWidgetTab* Tab)
+{
+       if (!count())
+       {
+               return;
+       }
+    ADS_PRINT("CDockAreaTabBar::removeTab ");
+       int NewCurrentIndex = currentIndex();
+       int RemoveIndex = d->TabsLayout->indexOf(Tab);
+       if (count() == 1)
+       {
+               NewCurrentIndex = -1;
+       }
+       if (NewCurrentIndex > RemoveIndex)
+       {
+               NewCurrentIndex--;
+       }
+       else if (NewCurrentIndex == RemoveIndex)
+       {
+               NewCurrentIndex = -1;
+               // First we walk to the right to search for the next visible tab
+               for (int i = (RemoveIndex + 1); i < count(); ++i)
+               {
+                       if (tab(i)->isVisibleTo(this))
+                       {
+                               NewCurrentIndex = i - 1;
+                               break;
+                       }
+               }
+
+               // If there is no visible tab right to this tab then we walk to
+               // the left to find a visible tab
+               if (NewCurrentIndex < 0)
+               {
+                       for (int i = (RemoveIndex - 1); i >= 0; --i)
+                       {
+                               if (tab(i)->isVisibleTo(this))
+                               {
+                                       NewCurrentIndex = i;
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       emit removingTab(RemoveIndex);
+       d->TabsLayout->removeWidget(Tab);
+       Tab->disconnect(this);
+       Tab->removeEventFilter(this);
+    ADS_PRINT("NewCurrentIndex " << NewCurrentIndex);
+       if (NewCurrentIndex != d->CurrentIndex)
+       {
+               setCurrentIndex(NewCurrentIndex);
+       }
+       else
+       {
+               d->updateTabs();
+       }
+
+       updateGeometry();
+}
+
+
+//===========================================================================
+int CDockAreaTabBar::currentIndex() const
+{
+       return d->CurrentIndex;
+}
+
+
+//===========================================================================
+CDockWidgetTab* CDockAreaTabBar::currentTab() const
+{
+       if (d->CurrentIndex < 0)
+       {
+               return nullptr;
+       }
+       else
+       {
+               return 
qobject_cast<CDockWidgetTab*>(d->TabsLayout->itemAt(d->CurrentIndex)->widget());
+       }
+}
+
+
+//===========================================================================
+void CDockAreaTabBar::onTabClicked()
+{
+       CDockWidgetTab* Tab = qobject_cast<CDockWidgetTab*>(sender());
+       if (!Tab)
+       {
+               return;
+       }
+
+       int index = d->TabsLayout->indexOf(Tab);
+       if (index < 0)
+       {
+               return;
+       }
+       setCurrentIndex(index);
+       emit tabBarClicked(index);
+}
+
+
+//===========================================================================
+void CDockAreaTabBar::onTabCloseRequested()
+{
+       CDockWidgetTab* Tab = qobject_cast<CDockWidgetTab*>(sender());
+       int Index = d->TabsLayout->indexOf(Tab);
+       closeTab(Index);
+}
+
+
+//===========================================================================
+void CDockAreaTabBar::onCloseOtherTabsRequested()
+{
+       auto Sender = qobject_cast<CDockWidgetTab*>(sender());
+       for (int i = 0; i < count(); ++i)
+       {
+               auto Tab = tab(i);
+               if (Tab->isClosable() && !Tab->isHidden() && Tab != Sender)
+               {
+                       // If the dock widget is deleted with the closeTab() 
call, its tab
+                       // it will no longer be in the layout, and thus the 
index needs to
+                       // be updated to not skip any tabs
+                       int Offset = Tab->dockWidget()->features().testFlag(
+                               CDockWidget::DockWidgetDeleteOnClose) ? 1 : 0;
+                       closeTab(i);
+
+                       // If the the dock widget blocks closing, i.e. if the 
flag
+                       // CustomCloseHandling is set, and the dock widget is 
still open,
+                       // then we do not need to correct the index
+                       if (Tab->dockWidget()->isClosed())
+                       {
+                               i -= Offset;
+                       }
+               }
+       }
+}
+
+
+//===========================================================================
+CDockWidgetTab* CDockAreaTabBar::tab(int Index) const
+{
+       if (Index >= count() || Index < 0)
+       {
+               return nullptr;
+       }
+       return 
qobject_cast<CDockWidgetTab*>(d->TabsLayout->itemAt(Index)->widget());
+}
+
+
+//===========================================================================
+void CDockAreaTabBar::onTabWidgetMoved(const QPoint& GlobalPos)
+{
+       CDockWidgetTab* MovingTab = qobject_cast<CDockWidgetTab*>(sender());
+       if (!MovingTab)
+       {
+               return;
+       }
+
+       int fromIndex = d->TabsLayout->indexOf(MovingTab);
+       auto MousePos = mapFromGlobal(GlobalPos);
+       MousePos.rx() = qMax(d->firstTab()->geometry().left(), MousePos.x());
+       MousePos.rx() = qMin(d->lastTab()->geometry().right(), MousePos.x());
+       int toIndex = -1;
+       // Find tab under mouse
+       for (int i = 0; i < count(); ++i)
+       {
+               CDockWidgetTab* DropTab = tab(i);
+               if (DropTab == MovingTab || !DropTab->isVisibleTo(this)
+                   || !DropTab->geometry().contains(MousePos))
+               {
+                       continue;
+               }
+
+               toIndex = d->TabsLayout->indexOf(DropTab);
+               if (toIndex == fromIndex)
+               {
+                       toIndex = -1;
+               }
+               break;
+       }
+
+       if (toIndex > -1)
+       {
+               d->TabsLayout->removeWidget(MovingTab);
+               d->TabsLayout->insertWidget(toIndex, MovingTab);
+        ADS_PRINT("tabMoved from " << fromIndex << " to " << toIndex);
+               emit tabMoved(fromIndex, toIndex);
+               setCurrentIndex(toIndex);
+       }
+       else
+       {
+               // Ensure that the moved tab is reset to its start position
+               d->TabsLayout->update();
+       }
+}
+
+//===========================================================================
+void CDockAreaTabBar::closeTab(int Index)
+{
+       if (Index < 0 || Index >= count())
+       {
+               return;
+       }
+
+       auto Tab = tab(Index);
+       if (Tab->isHidden())
+       {
+               return;
+       }
+       emit tabCloseRequested(Index);
+}
+
+
+//===========================================================================
+bool CDockAreaTabBar::eventFilter(QObject *watched, QEvent *event)
+{
+       bool Result = Super::eventFilter(watched, event);
+       CDockWidgetTab* Tab = qobject_cast<CDockWidgetTab*>(watched);
+       if (!Tab)
+       {
+               return Result;
+       }
+
+       switch (event->type())
+       {
+       case QEvent::Hide:
+                emit tabClosed(d->TabsLayout->indexOf(Tab));
+                updateGeometry();
+                break;
+
+       case QEvent::Show:
+                emit tabOpened(d->TabsLayout->indexOf(Tab));
+                updateGeometry();
+                break;
+
+       default:
+               break;
+       }
+
+       return Result;
+}
+
+
+//===========================================================================
+bool CDockAreaTabBar::isTabOpen(int Index) const
+{
+       if (Index < 0 || Index >= count())
+       {
+               return false;
+       }
+
+       return !tab(Index)->isHidden();
+}
+
+
+//===========================================================================
+QSize CDockAreaTabBar::minimumSizeHint() const
+{
+       QSize Size = sizeHint();
+       Size.setWidth(10);
+       return Size;
+}
+
+
+//===========================================================================
+QSize CDockAreaTabBar::sizeHint() const
+{
+       return d->TabsContainerWidget->sizeHint();
+}
+
+} // namespace ads
+
+
+//---------------------------------------------------------------------------
+// EOF DockAreaTabBar.cpp


Property changes on: brlcad/branches/qtged/src/qged/qtads/DockAreaTabBar.cpp
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/branches/qtged/src/qged/qtads/DockAreaTabBar.h
===================================================================
--- brlcad/branches/qtged/src/qged/qtads/DockAreaTabBar.h                       
        (rev 0)
+++ brlcad/branches/qtged/src/qged/qtads/DockAreaTabBar.h       2020-06-22 
02:33:25 UTC (rev 76174)
@@ -0,0 +1,215 @@
+#ifndef DockAreaTabBarH
+#define DockAreaTabBarH
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file   DockAreaTabBar.h
+/// \author Uwe Kindler
+/// \date   24.08.2018
+/// \brief  Declaration of CDockAreaTabBar class
+//============================================================================
+
+//============================================================================
+//                                   INCLUDES
+//============================================================================
+#include <QScrollArea>
+#include "ads_globals.h"
+
+namespace ads
+{
+class CDockAreaWidget;
+class CDockWidgetTab;
+struct DockAreaTabBarPrivate;
+class CDockAreaTitleBar;
+class CFloatingDockContainer;
+class IFloatingWidget;
+
+/**
+ * Custom tabbar implementation for tab area that is shown on top of a
+ * dock area widget.
+ * The tabbar displays the tab widgets of the contained dock widgets.
+ * We cannot use QTabBar here because it does a lot of fancy animations
+ * that will crash the application if a tab is removed while the animation
+ * has not finished. And we need to remove a tab, if the user drags a
+ * a dock widget out of a group of tabbed widgets
+ */
+class ADS_EXPORT CDockAreaTabBar : public QScrollArea
+{
+       Q_OBJECT
+private:
+       DockAreaTabBarPrivate* d; ///< private data (pimpl)
+       friend struct DockAreaTabBarPrivate;
+       friend class CDockAreaTitleBar;
+
+private slots:
+       void onTabClicked();
+       void onTabCloseRequested();
+       void onCloseOtherTabsRequested();
+       void onTabWidgetMoved(const QPoint& GlobalPos);
+
+protected:
+       virtual void wheelEvent(QWheelEvent* Event) override;
+
+
+public:
+       using Super = QScrollArea;
+
+       /**
+        * Default Constructor
+        */
+       CDockAreaTabBar(CDockAreaWidget* parent);
+
+       /**
+        * Virtual Destructor
+        */
+       virtual ~CDockAreaTabBar();
+
+       /**
+        * Inserts the given dock widget tab at the given position.
+        * Inserting a new tab at an index less than or equal to the current 
index
+        * will increment the current index, but keep the current tab.
+        */
+       void insertTab(int Index, CDockWidgetTab* Tab);
+
+       /**
+        * Removes the given DockWidgetTab from the tabbar
+        */
+       void removeTab(CDockWidgetTab* Tab);
+
+       /**
+        * Returns the number of tabs in this tabbar
+        */
+       int count() const;
+
+       /**
+        * Returns the current index or -1 if no tab is selected
+        */
+       int currentIndex() const;
+
+       /**
+        * Returns the current tab or a nullptr if no tab is selected.
+        */
+       CDockWidgetTab* currentTab() const;
+
+       /**
+        * Returns the tab with the given index
+        */
+       CDockWidgetTab* tab(int Index) const;
+
+       /**
+        * Filters the tab widget events
+        */
+       virtual bool eventFilter(QObject *watched, QEvent *event) override;
+
+       /**
+        * This function returns true if the tab is open, that means if it is
+        * visible to the user. If the function returns false, the tab is
+        * closed
+        */
+       bool isTabOpen(int Index) const;
+
+       /**
+        * Overrides the minimumSizeHint() function of QScrollArea
+        * The minimumSizeHint() is bigger than the sizeHint () for the scroll
+        * area because even if the scrollbars are invisible, the required 
speace
+        * is reserved in the minimumSizeHint(). This override simply returns
+        * sizeHint();
+        */
+       virtual QSize minimumSizeHint() const override;
+
+       /**
+        * The function provides a sizeHint that matches the height of the
+        * internal viewport.
+        */
+       virtual QSize sizeHint() const override;
+
+public slots:
+       /**
+        * This property sets the index of the tab bar's visible tab
+        */
+       void setCurrentIndex(int Index);
+
+       /**
+        * This function will close the tab given in Index param.
+        * Closing a tab means, the tab will be hidden, it will not be removed
+        */
+       void closeTab(int Index);
+
+signals:
+    /**
+     * This signal is emitted when the tab bar's current tab is about to be 
changed. The new
+     * current has the given index, or -1 if there isn't a new one.
+     */
+       void currentChanging(int Index);
+
+       /**
+        * This signal is emitted when the tab bar's current tab changes. The 
new
+        * current has the given index, or -1 if there isn't a new one
+        */
+       void currentChanged(int Index);
+
+       /**
+        * This signal is emitted when user clicks on a tab
+        */
+       void tabBarClicked(int index);
+
+       /**
+        * This signal is emitted when the close button on a tab is clicked.
+        * The index is the index that should be closed.
+        */
+       void tabCloseRequested(int index);
+
+       /**
+        * This signal is emitted if a tab has been closed
+        */
+       void tabClosed(int index);
+
+       /**
+        * This signal is emitted if a tab has been opened.
+        * A tab is opened if it has been made visible
+        */
+       void tabOpened(int index);
+
+       /**
+        * This signal is emitted when the tab has moved the tab at index 
position
+        * from to index position to.
+        */
+       void tabMoved(int from, int to);
+
+       /**
+        * This signal is emitted, just before the tab with the given index is
+        * removed
+        */
+       void removingTab(int index);
+
+       /**
+        * This signal is emitted if a tab has been inserted
+        */
+       void tabInserted(int index);
+
+       /**
+        * This signal is emitted when a tab title elide state has been changed
+        */
+       void elidedChanged(bool elided);
+}; // class CDockAreaTabBar
+} // namespace ads
+//-----------------------------------------------------------------------------
+#endif // DockAreaTabBarH
+


Property changes on: brlcad/branches/qtged/src/qged/qtads/DockAreaTabBar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/branches/qtged/src/qged/qtads/DockAreaTitleBar.cpp
===================================================================
--- brlcad/branches/qtged/src/qged/qtads/DockAreaTitleBar.cpp                   
        (rev 0)
+++ brlcad/branches/qtged/src/qged/qtads/DockAreaTitleBar.cpp   2020-06-22 
02:33:25 UTC (rev 76174)
@@ -0,0 +1,650 @@
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file   DockAreaTitleBar.cpp
+/// \author Uwe Kindler
+/// \date   12.10.2018
+/// \brief  Implementation of CDockAreaTitleBar class
+//============================================================================
+
+//============================================================================
+//                                   INCLUDES
+//============================================================================
+#include "DockAreaTitleBar.h"
+
+#include <QPushButton>
+#include <QToolButton>
+#include <QBoxLayout>
+#include <QStyle>
+#include <QMenu>
+#include <QScrollArea>
+#include <QMouseEvent>
+#include <QDebug>
+#include <QPointer>
+
+#include "DockAreaTitleBar_p.h"
+#include "ads_globals.h"
+#include "FloatingDockContainer.h"
+#include "FloatingDragPreview.h"
+#include "DockAreaWidget.h"
+#include "DockOverlay.h"
+#include "DockManager.h"
+#include "DockWidget.h"
+#include "DockWidgetTab.h"
+#include "DockAreaTabBar.h"
+#include "IconProvider.h"
+#include "DockComponentsFactory.h"
+
+#include <iostream>
+
+namespace ads
+{
+
+/**
+ * Private data class of CDockAreaTitleBar class (pimpl)
+ */
+struct DockAreaTitleBarPrivate
+{
+       CDockAreaTitleBar* _this;
+       QPointer<tTitleBarButton> TabsMenuButton;
+       QPointer<tTitleBarButton> UndockButton;
+       QPointer<tTitleBarButton> CloseButton;
+       QBoxLayout* Layout;
+       CDockAreaWidget* DockArea;
+       CDockAreaTabBar* TabBar;
+       bool MenuOutdated = true;
+       QMenu* TabsMenu;
+       QList<tTitleBarButton*> DockWidgetActionsButtons;
+
+       QPoint DragStartMousePos;
+       eDragState DragState = DraggingInactive;
+       IFloatingWidget* FloatingWidget = nullptr;
+
+
+       /**
+        * Private data constructor
+        */
+       DockAreaTitleBarPrivate(CDockAreaTitleBar* _public);
+
+       /**
+        * Creates the title bar close and menu buttons
+        */
+       void createButtons();
+
+       /**
+        * Creates the internal TabBar
+        */
+       void createTabBar();
+
+       /**
+        * Convenience function for DockManager access
+        */
+       CDockManager* dockManager() const
+       {
+               return DockArea->dockManager();
+       }
+
+       /**
+        * Returns true if the given config flag is set
+        * Convenience function to ease config flag testing
+        */
+       static bool testConfigFlag(CDockManager::eConfigFlag Flag)
+       {
+               return CDockManager::testConfigFlag(Flag);
+       }
+
+       /**
+        * Test function for current drag state
+        */
+       bool isDraggingState(eDragState dragState) const
+       {
+               return this->DragState == dragState;
+       }
+
+
+       /**
+        * Starts floating
+        */
+       void startFloating(const QPoint& Offset);
+
+       /**
+        * Makes the dock area floating
+        */
+       IFloatingWidget* makeAreaFloating(const QPoint& Offset, eDragState 
DragState);
+};// struct DockAreaTitleBarPrivate
+
+//============================================================================
+DockAreaTitleBarPrivate::DockAreaTitleBarPrivate(CDockAreaTitleBar* _public) :
+       _this(_public)
+{
+
+}
+
+
+//============================================================================
+void DockAreaTitleBarPrivate::createButtons()
+{
+       QSizePolicy ButtonSizePolicy(QSizePolicy::Fixed, 
QSizePolicy::Expanding);
+
+       // Tabs menu button
+       TabsMenuButton = new 
CTitleBarButton(testConfigFlag(CDockManager::DockAreaHasTabsMenuButton));
+       TabsMenuButton->setObjectName("tabsMenuButton");
+       TabsMenuButton->setAutoRaise(true);
+       TabsMenuButton->setPopupMode(QToolButton::InstantPopup);
+       internal::setButtonIcon(TabsMenuButton, 
QStyle::SP_TitleBarUnshadeButton, ads::DockAreaMenuIcon);
+       QMenu* LTabsMenu = new QMenu(TabsMenuButton);
+#ifndef QT_NO_TOOLTIP
+       LTabsMenu->setToolTipsVisible(true);
+#endif
+       _this->connect(LTabsMenu, SIGNAL(aboutToShow()), 
SLOT(onTabsMenuAboutToShow()));
+       TabsMenuButton->setMenu(LTabsMenu);
+       internal::setToolTip(TabsMenuButton, QObject::tr("List All Tabs"));
+       TabsMenuButton->setSizePolicy(ButtonSizePolicy);
+       Layout->addWidget(TabsMenuButton, 0);
+       _this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)),
+               SLOT(onTabsMenuActionTriggered(QAction*)));
+
+       // Undock button
+       UndockButton = new 
CTitleBarButton(testConfigFlag(CDockManager::DockAreaHasUndockButton));
+       UndockButton->setObjectName("detachGroupButton");
+       UndockButton->setAutoRaise(true);
+       internal::setToolTip(UndockButton, QObject::tr("Detach Group"));
+       internal::setButtonIcon(UndockButton, QStyle::SP_TitleBarNormalButton, 
ads::DockAreaUndockIcon);
+       UndockButton->setSizePolicy(ButtonSizePolicy);
+       Layout->addWidget(UndockButton, 0);
+       _this->connect(UndockButton, SIGNAL(clicked()), 
SLOT(onUndockButtonClicked()));
+
+       // Close button
+       CloseButton = new 
CTitleBarButton(testConfigFlag(CDockManager::DockAreaHasCloseButton));
+       CloseButton->setObjectName("dockAreaCloseButton");
+       CloseButton->setAutoRaise(true);
+       internal::setButtonIcon(CloseButton, QStyle::SP_TitleBarCloseButton, 
ads::DockAreaCloseIcon);
+       if (testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
+       {
+               internal::setToolTip(CloseButton, QObject::tr("Close Active 
Tab"));
+       }
+       else
+       {
+               internal::setToolTip(CloseButton, QObject::tr("Close Group"));
+       }
+       CloseButton->setSizePolicy(ButtonSizePolicy);
+       CloseButton->setIconSize(QSize(16, 16));
+       Layout->addWidget(CloseButton, 0);
+       _this->connect(CloseButton, SIGNAL(clicked()), 
SLOT(onCloseButtonClicked()));
+}
+
+
+//============================================================================
+void DockAreaTitleBarPrivate::createTabBar()
+{
+       TabBar = componentsFactory()->createDockAreaTabBar(DockArea);
+    TabBar->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
+       Layout->addWidget(TabBar);
+       _this->connect(TabBar, SIGNAL(tabClosed(int)), 
SLOT(markTabsMenuOutdated()));
+       _this->connect(TabBar, SIGNAL(tabOpened(int)), 
SLOT(markTabsMenuOutdated()));
+       _this->connect(TabBar, SIGNAL(tabInserted(int)), 
SLOT(markTabsMenuOutdated()));
+       _this->connect(TabBar, SIGNAL(removingTab(int)), 
SLOT(markTabsMenuOutdated()));
+       _this->connect(TabBar, SIGNAL(tabMoved(int, int)), 
SLOT(markTabsMenuOutdated()));
+       _this->connect(TabBar, SIGNAL(currentChanged(int)), 
SLOT(onCurrentTabChanged(int)));
+       _this->connect(TabBar, SIGNAL(tabBarClicked(int)), 
SIGNAL(tabBarClicked(int)));
+       _this->connect(TabBar, SIGNAL(elidedChanged(bool)), 
SLOT(markTabsMenuOutdated()));
+}
+
+
+//============================================================================
+IFloatingWidget* DockAreaTitleBarPrivate::makeAreaFloating(const QPoint& 
Offset, eDragState LDragState)
+{
+       QSize Size = DockArea->size();
+       this->DragState = LDragState;
+       bool OpaqueUndocking = 
CDockManager::testConfigFlag(CDockManager::OpaqueUndocking) ||
+               (DraggingFloatingWidget != LDragState);
+       CFloatingDockContainer* FloatingDockContainer = nullptr;
+       IFloatingWidget* LFloatingWidget;
+       if (OpaqueUndocking)
+       {
+               LFloatingWidget = FloatingDockContainer = new 
CFloatingDockContainer(DockArea);
+       }
+       else
+       {
+               auto w = new CFloatingDragPreview(DockArea);
+               QObject::connect(w, &CFloatingDragPreview::draggingCanceled, 
[=]()
+               {
+                       this->DragState = DraggingInactive;
+               });
+               LFloatingWidget = w;
+       }
+
+    LFloatingWidget->startFloating(Offset, Size, LDragState, nullptr);
+    if (FloatingDockContainer)
+    {
+               auto TopLevelDockWidget = 
FloatingDockContainer->topLevelDockWidget();
+               if (TopLevelDockWidget)
+               {
+                       TopLevelDockWidget->emitTopLevelChanged(true);
+               }
+    }
+
+       return LFloatingWidget;
+}
+
+
+//============================================================================
+void DockAreaTitleBarPrivate::startFloating(const QPoint& Offset)
+{
+       FloatingWidget = makeAreaFloating(Offset, DraggingFloatingWidget);
+}
+
+
+//============================================================================
+CDockAreaTitleBar::CDockAreaTitleBar(CDockAreaWidget* parent) :
+       QFrame(parent),
+       d(new DockAreaTitleBarPrivate(this))
+{
+       d->DockArea = parent;
+
+       setObjectName("dockAreaTitleBar");
+       d->Layout = new QBoxLayout(QBoxLayout::LeftToRight);
+       d->Layout->setContentsMargins(0, 0, 0, 0);
+       d->Layout->setSpacing(0);
+       setLayout(d->Layout);
+       setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+
+       d->createTabBar();
+       d->Layout->addWidget(new CSpacerWidget(this));
+       d->createButtons();
+}
+
+
+//============================================================================
+CDockAreaTitleBar::~CDockAreaTitleBar()
+{
+       if (!d->CloseButton.isNull())
+       {
+               delete d->CloseButton;
+       }
+
+       if (!d->TabsMenuButton.isNull())
+       {
+               delete d->TabsMenuButton;
+       }
+
+       if (!d->UndockButton.isNull())
+       {
+               delete d->UndockButton;
+       }
+       delete d;
+}
+
+
+//============================================================================
+CDockAreaTabBar* CDockAreaTitleBar::tabBar() const
+{
+       return d->TabBar;
+}
+
+//============================================================================
+void CDockAreaTitleBar::markTabsMenuOutdated()
+{
+       
if(DockAreaTitleBarPrivate::testConfigFlag(CDockManager::DockAreaDynamicTabsMenuButtonVisibility))
+       {
+               bool hasElidedTabTitle = false;
+               for (int i = 0; i < d->TabBar->count(); ++i)
+               {
+                       if (!d->TabBar->isTabOpen(i))
+                       {
+                               continue;
+                       }
+                       CDockWidgetTab* Tab = d->TabBar->tab(i);
+                       if(Tab->isTitleElided())
+                       {
+                               hasElidedTabTitle = true;
+                               break;
+                       }
+               }
+               bool visible = (hasElidedTabTitle && (d->TabBar->count() > 1));
+               QMetaObject::invokeMethod(d->TabsMenuButton, "setVisible", 
Qt::QueuedConnection, Q_ARG(bool, visible));
+       }
+       d->MenuOutdated = true;
+}
+
+//============================================================================
+void CDockAreaTitleBar::onTabsMenuAboutToShow()
+{
+       if (!d->MenuOutdated)
+       {
+               return;
+       }
+
+       QMenu* menu = d->TabsMenuButton->menu();
+       menu->clear();
+       for (int i = 0; i < d->TabBar->count(); ++i)
+       {
+               if (!d->TabBar->isTabOpen(i))
+               {
+                       continue;
+               }
+               auto Tab = d->TabBar->tab(i);
+               QAction* Action = menu->addAction(Tab->icon(), Tab->text());
+               internal::setToolTip(Action, Tab->toolTip());
+               Action->setData(i);
+       }
+
+       d->MenuOutdated = false;
+}
+
+
+//============================================================================
+void CDockAreaTitleBar::onCloseButtonClicked()
+{
+    ADS_PRINT("CDockAreaTitleBar::onCloseButtonClicked");
+       if (d->testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
+       {
+               d->TabBar->closeTab(d->TabBar->currentIndex());
+       }
+       else
+       {
+               d->DockArea->closeArea();
+       }
+}
+
+
+//============================================================================
+void CDockAreaTitleBar::onUndockButtonClicked()
+{
+       if (d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable))
+       {
+               d->makeAreaFloating(mapFromGlobal(QCursor::pos()), 
DraggingInactive);
+       }
+}
+
+
+//============================================================================
+void CDockAreaTitleBar::onTabsMenuActionTriggered(QAction* Action)
+{
+       int Index = Action->data().toInt();
+       d->TabBar->setCurrentIndex(Index);
+       emit tabBarClicked(Index);
+}
+
+
+//============================================================================
+void CDockAreaTitleBar::updateDockWidgetActionsButtons()
+{
+       CDockWidget* DockWidget = d->TabBar->currentTab()->dockWidget();
+       if (!d->DockWidgetActionsButtons.isEmpty())
+       {
+               for (auto Button : d->DockWidgetActionsButtons)
+               {
+                       d->Layout->removeWidget(Button);
+                       delete Button;
+               }
+               d->DockWidgetActionsButtons.clear();
+       }
+
+       auto Actions = DockWidget->titleBarActions();
+       if (Actions.isEmpty())
+       {
+               return;
+       }
+
+       int InsertIndex = indexOf(d->TabsMenuButton);
+       for (auto Action : Actions)
+       {
+               auto Button = new CTitleBarButton(true, this);
+               Button->setDefaultAction(Action);
+               Button->setAutoRaise(true);
+               Button->setPopupMode(QToolButton::InstantPopup);
+               Button->setObjectName(Action->objectName());
+               d->Layout->insertWidget(InsertIndex++, Button, 0);
+               d->DockWidgetActionsButtons.append(Button);
+       }
+}
+
+
+//============================================================================
+void CDockAreaTitleBar::onCurrentTabChanged(int Index)
+{
+       if (Index < 0)
+       {
+               return;
+       }
+
+       if (d->testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
+       {
+               CDockWidget* DockWidget = d->TabBar->tab(Index)->dockWidget();
+               
d->CloseButton->setEnabled(DockWidget->features().testFlag(CDockWidget::DockWidgetClosable));
+       }
+
+       updateDockWidgetActionsButtons();
+}
+
+
+//============================================================================
+QAbstractButton* CDockAreaTitleBar::button(TitleBarButton which) const
+{
+       switch (which)
+       {
+       case TitleBarButtonTabsMenu: return d->TabsMenuButton;
+       case TitleBarButtonUndock: return d->UndockButton;
+       case TitleBarButtonClose: return d->CloseButton;
+       default:
+               return nullptr;
+       }
+}
+
+
+//============================================================================
+void CDockAreaTitleBar::setVisible(bool Visible)
+{
+       Super::setVisible(Visible);
+       markTabsMenuOutdated();
+}
+
+
+//============================================================================
+void CDockAreaTitleBar::mousePressEvent(QMouseEvent* ev)
+{
+       if (ev->button() == Qt::LeftButton)
+       {
+               ev->accept();
+               d->DragStartMousePos = ev->pos();
+               d->DragState = DraggingMousePressed;
+
+               if 
(CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
+               {
+                       d->TabBar->currentTab()->setFocus(Qt::OtherFocusReason);
+               }
+               return;
+       }
+       Super::mousePressEvent(ev);
+}
+
+
+//============================================================================
+void CDockAreaTitleBar::mouseReleaseEvent(QMouseEvent* ev)
+{
+       if (ev->button() == Qt::LeftButton)
+       {
+        ADS_PRINT("CDockAreaTitleBar::mouseReleaseEvent");
+               ev->accept();
+               auto CurrentDragState = d->DragState;
+               d->DragStartMousePos = QPoint();
+               d->DragState = DraggingInactive;
+               if (DraggingFloatingWidget == CurrentDragState)
+               {
+                       d->FloatingWidget->finishDragging();
+               }
+
+               return;
+       }
+       Super::mouseReleaseEvent(ev);
+}
+
+
+//============================================================================
+void CDockAreaTitleBar::mouseMoveEvent(QMouseEvent* ev)
+{
+       Super::mouseMoveEvent(ev);
+       if (!(ev->buttons() & Qt::LeftButton) || 
d->isDraggingState(DraggingInactive))
+       {
+               d->DragState = DraggingInactive;
+               return;
+       }
+
+    // move floating window
+    if (d->isDraggingState(DraggingFloatingWidget))
+    {
+        d->FloatingWidget->moveFloating();
+        return;
+    }
+
+       // If this is the last dock area in a floating dock container it does 
not make
+       // sense to move it to a new floating widget and leave this one
+       // empty
+       if (d->DockArea->dockContainer()->isFloating()
+        && d->DockArea->dockContainer()->visibleDockAreaCount() == 1)
+       {
+               return;
+       }
+
+       // If one single dock widget in this area is not floatable then the 
whole
+       // area is not floatable
+       // If we do non opaque undocking, then we can create the floating drag
+       // preview if the dock widget is movable
+       auto Features = d->DockArea->features();
+    if (!Features.testFlag(CDockWidget::DockWidgetFloatable)
+    && !(Features.testFlag(CDockWidget::DockWidgetMovable) && 
!CDockManager::testConfigFlag(CDockManager::OpaqueUndocking)))
+       {
+               return;
+       }
+
+       int DragDistance = (d->DragStartMousePos - ev->pos()).manhattanLength();
+       if (DragDistance >= CDockManager::startDragDistance())
+       {
+        ADS_PRINT("CDockAreaTitlBar::startFloating");
+               d->startFloating(d->DragStartMousePos);
+               auto Overlay = d->DockArea->dockManager()->containerOverlay();
+               Overlay->setAllowedAreas(OuterDockAreas);
+       }
+
+       return;
+}
+
+
+//============================================================================
+void CDockAreaTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
+{
+       // If this is the last dock area in a dock container it does not make
+       // sense to move it to a new floating widget and leave this one
+       // empty
+       if (d->DockArea->dockContainer()->isFloating() && 
d->DockArea->dockContainer()->dockAreaCount() == 1)
+       {
+               return;
+       }
+
+       if (!d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable))
+       {
+               return;
+       }
+       d->makeAreaFloating(event->pos(), DraggingInactive);
+}
+
+
+//============================================================================
+void CDockAreaTitleBar::contextMenuEvent(QContextMenuEvent* ev)
+{
+       ev->accept();
+       if (d->isDraggingState(DraggingFloatingWidget))
+       {
+               return;
+       }
+
+       QMenu Menu(this);
+       auto Action = Menu.addAction(tr("Detach Area"), this, 
SLOT(onUndockButtonClicked()));
+       
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable));
+       Menu.addSeparator();
+       Action = Menu.addAction(tr("Close Area"), this, 
SLOT(onCloseButtonClicked()));
+       
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetClosable));
+       Menu.addAction(tr("Close Other Areas"), d->DockArea, 
SLOT(closeOtherAreas()));
+       Menu.exec(ev->globalPos());
+}
+
+
+//============================================================================
+void CDockAreaTitleBar::insertWidget(int index, QWidget *widget)
+{
+       d->Layout->insertWidget(index, widget);
+}
+
+
+//============================================================================
+int CDockAreaTitleBar::indexOf(QWidget *widget) const
+{
+       return d->Layout->indexOf(widget);
+}
+
+//============================================================================
+CTitleBarButton::CTitleBarButton(bool visible, QWidget* parent)
+       : tTitleBarButton(parent),
+         Visible(visible),
+         
HideWhenDisabled(CDockManager::testConfigFlag(CDockManager::DockAreaHideDisabledButtons))
+{
+
+}
+
+//============================================================================
+void CTitleBarButton::setVisible(bool visible)
+{
+       // 'visible' can stay 'true' if and only if this button is configured 
to generaly visible:
+       visible = visible && this->Visible;
+
+       // 'visible' can stay 'true' unless: this button is configured to be 
invisible when it is disabled and it is currently disabled:
+       if (visible && HideWhenDisabled)
+       {
+               visible = isEnabled();
+       }
+
+       Super::setVisible(visible);
+}
+
+//============================================================================
+bool CTitleBarButton::event(QEvent *ev)
+{
+       if (QEvent::EnabledChange == ev->type() && HideWhenDisabled)
+       {
+               // force setVisible() call 
+               // Calling setVisible() directly here doesn't work well when 
button is expected to be shown first time
+               QMetaObject::invokeMethod(this, "setVisible", 
Qt::QueuedConnection, Q_ARG(bool, isEnabled()));
+       }
+
+       return Super::event(ev);
+}
+
+//============================================================================
+CSpacerWidget::CSpacerWidget(QWidget* Parent /*= 0*/) : Super(Parent)
+{
+       setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+       setStyleSheet("border: none; background: none;");
+}
+
+} // namespace ads
+
+//---------------------------------------------------------------------------
+// EOF DockAreaTitleBar.cpp


Property changes on: brlcad/branches/qtged/src/qged/qtads/DockAreaTitleBar.cpp
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/branches/qtged/src/qged/qtads/DockAreaTitleBar.h
===================================================================
--- brlcad/branches/qtged/src/qged/qtads/DockAreaTitleBar.h                     
        (rev 0)
+++ brlcad/branches/qtged/src/qged/qtads/DockAreaTitleBar.h     2020-06-22 
02:33:25 UTC (rev 76174)
@@ -0,0 +1,162 @@
+#ifndef DockAreaTitleBarH
+#define DockAreaTitleBarH
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file   DockAreaTitleBar.h
+/// \author Uwe Kindler
+/// \date   12.10.2018
+/// \brief  Declaration of CDockAreaTitleBar class
+//============================================================================
+
+
+//============================================================================
+//                                   INCLUDES
+//============================================================================
+#include <QFrame>
+
+#include "ads_globals.h"
+
+QT_FORWARD_DECLARE_CLASS(QAbstractButton)
+
+namespace ads
+{
+class CDockAreaTabBar;
+class CDockAreaWidget;
+struct DockAreaTitleBarPrivate;
+
+/**
+ * Title bar of a dock area.
+ * The title bar contains a tabbar with all tabs for a dock widget group and
+ * with a tabs menu button, a undock button and a close button.
+ */
+class ADS_EXPORT CDockAreaTitleBar : public QFrame
+{
+       Q_OBJECT
+private:
+       DockAreaTitleBarPrivate* d; ///< private data (pimpl)
+       friend struct DockAreaTitleBarPrivate;
+
+private slots:
+       void onTabsMenuAboutToShow();
+       void onCloseButtonClicked();
+       void onUndockButtonClicked();
+       void onTabsMenuActionTriggered(QAction* Action);
+       void onCurrentTabChanged(int Index);
+
+protected:
+               /**
+        * Stores mouse position to detect dragging
+        */
+       virtual void mousePressEvent(QMouseEvent* ev) override;
+
+       /**
+        * Stores mouse position to detect dragging
+        */
+       virtual void mouseReleaseEvent(QMouseEvent* ev) override;
+
+       /**
+        * Starts floating the complete docking area including all dock widgets,
+        * if it is not the last dock area in a floating widget
+        */
+       virtual void mouseMoveEvent(QMouseEvent* ev) override;
+
+       /**
+        * Double clicking the title bar also starts floating of the complete 
area
+        */
+       virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
+
+       /**
+        * Show context menu
+        */
+       virtual void contextMenuEvent(QContextMenuEvent *event) override;
+
+public slots:
+       /**
+        * Call this slot to tell the title bar that it should update the tabs 
menu
+        * the next time it is shown.
+        */
+       void markTabsMenuOutdated();
+
+
+public:
+       using Super = QFrame;
+
+       /**
+        * Default Constructor
+        */
+       CDockAreaTitleBar(CDockAreaWidget* parent);
+
+       /**
+        * Virtual Destructor
+        */
+       virtual ~CDockAreaTitleBar();
+
+       /**
+        * Returns the pointer to the tabBar()
+        */
+       CDockAreaTabBar* tabBar() const;
+
+       /**
+        * Returns the button corresponding to the given title bar button 
identifier
+        */
+       QAbstractButton* button(TitleBarButton which) const;
+
+       /**
+        * Updates the visibility of the dock widget actions in the title bar
+        */
+       void updateDockWidgetActionsButtons();
+
+       /**
+        * Marks the tabs menu outdated before it calls its base class
+        * implementation
+        */
+       virtual void setVisible(bool Visible) override;
+
+       /**
+        * Inserts a custom widget at position index into this title bar.
+        * If index is negative, the widget is added at the end.
+        * You can use this function to insert custom widgets into the title 
bar.
+        */
+       void insertWidget(int index, QWidget *widget);
+
+       /**
+        * Searches for widget widget in this title bar.
+        * You can use this function, to get the position of the default
+        * widget in the tile bar.
+        * \code
+        * int tabBarIndex = TitleBar->indexOf(TitleBar->tabBar());
+        * int closeButtonIndex = 
TitleBar->indexOf(TitleBar->button(TitleBarButtonClose));
+        * \endcode
+        */
+       int indexOf(QWidget *widget) const;
+
+signals:
+       /**
+        * This signal is emitted if a tab in the tab bar is clicked by the user
+        * or if the user clicks on a tab item in the title bar tab menu.
+        */
+       void tabBarClicked(int index);
+}; // class name
+
+}
+ // namespace ads
+//-----------------------------------------------------------------------------
+#endif // DockAreaTitleBarH


Property changes on: brlcad/branches/qtged/src/qged/qtads/DockAreaTitleBar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/branches/qtged/src/qged/qtads/DockAreaTitleBar_p.h
===================================================================
--- brlcad/branches/qtged/src/qged/qtads/DockAreaTitleBar_p.h                   
        (rev 0)
+++ brlcad/branches/qtged/src/qged/qtads/DockAreaTitleBar_p.h   2020-06-22 
02:33:25 UTC (rev 76174)
@@ -0,0 +1,94 @@
+#ifndef DockAreaTitleBar_pH
+#define DockAreaTitleBar_pH
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file   DockAreaTitleBar_p.h
+/// \author Uwe Kindler
+/// \date   12.10.2018
+/// \brief  Declaration of classes CTitleBarButton and CSpacerWidget
+//============================================================================
+
+
+//============================================================================
+//                                   INCLUDES
+//============================================================================
+#include <QFrame>
+#include <QToolButton>
+
+#include "ads_globals.h"
+
+namespace ads
+{
+using tTitleBarButton = QToolButton;
+
+/**
+* Title bar button of a dock area that customizes tTitleBarButton 
appearance/behaviour
+* according to various config flags such as:
+* CDockManager::DockAreaHas_xxx_Button - if set to 'false' keeps the button 
always invisible
+* CDockManager::DockAreaHideDisabledButtons - if set to 'true' hides button 
when it is disabled
+*/
+class CTitleBarButton : public tTitleBarButton
+{
+       Q_OBJECT
+               
+private:
+       bool Visible = true;
+       bool HideWhenDisabled = false;
+
+public:
+       using Super = tTitleBarButton;
+       CTitleBarButton(bool visible = true, QWidget* parent = nullptr);
+
+       /**
+       * Adjust this visibility change request with our internal settings:
+       */
+       virtual void setVisible(bool visible) override;
+
+protected:
+       /**
+       * Handle EnabledChanged signal to set button invisible if the configured
+       */
+       bool event(QEvent *ev) override;
+};
+
+
+/**
+* This spacer widget is here because of the following problem.
+* The dock area title bar handles mouse dragging and moving the floating 
widget.
+* The  problem is, that if the title bar becomes invisible, i.e. if the dock
+* area contains only one single dock widget and the dock area is moved
+* into a floating widget, then mouse events are not handled anymore and 
dragging
+* of the floating widget stops.
+*/
+class CSpacerWidget : public QWidget
+{
+       Q_OBJECT
+public:
+       using Super = QWidget;
+       CSpacerWidget(QWidget* Parent = 0);
+       virtual QSize sizeHint() const override {return QSize(0, 0);}
+       virtual QSize minimumSizeHint() const override {return QSize(0, 0);}
+};
+
+}
+ // namespace ads
+//-----------------------------------------------------------------------------
+#endif // DockAreaTitleBar_pH


Property changes on: brlcad/branches/qtged/src/qged/qtads/DockAreaTitleBar_p.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/branches/qtged/src/qged/qtads/DockAreaWidget.cpp
===================================================================
--- brlcad/branches/qtged/src/qged/qtads/DockAreaWidget.cpp                     
        (rev 0)
+++ brlcad/branches/qtged/src/qged/qtads/DockAreaWidget.cpp     2020-06-22 
02:33:25 UTC (rev 76174)
@@ -0,0 +1,909 @@
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file   DockAreaWidget.cpp
+/// \author Uwe Kindler
+/// \date   24.02.2017
+/// \brief  Implementation of CDockAreaWidget class
+//============================================================================
+
+
+//============================================================================
+//                                   INCLUDES
+//============================================================================
+#include "DockAreaWidget.h"
+
+#include <iostream>
+
+#include <QStackedLayout>
+#include <QScrollBar>
+#include <QScrollArea>
+#include <QWheelEvent>
+#include <QStyle>
+#include <QPushButton>
+#include <QDebug>
+#include <QMenu>
+#include <QSplitter>
+#include <QXmlStreamWriter>
+#include <QVector>
+#include <QList>
+
+
+#include "DockContainerWidget.h"
+#include "DockWidget.h"
+#include "FloatingDockContainer.h"
+#include "DockManager.h"
+#include "DockOverlay.h"
+#include "DockAreaTabBar.h"
+#include "DockSplitter.h"
+#include "DockAreaTitleBar.h"
+#include "DockComponentsFactory.h"
+#include "DockWidgetTab.h"
+
+
+namespace ads
+{
+static const char* const INDEX_PROPERTY = "index";
+static const char* const ACTION_PROPERTY = "action";
+
+/**
+ * Internal dock area layout mimics stack layout but only inserts the current
+ * widget into the internal QLayout object.
+ * \warning Only the current widget has a parent. All other widgets
+ * do not have a parent. That means, a widget that is in this layout may
+ * return nullptr for its parent() function if it is not the current widget.
+ */
+class CDockAreaLayout
+{
+private:
+       QBoxLayout* m_ParentLayout;
+       QList<QWidget*> m_Widgets;
+       int m_CurrentIndex = -1;
+       QWidget* m_CurrentWidget = nullptr;
+
+public:
+       /**
+        * Creates an instance with the given parent layout
+        */
+       CDockAreaLayout(QBoxLayout* ParentLayout)
+               : m_ParentLayout(ParentLayout)
+       {
+
+       }
+
+       /**
+        * Returns the number of widgets in this layout
+        */
+       int count() const
+       {
+               return m_Widgets.count();
+       }
+
+       /**
+        * Inserts the widget at the given index position into the internal 
widget
+        * list
+        */
+       void insertWidget(int index, QWidget* Widget)
+       {
+               Widget->setParent(nullptr);
+               if (index < 0)
+               {
+                       index = m_Widgets.count();
+               }
+               m_Widgets.insert(index, Widget);
+               if (m_CurrentIndex < 0)
+               {
+                       setCurrentIndex(index);
+               }
+               else
+               {
+                       if (index <= m_CurrentIndex )
+                       {
+                               ++m_CurrentIndex;
+                       }
+               }
+       }
+
+       /**
+        * Removes the given widget from the layout
+        */
+       void removeWidget(QWidget* Widget)
+       {
+               if (currentWidget() == Widget)
+               {
+                       auto LayoutItem = m_ParentLayout->takeAt(1);
+                       if (LayoutItem)
+                       {
+                               LayoutItem->widget()->setParent(nullptr);
+                       }
+                       m_CurrentWidget = nullptr;
+                       m_CurrentIndex = -1;
+               }
+               else if (indexOf(Widget) < m_CurrentIndex)
+               {
+                       --m_CurrentIndex;
+               }
+               m_Widgets.removeOne(Widget);
+       }
+
+       /**
+        * Returns the current selected widget
+        */
+       QWidget* currentWidget() const
+       {
+               return m_CurrentWidget;
+       }
+
+       /**
+        * Activates the widget with the give index.
+        */
+       void setCurrentIndex(int index)
+       {
+               QWidget *prev = currentWidget();
+               QWidget *next = widget(index);
+               if (!next || (next == prev && !m_CurrentWidget))
+               {
+                       return;
+               }
+
+               bool reenableUpdates = false;
+               QWidget *parent = m_ParentLayout->parentWidget();
+
+               if (parent && parent->updatesEnabled())
+               {
+                       reenableUpdates = true;
+                       parent->setUpdatesEnabled(false);
+               }
+
+               auto LayoutItem = m_ParentLayout->takeAt(1);
+               if (LayoutItem)
+               {
+                       LayoutItem->widget()->setParent(nullptr);
+               }
+
+               m_ParentLayout->addWidget(next);
+               if (prev)
+               {
+                       prev->hide();
+               }
+               m_CurrentIndex = index;
+               m_CurrentWidget = next;
+
+
+               if (reenableUpdates)
+               {
+                       parent->setUpdatesEnabled(true);
+               }
+       }
+
+       /**
+        * Returns the index of the current active widget
+        */
+       int currentIndex() const
+       {
+               return m_CurrentIndex;
+       }
+
+       /**
+        * Returns true if there are no widgets in the layout
+        */
+       bool isEmpty() const
+       {
+               return m_Widgets.empty();
+       }
+
+       /**
+        * Returns the index of the given widget
+        */
+       int indexOf(QWidget* w) const
+       {
+               return m_Widgets.indexOf(w);
+       }
+
+       /**
+        * Returns the widget for the given index
+        */
+       QWidget* widget(int index) const
+       {
+               return (index < m_Widgets.size()) ? m_Widgets.at(index) : 
nullptr;
+       }
+
+       /**
+        * Returns the geometry of the current active widget
+        */
+       QRect geometry() const
+       {
+               return m_Widgets.empty() ? QRect() : 
currentWidget()->geometry();
+       }
+};
+
+
+
+using DockAreaLayout = CDockAreaLayout;
+
+
+/**
+ * Private data class of CDockAreaWidget class (pimpl)
+ */
+struct DockAreaWidgetPrivate
+{
+       CDockAreaWidget*        _this                   = nullptr;
+       QBoxLayout*                     Layout                  = nullptr;
+       DockAreaLayout*         ContentsLayout  = nullptr;
+       CDockAreaTitleBar*      TitleBar                = nullptr;
+       CDockManager*           DockManager             = nullptr;
+       bool UpdateTitleBarButtons = false;
+       DockWidgetAreas         AllowedAreas    = AllDockAreas;
+       QSize MinSizeHint;
+
+       /**
+        * Private data constructor
+        */
+       DockAreaWidgetPrivate(CDockAreaWidget* _public);
+
+       /**
+        * Creates the layout for top area with tabs and close button
+        */
+       void createTitleBar();
+
+       /**
+        * Returns the dock widget with the given index
+        */
+       CDockWidget* dockWidgetAt(int index)
+       {
+               return 
qobject_cast<CDockWidget*>(ContentsLayout->widget(index));
+       }
+
+       /**
+        * Convenience function to ease title widget access by index
+        */
+       CDockWidgetTab* tabWidgetAt(int index)
+       {
+               return dockWidgetAt(index)->tabWidget();
+       }
+
+
+       /**
+        * Returns the tab action of the given dock widget
+        */
+       QAction* dockWidgetTabAction(CDockWidget* DockWidget) const
+       {
+               return 
qvariant_cast<QAction*>(DockWidget->property(ACTION_PROPERTY));
+       }
+
+       /**
+        * Returns the index of the given dock widget
+        */
+       int dockWidgetIndex(CDockWidget* DockWidget) const
+       {
+               return DockWidget->property(INDEX_PROPERTY).toInt();
+       }
+
+       /**
+        * Convenience function for tabbar access
+        */
+       CDockAreaTabBar* tabBar() const
+       {
+               return TitleBar->tabBar();
+       }
+
+       /**
+        * Udpates the enable state of the close and detach button
+        */
+       void updateTitleBarButtonStates();
+
+       /**
+        * Scans all contained dock widgets for the max. minimum size hint
+        */
+       void updateMinimumSizeHint()
+       {
+               MinSizeHint = QSize();
+               for (int i = 0; i < ContentsLayout->count(); ++i)
+               {
+                       auto Widget = ContentsLayout->widget(i);
+                       MinSizeHint.setHeight(qMax(MinSizeHint.height(), 
Widget->minimumSizeHint().height()));
+                       MinSizeHint.setWidth(qMax(MinSizeHint.width(), 
Widget->minimumSizeHint().width()));
+               }
+       }
+};
+// struct DockAreaWidgetPrivate
+
+
+//============================================================================
+DockAreaWidgetPrivate::DockAreaWidgetPrivate(CDockAreaWidget* _public) :
+       _this(_public)
+{
+
+}
+
+
+//============================================================================
+void DockAreaWidgetPrivate::createTitleBar()
+{
+       TitleBar = componentsFactory()->createDockAreaTitleBar(_this);
+       Layout->addWidget(TitleBar);
+       QObject::connect(tabBar(), &CDockAreaTabBar::tabCloseRequested, _this, 
&CDockAreaWidget::onTabCloseRequested);
+       QObject::connect(TitleBar, &CDockAreaTitleBar::tabBarClicked, _this, 
&CDockAreaWidget::setCurrentIndex);
+       QObject::connect(tabBar(), &CDockAreaTabBar::tabMoved, _this, 
&CDockAreaWidget::reorderDockWidget);
+}
+
+
+//============================================================================
+void DockAreaWidgetPrivate::updateTitleBarButtonStates()
+{
+       if (_this->isHidden())
+       {
+               UpdateTitleBarButtons = true;
+               return;
+       }
+
+       TitleBar->button(TitleBarButtonClose)->setEnabled(
+               _this->features().testFlag(CDockWidget::DockWidgetClosable));
+       TitleBar->button(TitleBarButtonUndock)->setEnabled(
+               _this->features().testFlag(CDockWidget::DockWidgetFloatable));
+       TitleBar->updateDockWidgetActionsButtons();
+       UpdateTitleBarButtons = false;
+}
+
+
+//============================================================================
+CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, 
CDockContainerWidget* parent) :
+       QFrame(parent),
+       d(new DockAreaWidgetPrivate(this))
+{
+       d->DockManager = DockManager;
+       d->Layout = new QBoxLayout(QBoxLayout::TopToBottom);
+       d->Layout->setContentsMargins(0, 0, 0, 0);
+       d->Layout->setSpacing(0);
+       setLayout(d->Layout);
+
+       d->createTitleBar();
+       d->ContentsLayout = new DockAreaLayout(d->Layout);
+       if (d->DockManager)
+       {
+               emit d->DockManager->dockAreaCreated(this);
+       }
+}
+
+//============================================================================
+CDockAreaWidget::~CDockAreaWidget()
+{
+    ADS_PRINT("~CDockAreaWidget()");
+       delete d->ContentsLayout;
+       delete d;
+}
+
+
+//============================================================================
+CDockManager* CDockAreaWidget::dockManager() const
+{
+       return d->DockManager;
+}
+
+
+//============================================================================
+CDockContainerWidget* CDockAreaWidget::dockContainer() const
+{
+       return internal::findParent<CDockContainerWidget*>(this);
+}
+
+
+//============================================================================
+void CDockAreaWidget::addDockWidget(CDockWidget* DockWidget)
+{
+       insertDockWidget(d->ContentsLayout->count(), DockWidget);
+}
+
+
+//============================================================================
+void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
+       bool Activate)
+{
+       d->ContentsLayout->insertWidget(index, DockWidget);
+       DockWidget->setDockArea(this);
+       DockWidget->tabWidget()->setDockAreaWidget(this);
+       auto TabWidget = DockWidget->tabWidget();
+       // Inserting the tab will change the current index which in turn will
+       // make the tab widget visible in the slot
+       d->tabBar()->blockSignals(true);
+       d->tabBar()->insertTab(index, TabWidget);
+       d->tabBar()->blockSignals(false);
+       TabWidget->setVisible(!DockWidget->isClosed());
+       DockWidget->setProperty(INDEX_PROPERTY, index);
+       d->MinSizeHint.setHeight(qMax(d->MinSizeHint.height(), 
DockWidget->minimumSizeHint().height()));
+       d->MinSizeHint.setWidth(qMax(d->MinSizeHint.width(), 
DockWidget->minimumSizeHint().width()));
+       if (Activate)
+       {
+               setCurrentIndex(index);
+       }
+       // If this dock area is hidden, then we need to make it visible again
+       // by calling DockWidget->toggleViewInternal(true);
+       if (!this->isVisible() && d->ContentsLayout->count() > 1 && 
!dockManager()->isRestoringState())
+       {
+               DockWidget->toggleViewInternal(true);
+       }
+       d->updateTitleBarButtonStates();
+}
+
+
+//============================================================================
+void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
+{
+    ADS_PRINT("CDockAreaWidget::removeDockWidget");
+       auto NextOpenDockWidget = nextOpenDockWidget(DockWidget);
+
+       d->ContentsLayout->removeWidget(DockWidget);
+       auto TabWidget = DockWidget->tabWidget();
+       TabWidget->hide();
+       d->tabBar()->removeTab(TabWidget);
+       CDockContainerWidget* DockContainer = dockContainer();
+       if (NextOpenDockWidget)
+       {
+               setCurrentDockWidget(NextOpenDockWidget);
+       }
+       else if (d->ContentsLayout->isEmpty() && DockContainer->dockAreaCount() 
>= 1)
+       {
+        ADS_PRINT("Dock Area empty");
+               DockContainer->removeDockArea(this);
+               this->deleteLater();
+       }
+       else
+       {
+               // if contents layout is not empty but there are no more open 
dock
+               // widgets, then we need to hide the dock area because it does 
not
+               // contain any visible content
+               hideAreaWithNoVisibleContent();
+       }
+
+       d->updateTitleBarButtonStates();
+       updateTitleBarVisibility();
+       d->updateMinimumSizeHint();
+       auto TopLevelDockWidget = DockContainer->topLevelDockWidget();
+       if (TopLevelDockWidget)
+       {
+               TopLevelDockWidget->emitTopLevelChanged(true);
+       }
+
+#if (ADS_DEBUG_LEVEL > 0)
+       DockContainer->dumpLayout();
+#endif
+}
+
+
+//============================================================================
+void CDockAreaWidget::hideAreaWithNoVisibleContent()
+{
+       this->toggleView(false);
+
+       // Hide empty parent splitters
+       auto Splitter = internal::findParent<CDockSplitter*>(this);
+       internal::hideEmptyParentSplitters(Splitter);
+
+       //Hide empty floating widget
+       CDockContainerWidget* Container = this->dockContainer();
+       if (!Container->isFloating() && 
!CDockManager::testConfigFlag(CDockManager::HideSingleCentralWidgetTitleBar))
+       {
+               return;
+       }
+
+       updateTitleBarVisibility();
+       auto TopLevelWidget = Container->topLevelDockWidget();
+       auto FloatingWidget = Container->floatingWidget();
+       if (TopLevelWidget)
+       {
+               if (FloatingWidget)
+               {
+                       FloatingWidget->updateWindowTitle();
+               }
+               CDockWidget::emitTopLevelEventForWidget(TopLevelWidget, true);
+       }
+       else if (Container->openedDockAreas().isEmpty() && FloatingWidget)
+       {
+               FloatingWidget->hide();
+       }
+}
+
+
+//============================================================================
+void CDockAreaWidget::onTabCloseRequested(int Index)
+{
+    ADS_PRINT("CDockAreaWidget::onTabCloseRequested " << Index);
+    auto* DockWidget = dockWidget(Index);
+    if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
+    {
+       DockWidget->closeDockWidgetInternal();
+    }
+    else
+    {
+       DockWidget->toggleView(false);
+    }
+}
+
+
+//============================================================================
+CDockWidget* CDockAreaWidget::currentDockWidget() const
+{
+       int CurrentIndex = currentIndex();
+       if (CurrentIndex < 0)
+       {
+               return nullptr;
+       }
+
+       return dockWidget(CurrentIndex);
+}
+
+
+//============================================================================
+void CDockAreaWidget::setCurrentDockWidget(CDockWidget* DockWidget)
+{
+       if (dockManager()->isRestoringState())
+       {
+               return;
+       }
+
+       internalSetCurrentDockWidget(DockWidget);
+}
+
+
+//============================================================================
+void CDockAreaWidget::internalSetCurrentDockWidget(CDockWidget* DockWidget)
+{
+       int Index = index(DockWidget);
+       if (Index < 0)
+       {
+               return;
+       }
+
+       setCurrentIndex(Index);
+}
+
+
+//============================================================================
+void CDockAreaWidget::setCurrentIndex(int index)
+{
+       auto TabBar = d->tabBar();
+       if (index < 0 || index > (TabBar->count() - 1))
+       {
+               qWarning() << Q_FUNC_INFO << "Invalid index" << index;
+               return;
+    }
+
+       auto cw = d->ContentsLayout->currentWidget();
+       auto nw = d->ContentsLayout->widget(index);
+       if (cw == nw && !nw->isHidden())
+       {
+               return;
+       }
+
+    emit currentChanging(index);
+    TabBar->setCurrentIndex(index);
+       d->ContentsLayout->setCurrentIndex(index);
+       d->ContentsLayout->currentWidget()->show();
+       emit currentChanged(index);
+}
+
+
+//============================================================================
+int CDockAreaWidget::currentIndex() const
+{
+       return d->ContentsLayout->currentIndex();
+}
+
+
+//============================================================================
+QRect CDockAreaWidget::titleBarGeometry() const
+{
+       return d->TitleBar->geometry();
+}
+
+//============================================================================
+QRect CDockAreaWidget::contentAreaGeometry() const
+{
+       return d->ContentsLayout->geometry();
+}
+
+
+//============================================================================
+int CDockAreaWidget::index(CDockWidget* DockWidget)
+{
+       return d->ContentsLayout->indexOf(DockWidget);
+}
+
+
+//============================================================================
+QList<CDockWidget*> CDockAreaWidget::dockWidgets() const
+{
+       QList<CDockWidget*> DockWidgetList;
+       for (int i = 0; i < d->ContentsLayout->count(); ++i)
+       {
+               DockWidgetList.append(dockWidget(i));
+       }
+       return DockWidgetList;
+}
+
+
+//============================================================================
+int CDockAreaWidget::openDockWidgetsCount() const
+{
+       int Count = 0;
+       for (int i = 0; i < d->ContentsLayout->count(); ++i)
+       {
+               if (!dockWidget(i)->isClosed())
+               {
+                       ++Count;
+               }
+       }
+       return Count;
+}
+
+
+//============================================================================
+QList<CDockWidget*> CDockAreaWidget::openedDockWidgets() const
+{
+       QList<CDockWidget*> DockWidgetList;
+       for (int i = 0; i < d->ContentsLayout->count(); ++i)
+       {
+               CDockWidget* DockWidget = dockWidget(i);
+               if (!DockWidget->isClosed())
+               {
+                       DockWidgetList.append(dockWidget(i));
+               }
+       }
+       return DockWidgetList;
+}
+
+
+//============================================================================
+int CDockAreaWidget::indexOfFirstOpenDockWidget() const
+{
+       for (int i = 0; i < d->ContentsLayout->count(); ++i)
+       {
+               if (!dockWidget(i)->isClosed())
+               {
+                       return i;
+               }
+       }
+
+       return -1;
+}
+
+
+//============================================================================
+int CDockAreaWidget::dockWidgetsCount() const
+{
+       return d->ContentsLayout->count();
+}
+
+
+//============================================================================
+CDockWidget* CDockAreaWidget::dockWidget(int Index) const
+{
+       return qobject_cast<CDockWidget*>(d->ContentsLayout->widget(Index));
+}
+
+
+//============================================================================
+void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex)
+{
+    ADS_PRINT("CDockAreaWidget::reorderDockWidget");
+       if (fromIndex >= d->ContentsLayout->count() || fromIndex < 0
+     || toIndex >= d->ContentsLayout->count() || toIndex < 0 || fromIndex == 
toIndex)
+       {
+        ADS_PRINT("Invalid index for tab movement" << fromIndex << toIndex);
+               return;
+       }
+
+       auto Widget = d->ContentsLayout->widget(fromIndex);
+       d->ContentsLayout->removeWidget(Widget);
+       d->ContentsLayout->insertWidget(toIndex, Widget);
+       setCurrentIndex(toIndex);
+}
+
+
+//============================================================================
+void CDockAreaWidget::toggleDockWidgetView(CDockWidget* DockWidget, bool Open)
+{
+       Q_UNUSED(DockWidget);
+       Q_UNUSED(Open);
+       updateTitleBarVisibility();
+}
+
+
+//============================================================================
+void CDockAreaWidget::updateTitleBarVisibility()
+{
+       CDockContainerWidget* Container = dockContainer();
+       if (!Container)
+       {
+               return;
+       }
+
+    if (CDockManager::testConfigFlag(CDockManager::AlwaysShowTabs))
+    {
+        return;
+    }
+
+       if (d->TitleBar)
+       {
+               bool Hidden = Container->hasTopLevelDockWidget() && 
(Container->isFloating()
+                       || 
CDockManager::testConfigFlag(CDockManager::HideSingleCentralWidgetTitleBar));
+               d->TitleBar->setVisible(!Hidden);
+       }
+}
+
+
+//============================================================================
+void CDockAreaWidget::markTitleBarMenuOutdated()
+{
+       if (d->TitleBar)
+       {
+               d->TitleBar->markTabsMenuOutdated();
+       }
+}
+
+
+
+//============================================================================
+void CDockAreaWidget::saveState(QXmlStreamWriter& s) const
+{
+       s.writeStartElement("Area");
+       s.writeAttribute("Tabs", QString::number(d->ContentsLayout->count()));
+       auto CurrentDockWidget = currentDockWidget();
+       QString Name = CurrentDockWidget ? CurrentDockWidget->objectName() : "";
+       s.writeAttribute("Current", Name);
+    ADS_PRINT("CDockAreaWidget::saveState TabCount: " << 
d->ContentsLayout->count()
+            << " Current: " << Name);
+       for (int i = 0; i < d->ContentsLayout->count(); ++i)
+       {
+               dockWidget(i)->saveState(s);
+       }
+       s.writeEndElement();
+}
+
+
+//============================================================================
+CDockWidget* CDockAreaWidget::nextOpenDockWidget(CDockWidget* DockWidget) const
+{
+       auto OpenDockWidgets = openedDockWidgets();
+       if (OpenDockWidgets.count() > 1 || (OpenDockWidgets.count() == 1 && 
OpenDockWidgets[0] != DockWidget))
+       {
+               CDockWidget* NextDockWidget;
+               if (OpenDockWidgets.last() == DockWidget)
+               {
+                       NextDockWidget = 
OpenDockWidgets[OpenDockWidgets.count() - 2];
+               }
+               else
+               {
+                       int NextIndex = OpenDockWidgets.indexOf(DockWidget) + 1;
+                       NextDockWidget = OpenDockWidgets[NextIndex];
+               }
+
+               return NextDockWidget;
+       }
+       else
+       {
+               return nullptr;
+       }
+}
+
+
+//============================================================================
+CDockWidget::DockWidgetFeatures CDockAreaWidget::features(eBitwiseOperator 
Mode) const
+{
+       if (BitwiseAnd == Mode)
+       {
+               CDockWidget::DockWidgetFeatures 
Features(CDockWidget::AllDockWidgetFeatures);
+               for (const auto DockWidget : dockWidgets())
+               {
+                       Features &= DockWidget->features();
+               }
+               return Features;
+       }
+       else
+       {
+               CDockWidget::DockWidgetFeatures 
Features(CDockWidget::NoDockWidgetFeatures);
+               for (const auto DockWidget : dockWidgets())
+               {
+                       Features |= DockWidget->features();
+               }
+               return Features;
+       }
+}
+
+
+//============================================================================
+void CDockAreaWidget::toggleView(bool Open)
+{
+       setVisible(Open);
+
+       emit viewToggled(Open);
+}
+
+
+//============================================================================
+void CDockAreaWidget::setVisible(bool Visible)
+{
+       Super::setVisible(Visible);
+       if (d->UpdateTitleBarButtons)
+       {
+               d->updateTitleBarButtonStates();
+       }
+}
+
+void CDockAreaWidget::setAllowedAreas(DockWidgetAreas areas)
+{
+       d->AllowedAreas = areas;
+}
+
+DockWidgetAreas CDockAreaWidget::allowedAreas() const
+{
+       return d->AllowedAreas;
+}
+
+//============================================================================
+QAbstractButton* CDockAreaWidget::titleBarButton(TitleBarButton which) const
+{
+       return d->TitleBar->button(which);
+}
+
+
+//============================================================================
+void CDockAreaWidget::closeArea()
+{
+       // If there is only one single dock widget and this widget has the
+       // DeleteOnClose feature, then we delete the dock widget now
+       auto OpenDockWidgets = openedDockWidgets();
+       if (OpenDockWidgets.count() == 1 && 
OpenDockWidgets[0]->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
+       {
+               OpenDockWidgets[0]->closeDockWidgetInternal();
+       }
+       else
+       {
+               for (auto DockWidget : openedDockWidgets())
+               {
+                       DockWidget->toggleView(false);
+               }
+       }
+}
+
+
+//============================================================================
+void CDockAreaWidget::closeOtherAreas()
+{
+       dockContainer()->closeOtherAreas(this);
+}
+
+
+//============================================================================
+CDockAreaTitleBar* CDockAreaWidget::titleBar() const
+{
+       return d->TitleBar;
+}
+
+
+//============================================================================
+QSize CDockAreaWidget::minimumSizeHint() const
+{
+       return d->MinSizeHint.isValid() ? d->MinSizeHint : 
Super::minimumSizeHint();
+}
+} // namespace ads
+
+//---------------------------------------------------------------------------
+// EOF DockAreaWidget.cpp


Property changes on: brlcad/branches/qtged/src/qged/qtads/DockAreaWidget.cpp
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/branches/qtged/src/qged/qtads/DockAreaWidget.h
===================================================================
--- brlcad/branches/qtged/src/qged/qtads/DockAreaWidget.h                       
        (rev 0)
+++ brlcad/branches/qtged/src/qged/qtads/DockAreaWidget.h       2020-06-22 
02:33:25 UTC (rev 76174)
@@ -0,0 +1,327 @@
+#ifndef DockAreaWidgetH
+#define DockAreaWidgetH
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file   DockAreaWidget.h
+/// \author Uwe Kindler
+/// \date   24.02.2017
+/// \brief  Declaration of CDockAreaWidget class
+//============================================================================
+
+
+//============================================================================
+//                                   INCLUDES
+//============================================================================
+#include <QFrame>
+
+#include "ads_globals.h"
+#include "DockWidget.h"
+
+QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
+QT_FORWARD_DECLARE_CLASS(QAbstractButton)
+
+namespace ads
+{
+struct DockAreaWidgetPrivate;
+class CDockManager;
+class CDockContainerWidget;
+class DockContainerWidgetPrivate;
+class CDockAreaTitleBar;
+
+
+/**
+ * DockAreaWidget manages multiple instances of DockWidgets.
+ * It displays a title tab, which is clickable and will switch to
+ * the contents associated to the title when clicked.
+ */
+class ADS_EXPORT CDockAreaWidget : public QFrame
+{
+       Q_OBJECT
+private:
+       DockAreaWidgetPrivate* d; ///< private data (pimpl)
+       friend struct DockAreaWidgetPrivate;
+       friend class CDockContainerWidget;
+       friend class DockContainerWidgetPrivate;
+       friend class CDockWidgetTab;
+       friend struct DockWidgetPrivate;
+       friend class CDockWidget;
+       friend struct DockManagerPrivate;
+       friend class CDockManager;
+
+private slots:
+       void onTabCloseRequested(int Index);
+
+       /**
+        * Reorder the index position of DockWidget at fromIndx to toIndex
+        * if a tab in the tabbar is dragged from one index to another one
+        */
+       void reorderDockWidget(int fromIndex, int toIndex);
+
+protected:
+       /**
+        * Inserts a dock widget into dock area.
+        * All dockwidgets in the dock area tabified in a stacked layout with 
tabs.
+        * The index indicates the index of the new dockwidget in the tabbar and
+        * in the stacked layout. If the Activate parameter is true, the new
+        * DockWidget will be the active one in the stacked layout
+        */
+       void insertDockWidget(int index, CDockWidget* DockWidget, bool Activate 
= true);
+
+       /**
+        * Add a new dock widget to dock area.
+        * All dockwidgets in the dock area tabified in a stacked layout with 
tabs
+        */
+       void addDockWidget(CDockWidget* DockWidget);
+
+       /**
+        * Removes the given dock widget from the dock area
+        */
+       void removeDockWidget(CDockWidget* DockWidget);
+
+       /**
+        * Called from dock widget if it is opened or closed
+        */
+       void toggleDockWidgetView(CDockWidget* DockWidget, bool Open);
+
+       /**
+        * This is a helper function to get the next open dock widget to 
activate
+        * if the given DockWidget will be closed or removed.
+        * The function returns the next widget that should be activated or
+        * nullptr in case there are no more open widgets in this area.
+        */
+       CDockWidget* nextOpenDockWidget(CDockWidget* DockWidget) const;
+
+       /**
+        * Returns the index of the given DockWidget in the internal layout
+        */
+       int index(CDockWidget* DockWidget);
+
+       /**
+        * Call this function, if you already know, that the dock does not
+        * contain any visible content (any open dock widgets).
+        */
+       void hideAreaWithNoVisibleContent();
+
+       /**
+        * Updates the dock area layout and components visibility
+        */
+       void updateTitleBarVisibility();
+
+       /**
+        * This is the internal private function for setting the current widget.
+        * This function is called by the public setCurrentDockWidget() function
+        * and by the dock manager when restoring the state
+        */
+       void internalSetCurrentDockWidget(CDockWidget* DockWidget);
+
+       /**
+        * Marks tabs menu to update
+        */
+       void markTitleBarMenuOutdated();
+
+protected slots:
+       void toggleView(bool Open);
+
+public:
+       using Super = QFrame;
+
+       /**
+        * Default Constructor
+        */
+       CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* 
parent);
+
+       /**
+        * Virtual Destructor
+        */
+       virtual ~CDockAreaWidget();
+
+       /**
+        * Returns the dock manager object this dock area belongs to
+        */
+       CDockManager* dockManager() const;
+
+       /**
+        * Returns the dock container widget this dock area widget belongs to 
or 0
+        * if there is no
+        */
+       CDockContainerWidget* dockContainer() const;
+
+    /**
+     * Returns the largest minimumSizeHint() of the dock widgets in this
+     * area.
+     * The minimum size hint is updated if a dock widget is removed or added.
+     */
+    virtual QSize minimumSizeHint() const override;
+
+       /**
+        * Returns the rectangle of the title area
+        */
+       QRect titleBarGeometry() const;
+
+       /**
+        * Returns the rectangle of the content
+        */
+       QRect contentAreaGeometry() const;
+
+       /**
+        * Returns the number of dock widgets in this area
+        */
+       int dockWidgetsCount() const;
+
+       /**
+        * Returns a list of all dock widgets in this dock area.
+        * This list contains open and closed dock widgets.
+        */
+       QList<CDockWidget*> dockWidgets() const;
+
+       /**
+        * Returns the number of open dock widgets in this area
+        */
+       int openDockWidgetsCount() const;
+
+       /**
+        * Returns a list of dock widgets that are not closed.
+        */
+       QList<CDockWidget*> openedDockWidgets() const;
+
+       /**
+        * Returns a dock widget by its index
+        */
+       CDockWidget* dockWidget(int Index) const;
+
+       /**
+        * Returns the index of the current active dock widget or -1 if there
+        * are is no active dock widget (ie.e if all dock widgets are closed)
+        */
+       int currentIndex() const;
+
+       /**
+        * Returns the index of the first open dock widgets in the list of
+        * dock widgets.
+        * This function is here for performance reasons. Normally it would
+        * be possible to take the first dock widget from the list returned by
+        * openedDockWidgets() function. But that function enumerates all
+        * dock widgets while this functions stops after the first open dock 
widget.
+        * If there are no open dock widgets, the function returns -1.
+        */
+       int indexOfFirstOpenDockWidget() const;
+
+       /**
+        * Returns the current active dock widget or a nullptr if there is no
+        * active dock widget (i.e. if all dock widgets are closed)
+        */
+       CDockWidget* currentDockWidget() const;
+
+       /**
+        * Shows the tab with the given dock widget
+        */
+       void setCurrentDockWidget(CDockWidget* DockWidget);
+
+       /**
+        * Saves the state into the given stream
+        */
+       void saveState(QXmlStreamWriter& Stream) const;
+
+       /**
+        * This functions returns the dock widget features of all dock widget in
+        * this area.
+        * A bitwise and is used to combine the flags of all dock widgets. That
+        * means, if only one single dock widget does not support a certain 
flag,
+        * the whole dock are does not support the flag. I.e. if one single
+        * dock widget in this area is not closable, the whole dock are is not
+        * closable.
+        */
+       CDockWidget::DockWidgetFeatures features(eBitwiseOperator Mode = 
BitwiseAnd) const;
+
+       /**
+        * Returns the title bar button corresponding to the given title bar
+        * button identifier
+        */
+       QAbstractButton* titleBarButton(TitleBarButton which) const;
+
+       /**
+        * Update the close button if visibility changed
+        */
+       virtual void setVisible(bool Visible) override;
+
+       /**
+        * Configures the areas of this particular dock area that are allowed 
for docking
+        */
+       void setAllowedAreas(DockWidgetAreas areas);
+
+       /**
+        * Returns flags with all allowed drop areas of this particular dock 
area
+        */
+       DockWidgetAreas allowedAreas() const;
+
+       /**
+        * Returns the title bar of this dock area
+        */
+       CDockAreaTitleBar* titleBar() const;
+
+public slots:
+       /**
+        * This activates the tab for the given tab index.
+        * If the dock widget for the given tab is not visible, the this 
function
+        * call will make it visible.
+        */
+       void setCurrentIndex(int index);
+
+       /**
+        * Closes the dock area and all dock widgets in this area
+        */
+       void closeArea();
+
+       /**
+        * This function closes all other areas except of this area
+        */
+       void closeOtherAreas();
+
+signals:
+       /**
+        * This signal is emitted when user clicks on a tab at an index.
+        */
+       void tabBarClicked(int index);
+
+    /**
+     * This signal is emitted when the tab bar's current tab is about to be 
changed. The new
+     * current has the given index, or -1 if there isn't a new one.
+     * @param index
+     */
+    void currentChanging(int index);
+
+       /**
+        * This signal is emitted when the tab bar's current tab changes. The 
new
+        * current has the given index, or -1 if there isn't a new one
+        * @param index
+        */
+       void currentChanged(int index);
+
+       /**
+        * This signal is emitted if the visibility of this dock area is toggled
+        * via toggle view function
+        */
+       void viewToggled(bool Open);
+}; // class DockAreaWidget
+}
+ // namespace ads
+//-----------------------------------------------------------------------------
+#endif // DockAreaWidgetH


Property changes on: brlcad/branches/qtged/src/qged/qtads/DockAreaWidget.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/branches/qtged/src/qged/qtads/DockComponentsFactory.cpp
===================================================================
--- brlcad/branches/qtged/src/qged/qtads/DockComponentsFactory.cpp              
                (rev 0)
+++ brlcad/branches/qtged/src/qged/qtads/DockComponentsFactory.cpp      
2020-06-22 02:33:25 UTC (rev 76174)
@@ -0,0 +1,69 @@
+//============================================================================
+/// \file   DockComponentsFactory.cpp
+/// \author Uwe Kindler
+/// \date   10.02.2020
+/// \brief  Implementation of DockComponentsFactory
+//============================================================================
+
+//============================================================================
+//                                   INCLUDES
+//============================================================================
+#include "DockComponentsFactory.h"
+
+#include <memory>
+
+#include "DockWidgetTab.h"
+#include "DockAreaTabBar.h"
+#include "DockAreaTitleBar.h"
+#include "DockWidget.h"
+#include "DockAreaWidget.h"
+
+namespace ads
+{
+static std::unique_ptr<CDockComponentsFactory> DefaultFactory(new 
CDockComponentsFactory());
+
+
+//============================================================================
+CDockWidgetTab* CDockComponentsFactory::createDockWidgetTab(CDockWidget* 
DockWidget) const
+{
+       return new CDockWidgetTab(DockWidget);
+}
+
+
+//============================================================================
+CDockAreaTabBar* CDockComponentsFactory::createDockAreaTabBar(CDockAreaWidget* 
DockArea) const
+{
+       return new CDockAreaTabBar(DockArea);
+}
+
+
+//============================================================================
+CDockAreaTitleBar* 
CDockComponentsFactory::createDockAreaTitleBar(CDockAreaWidget* DockArea) const
+{
+       return new CDockAreaTitleBar(DockArea);
+}
+
+
+//============================================================================
+const CDockComponentsFactory* CDockComponentsFactory::factory()
+{
+       return DefaultFactory.get();
+}
+
+
+//============================================================================
+void CDockComponentsFactory::setFactory(CDockComponentsFactory* Factory)
+{
+       DefaultFactory.reset(Factory);
+}
+
+
+//============================================================================
+void CDockComponentsFactory::resetDefaultFactory()
+{
+       DefaultFactory.reset(new CDockComponentsFactory());
+}
+} // namespace ads
+
+//---------------------------------------------------------------------------
+// EOF DockComponentsFactory.cpp


Property changes on: 
brlcad/branches/qtged/src/qged/qtads/DockComponentsFactory.cpp
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/branches/qtged/src/qged/qtads/DockComponentsFactory.h
===================================================================
--- brlcad/branches/qtged/src/qged/qtads/DockComponentsFactory.h                
                (rev 0)
+++ brlcad/branches/qtged/src/qged/qtads/DockComponentsFactory.h        
2020-06-22 02:33:25 UTC (rev 76174)
@@ -0,0 +1,90 @@
+#ifndef DockComponentsFactoryH
+#define DockComponentsFactoryH
+//============================================================================
+/// \file   DockComponentsFactory.h
+/// \author Uwe Kindler
+/// \date   10.02.2020
+/// \brief  Declaration of DockComponentsFactory
+//============================================================================
+
+//============================================================================
+//                                   INCLUDES
+//============================================================================
+#include "ads_globals.h"
+
+namespace ads
+{
+class CDockWidgetTab;
+class CDockAreaTitleBar;
+class CDockAreaTabBar;
+class CDockAreaWidget;
+class CDockWidget;
+
+
+
+/**
+ * Factory for creation of certain GUI elements for the docking framework.
+ * A default unique instance provided by CDockComponentsFactory is used for
+ * creation of all supported components. To inject your custom components,
+ * you can create your own derived dock components factory and register
+ * it via setDefaultFactory() function.
+ * \code
+ * CDockComponentsFactory::setDefaultFactory(new MyComponentsFactory()));
+ * \endcode
+ */
+class ADS_EXPORT CDockComponentsFactory
+{
+public:
+       /**
+        * Force virtual destructor
+        */
+       virtual ~CDockComponentsFactory() {}
+
+       /**
+        * This default implementation just creates a dock widget tab with
+        * new CDockWidgetTab(DockWIdget).
+        */
+       virtual CDockWidgetTab* createDockWidgetTab(CDockWidget* DockWidget) 
const;
+
+       /**
+        * This default implementation just creates a dock area tab bar with
+        * new CDockAreaTabBar(DockArea).
+        */
+       virtual CDockAreaTabBar* createDockAreaTabBar(CDockAreaWidget* 
DockArea) const;
+
+       /**
+        * This default implementation just creates a dock area title bar with
+        * new CDockAreaTitleBar(DockArea).
+        */
+       virtual CDockAreaTitleBar* createDockAreaTitleBar(CDockAreaWidget* 
DockArea) const;
+
+       /**
+        * Returns the default components factory
+        */
+       static const CDockComponentsFactory* factory();
+
+       /**
+        * Sets a new default factory for creation of GUI elements.
+        * This function takes ownership of the given Factory.
+        */
+       static void setFactory(CDockComponentsFactory* Factory);
+
+       /**
+        * Resets the current factory to the
+        */
+       static void resetDefaultFactory();
+};
+
+
+/**
+ * Convenience function to ease factory instance access
+ */
+inline const CDockComponentsFactory* componentsFactory()
+{
+       return CDockComponentsFactory::factory();
+}
+
+} // namespace ads
+
+//---------------------------------------------------------------------------
+#endif // DockComponentsFactoryH


Property changes on: 
brlcad/branches/qtged/src/qged/qtads/DockComponentsFactory.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/branches/qtged/src/qged/qtads/DockContainerWidget.cpp
===================================================================
--- brlcad/branches/qtged/src/qged/qtads/DockContainerWidget.cpp                
                (rev 0)
+++ brlcad/branches/qtged/src/qged/qtads/DockContainerWidget.cpp        
2020-06-22 02:33:25 UTC (rev 76174)
@@ -0,0 +1,1783 @@
+/*******************************************************************************
+** Qt Advanced Docking System

@@ Diff output truncated at 100000 characters. @@
This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
BRL-CAD Source Commits mailing list
brlcad-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to