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

This commit is contained in:
Uwe Kindler 2018-09-12 13:52:10 +02:00
parent 5d380708e1
commit 77d2cebe39
4 changed files with 263 additions and 8 deletions

View File

@ -93,7 +93,8 @@ static ads::CDockWidget* createCalendarDockWidget(QMenu* ViewMenu)
{ {
static int CalendarCount = 0; static int CalendarCount = 0;
QCalendarWidget* w = new QCalendarWidget(); 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->setWidget(w);
DockWidget->setToggleViewActionMode(ads::CDockWidget::ActionModeShow); DockWidget->setToggleViewActionMode(ads::CDockWidget::ActionModeShow);
ViewMenu->addAction(DockWidget->toggleViewAction()); ViewMenu->addAction(DockWidget->toggleViewAction());
@ -110,7 +111,8 @@ static ads::CDockWidget* createFileSystemTreeDockWidget(QMenu* ViewMenu)
QFileSystemModel* m = new QFileSystemModel(w); QFileSystemModel* m = new QFileSystemModel(w);
m->setRootPath(QDir::currentPath()); m->setRootPath(QDir::currentPath());
w->setModel(m); 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); DockWidget->setWidget(w);
ViewMenu->addAction(DockWidget->toggleViewAction()); ViewMenu->addAction(DockWidget->toggleViewAction());
return DockWidget; return DockWidget;
@ -174,9 +176,16 @@ void MainWindowPrivate::createContent()
DockWidget->setFeature(ads::CDockWidget::DockWidgetClosable, false); DockWidget->setFeature(ads::CDockWidget::DockWidgetClosable, false);
DockManager->addDockWidget(ads::LeftDockWidgetArea, DockWidget); DockManager->addDockWidget(ads::LeftDockWidgetArea, DockWidget);
DockManager->addDockWidget(ads::LeftDockWidgetArea, createLongTextLabelDockWidget(ViewMenu)); DockManager->addDockWidget(ads::LeftDockWidgetArea, createLongTextLabelDockWidget(ViewMenu));
DockManager->addDockWidget(ads::BottomDockWidgetArea, createFileSystemTreeDockWidget(ViewMenu));
auto FileSystemWidget = 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); FileSystemWidget->setFeature(ads::CDockWidget::DockWidgetMovable, false);
auto TopDockArea = DockManager->addDockWidget(ads::TopDockWidgetArea, FileSystemWidget); auto TopDockArea = DockManager->addDockWidget(ads::TopDockWidgetArea, FileSystemWidget);
DockWidget = createCalendarDockWidget(ViewMenu); DockWidget = createCalendarDockWidget(ViewMenu);

View File

@ -35,10 +35,12 @@
#include <QAction> #include <QAction>
#include <QSplitter> #include <QSplitter>
#include <QStack> #include <QStack>
#include <QScrollArea>
#include <QTextStream> #include <QTextStream>
#include <QPointer> #include <QPointer>
#include <QEvent> #include <QEvent>
#include <QDebug> #include <QDebug>
#include <QToolBar>
#include <QXmlStreamWriter> #include <QXmlStreamWriter>
#include "DockContainerWidget.h" #include "DockContainerWidget.h"
@ -66,6 +68,13 @@ struct DockWidgetPrivate
CDockAreaWidget* DockArea = nullptr; CDockAreaWidget* DockArea = nullptr;
QAction* ToggleViewAction; QAction* ToggleViewAction;
bool Closed = false; 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 * Private data constructor
@ -99,6 +108,16 @@ struct DockWidgetPrivate
* if all dock widgets in all dock areas are closed * if all dock widgets in all dock areas are closed
*/ */
void hideEmptyFloatingWidget(); void hideEmptyFloatingWidget();
/**
* Setup the top tool bar
*/
void setupToolBar();
/**
* Setup the main scroll area
*/
void setupScrollArea();
}; };
// struct DockWidgetPrivate // 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), QFrame(parent),
d(new DockWidgetPrivate(this)) d(new DockWidgetPrivate(this))
{ {
d->LayoutFlags = layoutFlags;
d->Layout = new QBoxLayout(QBoxLayout::TopToBottom); d->Layout = new QBoxLayout(QBoxLayout::TopToBottom);
d->Layout->setContentsMargins(0, 0, 0, 0); d->Layout->setContentsMargins(0, 0, 0, 0);
d->Layout->setSpacing(0); d->Layout->setSpacing(0);
setLayout(d->Layout); setLayout(d->Layout);
setWindowTitle(title); setWindowTitle(title);
setObjectName(title); setObjectName(title);
d->setupToolBar();
d->setupScrollArea();
d->TabWidget = new CDockWidgetTab(this); d->TabWidget = new CDockWidgetTab(this);
d->ToggleViewAction = new QAction(title); d->ToggleViewAction = new QAction(title);
d->ToggleViewAction->setCheckable(true); d->ToggleViewAction->setCheckable(true);
connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this, connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this,
SLOT(toggleView(bool))); SLOT(toggleView(bool)));
setToolbarFloatingStyle(false);
} }
//============================================================================ //============================================================================
@ -233,7 +291,11 @@ void CDockWidget::setToggleViewActionChecked(bool Checked)
//============================================================================ //============================================================================
void CDockWidget::setWidget(QWidget* widget) 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); d->Layout->replaceWidget(d->Widget, widget);
} }
@ -243,6 +305,7 @@ void CDockWidget::setWidget(QWidget* widget)
} }
d->Widget = 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 } // namespace ads

View File

@ -34,6 +34,7 @@
#include "ads_globals.h" #include "ads_globals.h"
class QToolBar;
class QXmlStreamWriter; class QXmlStreamWriter;
namespace ads namespace ads
@ -56,6 +57,12 @@ private:
DockWidgetPrivate* d; ///< private data (pimpl) DockWidgetPrivate* d; ///< private data (pimpl)
friend struct DockWidgetPrivate; friend struct DockWidgetPrivate;
private slots:
/**
* Adjusts the toolbar icon sizes according to the floating state
*/
void setToolbarFloatingStyle(bool topLevel);
protected: protected:
friend class CDockContainerWidget; friend class CDockContainerWidget;
friend class CDockAreaWidget; friend class CDockAreaWidget;
@ -109,7 +116,6 @@ public:
}; };
Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature) Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature)
enum eState enum eState
{ {
StateHidden, StateHidden,
@ -117,6 +123,27 @@ public:
StateFloating 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. * This mode configures the behavior of the toggle view action.
* If the mode if ActionModeToggle, then the toggle view action is * If the mode if ActionModeToggle, then the toggle view action is
@ -131,6 +158,7 @@ public:
ActionModeShow //!< ActionModeShow ActionModeShow //!< ActionModeShow
}; };
/** /**
* This constructor creates a dock widget with the given title. * 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 * 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 * 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 * during runtime, you need to set a unique object name explicitely
* by calling setObjectName() after construction. * 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 * Virtual Destructor
@ -246,6 +276,50 @@ public:
*/ */
QIcon icon() const; 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 ----------------------------------------------- public: // reimplements QFrame -----------------------------------------------
/** /**

View File

@ -63,4 +63,10 @@ QPushButton#tabsMenuButton
padding: 2px; padding: 2px;
} }
QScrollArea#dockWidgetScrollArea
{
padding: 0px;
border: none;
}