From 77d2cebe398c3484bc2d6ff5fbd0953ddedc045b Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Wed, 12 Sep 2018 13:52:10 +0200 Subject: [PATCH] Added support for a default tool bar in dockwidgets that can ajust the tool button size according to the floating state, added support for inserting the content widget in a scoll area to provide better resizing for dock widgets --- demo/MainWindow.cpp | 17 +++- src/DockWidget.cpp | 170 +++++++++++++++++++++++++++++++++++- src/DockWidget.h | 78 ++++++++++++++++- src/stylesheets/default.css | 6 ++ 4 files changed, 263 insertions(+), 8 deletions(-) diff --git a/demo/MainWindow.cpp b/demo/MainWindow.cpp index 4894cef..b0ee5b2 100644 --- a/demo/MainWindow.cpp +++ b/demo/MainWindow.cpp @@ -93,7 +93,8 @@ static ads::CDockWidget* createCalendarDockWidget(QMenu* ViewMenu) { static int CalendarCount = 0; QCalendarWidget* w = new QCalendarWidget(); - ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Calendar %1").arg(CalendarCount++)); + ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Calendar %1").arg(CalendarCount++), + nullptr, ads::CDockWidget::WithScrollArea); DockWidget->setWidget(w); DockWidget->setToggleViewActionMode(ads::CDockWidget::ActionModeShow); ViewMenu->addAction(DockWidget->toggleViewAction()); @@ -110,7 +111,8 @@ static ads::CDockWidget* createFileSystemTreeDockWidget(QMenu* ViewMenu) QFileSystemModel* m = new QFileSystemModel(w); m->setRootPath(QDir::currentPath()); w->setModel(m); - ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Filesystem %1").arg(FileSystemCount++)); + ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Filesystem %1").arg(FileSystemCount++), + nullptr, ads::CDockWidget::WithTopToolBar); DockWidget->setWidget(w); ViewMenu->addAction(DockWidget->toggleViewAction()); return DockWidget; @@ -174,9 +176,16 @@ void MainWindowPrivate::createContent() DockWidget->setFeature(ads::CDockWidget::DockWidgetClosable, false); DockManager->addDockWidget(ads::LeftDockWidgetArea, DockWidget); DockManager->addDockWidget(ads::LeftDockWidgetArea, createLongTextLabelDockWidget(ViewMenu)); - DockManager->addDockWidget(ads::BottomDockWidgetArea, createFileSystemTreeDockWidget(ViewMenu)); - auto FileSystemWidget = createFileSystemTreeDockWidget(ViewMenu); + auto ToolBar = FileSystemWidget->toolBar(); + ToolBar->addAction(ui.actionSaveState); + ToolBar->addAction(ui.actionRestoreState); + DockManager->addDockWidget(ads::BottomDockWidgetArea, FileSystemWidget); + + FileSystemWidget = createFileSystemTreeDockWidget(ViewMenu); + ToolBar = FileSystemWidget->toolBar(); + ToolBar->addAction(ui.actionSaveState); + ToolBar->addAction(ui.actionRestoreState); FileSystemWidget->setFeature(ads::CDockWidget::DockWidgetMovable, false); auto TopDockArea = DockManager->addDockWidget(ads::TopDockWidgetArea, FileSystemWidget); DockWidget = createCalendarDockWidget(ViewMenu); diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index 16db4d2..f41bf08 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -35,10 +35,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include "DockContainerWidget.h" @@ -66,6 +68,13 @@ struct DockWidgetPrivate CDockAreaWidget* DockArea = nullptr; QAction* ToggleViewAction; bool Closed = false; + CDockWidget::LayoutFlags LayoutFlags; + QScrollArea* ScrollArea = nullptr; + QToolBar* ToolBar = nullptr; + Qt::ToolButtonStyle ToolBarStyleDocked = Qt::ToolButtonIconOnly; + Qt::ToolButtonStyle ToolBarStyleFloating = Qt::ToolButtonTextUnderIcon; + QSize ToolBarIconSizeDocked = QSize(16, 16); + QSize ToolBarIconSizeFloating = QSize(24, 24); /** * Private data constructor @@ -99,6 +108,16 @@ struct DockWidgetPrivate * if all dock widgets in all dock areas are closed */ void hideEmptyFloatingWidget(); + + /** + * Setup the top tool bar + */ + void setupToolBar(); + + /** + * Setup the main scroll area + */ + void setupScrollArea(); }; // struct DockWidgetPrivate @@ -194,22 +213,61 @@ void DockWidgetPrivate::hideEmptyFloatingWidget() //============================================================================ -CDockWidget::CDockWidget(const QString &title, QWidget *parent) : +void DockWidgetPrivate::setupToolBar() +{ + if (!LayoutFlags.testFlag(CDockWidget::WithTopToolBar)) + { + return; + } + + ToolBar = new QToolBar(_this); + ToolBar->setObjectName("dockWidgetToolBar"); + Layout->addWidget(ToolBar); + ToolBar->setIconSize(QSize(16, 16)); + ToolBar->toggleViewAction()->setEnabled(false); + ToolBar->toggleViewAction()->setVisible(false); + _this->connect(_this, SIGNAL(topLevelChanged(bool)), SLOT(setToolbarFloatingStyle(bool))); +} + + + +//============================================================================ +void DockWidgetPrivate::setupScrollArea() +{ + if (!LayoutFlags.testFlag(CDockWidget::WithScrollArea)) + { + return; + } + + ScrollArea = new QScrollArea(_this); + ScrollArea->setObjectName("dockWidgetScrollArea"); + ScrollArea->setWidgetResizable(true); + Layout->addWidget(ScrollArea); +} + + +//============================================================================ +CDockWidget::CDockWidget(const QString &title, QWidget *parent, + LayoutFlags layoutFlags) : QFrame(parent), d(new DockWidgetPrivate(this)) { + d->LayoutFlags = layoutFlags; d->Layout = new QBoxLayout(QBoxLayout::TopToBottom); d->Layout->setContentsMargins(0, 0, 0, 0); d->Layout->setSpacing(0); setLayout(d->Layout); setWindowTitle(title); setObjectName(title); + d->setupToolBar(); + d->setupScrollArea(); d->TabWidget = new CDockWidgetTab(this); d->ToggleViewAction = new QAction(title); d->ToggleViewAction->setCheckable(true); connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this, SLOT(toggleView(bool))); + setToolbarFloatingStyle(false); } //============================================================================ @@ -233,7 +291,11 @@ void CDockWidget::setToggleViewActionChecked(bool Checked) //============================================================================ void CDockWidget::setWidget(QWidget* widget) { - if (d->Widget) + if (d->LayoutFlags.testFlag(WithScrollArea)) + { + d->ScrollArea->setWidget(widget); + } + else if (d->Widget) { d->Layout->replaceWidget(d->Widget, widget); } @@ -243,6 +305,7 @@ void CDockWidget::setWidget(QWidget* widget) } d->Widget = widget; + d->Widget->setProperty("dockWidgetContent", true); } @@ -465,6 +528,109 @@ QIcon CDockWidget::icon() const } +//============================================================================ +QToolBar* CDockWidget::toolBar() const +{ + return d->ToolBar; +} + + +//============================================================================ +void CDockWidget::setToolBar(QToolBar* ToolBar) +{ + if (d->ToolBar) + { + delete d->ToolBar; + } + + d->ToolBar = ToolBar; + d->Layout->insertWidget(0, d->ToolBar); + this->connect(this, SIGNAL(topLevelChanged(bool)), SLOT(setToolbarFloatingStyle(bool))); + setToolbarFloatingStyle(isFloating()); +} + + +//============================================================================ +void CDockWidget::setToolBarStyle(Qt::ToolButtonStyle Style, eState State) +{ + if (StateFloating == State) + { + d->ToolBarStyleFloating = Style; + } + else + { + d->ToolBarStyleDocked = Style; + } + + setToolbarFloatingStyle(isFloating()); +} + + +//============================================================================ +Qt::ToolButtonStyle CDockWidget::toolBarStyle(eState State) const +{ + if (StateFloating == State) + { + return d->ToolBarStyleFloating; + } + else + { + return d->ToolBarStyleDocked; + } +} + + +//============================================================================ +void CDockWidget::setToolBarIconSize(const QSize& IconSize, eState State) +{ + if (StateFloating == State) + { + d->ToolBarIconSizeFloating = IconSize; + } + else + { + d->ToolBarIconSizeDocked = IconSize; + } + + setToolbarFloatingStyle(isFloating()); +} + + +//============================================================================ +QSize CDockWidget::toolBarIconSize(eState State) const +{ + if (StateFloating == State) + { + return d->ToolBarIconSizeFloating; + } + else + { + return d->ToolBarIconSizeDocked; + } +} + + +//============================================================================ +void CDockWidget::setToolbarFloatingStyle(bool Floating) +{ + if (!d->ToolBar) + { + return; + } + + auto IconSize = Floating ? d->ToolBarIconSizeFloating : d->ToolBarIconSizeDocked; + if (IconSize != d->ToolBar->iconSize()) + { + d->ToolBar->setIconSize(IconSize); + } + + auto ButtonStyle = Floating ? d->ToolBarStyleFloating : d->ToolBarStyleDocked; + if (ButtonStyle != d->ToolBar->toolButtonStyle()) + { + d->ToolBar->setToolButtonStyle(ButtonStyle); + } +} + } // namespace ads diff --git a/src/DockWidget.h b/src/DockWidget.h index 5aa9bf5..b8e4ad7 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -34,6 +34,7 @@ #include "ads_globals.h" +class QToolBar; class QXmlStreamWriter; namespace ads @@ -56,6 +57,12 @@ private: DockWidgetPrivate* d; ///< private data (pimpl) friend struct DockWidgetPrivate; +private slots: + /** + * Adjusts the toolbar icon sizes according to the floating state + */ + void setToolbarFloatingStyle(bool topLevel); + protected: friend class CDockContainerWidget; friend class CDockAreaWidget; @@ -109,7 +116,6 @@ public: }; Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature) - enum eState { StateHidden, @@ -117,6 +123,27 @@ public: StateFloating }; + /** + * Use the layout flags to configure the layout of the dock widget. + * The content of a dock widget should be resizable do a very small size to + * prevent the dock widget from blocking the resizing. To ensure, that a + * dock widget can be resized very well, it is better to insert the content+ + * widget into a scroll area. Enable the WithScrollArea + * feature to use this feature. If your content widget is already in a + * scroll area or if it is a derived class like QTableView, the you should + * disable the WithScrollArea flag. + * Often dock widgets need a ToolBar for control of operations in the dock + * widget. Use the WithToolBar feature to enable a tool bar that is placed + * on top of the dock widget content. If this flag is disabled, the toolBar() + * function returns a nullptr. + */ + enum LayoutFlag + { + WithScrollArea = 0x01, + WithTopToolBar = 0x02 + }; + Q_DECLARE_FLAGS(LayoutFlags, LayoutFlag) + /** * This mode configures the behavior of the toggle view action. * If the mode if ActionModeToggle, then the toggle view action is @@ -131,6 +158,7 @@ public: ActionModeShow //!< ActionModeShow }; + /** * This constructor creates a dock widget with the given title. * The title is the text that is shown in the window title when the dock @@ -142,8 +170,10 @@ public: * If your title is not unique or if you would like to change the title * during runtime, you need to set a unique object name explicitely * by calling setObjectName() after construction. + * Use the layoutFlags to configure the layout of the dock widget. */ - CDockWidget(const QString &title, QWidget* parent = 0); + CDockWidget(const QString &title, QWidget* parent = 0, + LayoutFlags layoutFlags = 0); /** * Virtual Destructor @@ -246,6 +276,50 @@ public: */ QIcon icon() const; + /** + * If the WithToolBar layout flag is enabled, then this function returns + * the dock widget toolbar. If the flag is disabled, the function returns + * a nullptr. + */ + QToolBar* toolBar() const; + + /** + * Assign a new tool bar that is shown above the content widget. + * The dock widget will become the owner of the tool bar and deletes it + * on destruction + */ + void setToolBar(QToolBar* ToolBar); + + /** + * This function sets the tool button style for the given dock widget state. + * It is possible to switch the tool button style depending on the state. + * If a dock widget is floating, then here are more space and it is + * possible to select a style that requires more space like + * Qt::ToolButtonTextUnderIcon. For the docked state Qt::ToolButtonIconOnly + * might be better. + */ + void setToolBarStyle(Qt::ToolButtonStyle Style, eState State); + + /** + * Returns the tool button style for the given docking state. + * \see setToolBarStyle() + */ + Qt::ToolButtonStyle toolBarStyle(eState State) const; + + /** + * This function sets the tool button icon size for the given state. + * If a dock widget is floating, there is more space an increasing the + * icon size is possible. For docked widgets, small icon sizes, eg. 16 x 16 + * might be better. + */ + void setToolBarIconSize(const QSize& IconSize, eState State); + + /** + * Returns the icon size for a given docking state. + * \see setToolBarIconSize() + */ + QSize toolBarIconSize(eState State) const; + public: // reimplements QFrame ----------------------------------------------- /** diff --git a/src/stylesheets/default.css b/src/stylesheets/default.css index 1df7741..1a676ca 100644 --- a/src/stylesheets/default.css +++ b/src/stylesheets/default.css @@ -63,4 +63,10 @@ QPushButton#tabsMenuButton padding: 2px; } +QScrollArea#dockWidgetScrollArea +{ + padding: 0px; + border: none; +} +