Some changes for dockwidget tab close button, some refactorings to make insertion of widgets into dock widget easier, added createDefaultToolBar function for creation of toolbar and removed layout flags from CDockWidget

This commit is contained in:
Uwe Kindler 2018-11-08 10:04:29 +01:00
parent 316e5324ad
commit b3a272110a
15 changed files with 187 additions and 93 deletions

View File

@ -94,8 +94,7 @@ 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++),
nullptr, ads::CDockWidget::WithScrollArea);
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Calendar %1").arg(CalendarCount++));
DockWidget->setWidget(w);
DockWidget->setToggleViewActionMode(ads::CDockWidget::ActionModeShow);
ViewMenu->addAction(DockWidget->toggleViewAction());
@ -112,8 +111,7 @@ 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++),
nullptr, ads::CDockWidget::WithTopToolBar);
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Filesystem %1").arg(FileSystemCount++));
DockWidget->setWidget(w);
ViewMenu->addAction(DockWidget->toggleViewAction());
return DockWidget;
@ -178,13 +176,13 @@ void MainWindowPrivate::createContent()
DockManager->addDockWidget(ads::LeftDockWidgetArea, DockWidget);
DockManager->addDockWidget(ads::LeftDockWidgetArea, createLongTextLabelDockWidget(ViewMenu));
auto FileSystemWidget = createFileSystemTreeDockWidget(ViewMenu);
auto ToolBar = FileSystemWidget->toolBar();
auto ToolBar = FileSystemWidget->createDefaultToolBar();
ToolBar->addAction(ui.actionSaveState);
ToolBar->addAction(ui.actionRestoreState);
DockManager->addDockWidget(ads::BottomDockWidgetArea, FileSystemWidget);
FileSystemWidget = createFileSystemTreeDockWidget(ViewMenu);
ToolBar = FileSystemWidget->toolBar();
ToolBar = FileSystemWidget->createDefaultToolBar();
ToolBar->addAction(ui.actionSaveState);
ToolBar->addAction(ui.actionRestoreState);
FileSystemWidget->setFeature(ads::CDockWidget::DockWidgetMovable, false);

View File

@ -288,6 +288,7 @@ void CDockAreaTabBar::insertTab(int Index, CDockWidgetTab* Tab)
{
d->TabsLayout->insertWidget(Index, Tab);
connect(Tab, SIGNAL(clicked()), this, SLOT(onTabClicked()));
connect(Tab, SIGNAL(closeButtonClicked()), this, SLOT(onTabCloseButtonClicked()));
connect(Tab, SIGNAL(moved(const QPoint&)), this, SLOT(onTabWidgetMoved(const QPoint&)));
Tab->installEventFilter(this);
emit tabInserted(Index);
@ -400,6 +401,13 @@ void CDockAreaTabBar::onTabClicked()
}
//===========================================================================
void CDockAreaTabBar::onTabCloseButtonClicked()
{
closeTab(currentIndex());
}
//===========================================================================
CDockWidgetTab* CDockAreaTabBar::tab(int Index) const
{

View File

@ -54,6 +54,7 @@ private:
private slots:
void onTabClicked();
void onTabCloseButtonClicked();
void onTabWidgetMoved(const QPoint& GlobalPos);
protected:

View File

@ -37,9 +37,8 @@
#include <QScrollArea>
#include <QMouseEvent>
#include <QDebug>
#include <QStyleOptionButton>
#include <QPainter>
#include "ads_globals.h"
#include "FloatingDockContainer.h"
#include "DockAreaWidget.h"
#include "DockOverlay.h"
@ -81,8 +80,6 @@ struct DockAreaTitleBarPrivate
* Creates the internal TabBar
*/
void createTabBar();
QPixmap createTransparentPixmap(const QPixmap& Source);
};// struct DockAreaTitleBarPrivate
@ -95,18 +92,6 @@ DockAreaTitleBarPrivate::DockAreaTitleBarPrivate(CDockAreaTitleBar* _public) :
}
//============================================================================
QPixmap DockAreaTitleBarPrivate::createTransparentPixmap(const QPixmap& Source)
{
QPixmap disabledPixmap(Source.size());
disabledPixmap.fill(Qt::transparent);
QPainter p(&disabledPixmap);
p.setOpacity(0.25);
p.drawPixmap(0, 0, Source);
return disabledPixmap;
}
//============================================================================
void DockAreaTitleBarPrivate::createButtons()
{
@ -137,14 +122,14 @@ void DockAreaTitleBarPrivate::createButtons()
CloseButton->setObjectName("closeButton");
CloseButton->setAutoRaise(true);
// The standard icons do does not look good on high DPI screens
// The standard icons do not look good on high DPI screens
QIcon CloseIcon = _this->style()->standardIcon(QStyle::SP_TitleBarCloseButton);
QPixmap normalPixmap = _this->style()->standardPixmap(QStyle::SP_TitleBarCloseButton, 0, CloseButton);
QPixmap disabledPixmap = createTransparentPixmap(normalPixmap);
QPixmap disabledPixmap = internal::createTransparentPixmap(normalPixmap, 0.25);
CloseIcon.addPixmap(disabledPixmap, QIcon::Disabled);
CloseButton->setIcon(CloseIcon);
CloseButton->setToolTip(QObject::tr("Close"));
CloseButton->setToolTip(QObject::tr("Close all tabs"));
CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
TopLayout->addWidget(CloseButton, 0);
_this->connect(CloseButton, SIGNAL(clicked()), SLOT(onCloseButtonClicked()));
@ -236,7 +221,8 @@ void CDockAreaTitleBar::onTabsMenuAboutToShow()
void CDockAreaTitleBar::onCloseButtonClicked()
{
qDebug() << "CDockAreaTitleBar::onCloseButtonClicked";
d->TabBar->closeTab(d->TabBar->currentIndex());
//d->TabBar->closeTab(d->TabBar->currentIndex());
d->DockArea->closeArea();
}
@ -263,8 +249,8 @@ void CDockAreaTitleBar::onCurrentTabChanged(int Index)
{
return;
}
CDockWidget* DockWidget = d->TabBar->tab(Index)->dockWidget();
d->CloseButton->setEnabled(DockWidget->features().testFlag(CDockWidget::DockWidgetClosable));
/*CDockWidget* DockWidget = d->TabBar->tab(Index)->dockWidget();
d->CloseButton->setEnabled(DockWidget->features().testFlag(CDockWidget::DockWidgetClosable));*/
}

View File

@ -82,6 +82,9 @@ public:
*/
QAbstractButton* button(TitleBarButton which) const;
/**
* This function is here for debug reasons
*/
virtual void setVisible(bool Visible) override;
signals:

View File

@ -739,6 +739,16 @@ QAbstractButton* CDockAreaWidget::titleBarButton(TitleBarButton which) const
{
return d->TitleBar->button(which);
}
//============================================================================
void CDockAreaWidget::closeArea()
{
for (auto DockWidget : openedDockWidgets())
{
DockWidget->toggleView(false);
}
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@ -130,6 +130,9 @@ protected:
*/
void internalSetCurrentDockWidget(CDockWidget* DockWidget);
protected slots:
void toggleView(bool Open);
public:
using Super = QFrame;
@ -247,10 +250,9 @@ public slots:
void setCurrentIndex(int index);
/**
* This property controls whether the dock area is open or closed.
* The toogleViewAction triggers this slot.
* Closes the dock area and all dock widgets in this area
*/
void toggleView(bool Open);
void closeArea();
signals:
/**

View File

@ -68,7 +68,6 @@ struct DockWidgetPrivate
CDockAreaWidget* DockArea = nullptr;
QAction* ToggleViewAction;
bool Closed = false;
CDockWidget::LayoutFlags LayoutFlags;
QScrollArea* ScrollArea = nullptr;
QToolBar* ToolBar = nullptr;
Qt::ToolButtonStyle ToolBarStyleDocked = Qt::ToolButtonIconOnly;
@ -182,11 +181,6 @@ void DockWidgetPrivate::updateParentDockArea()
//============================================================================
void DockWidgetPrivate::setupToolBar()
{
if (!LayoutFlags.testFlag(CDockWidget::WithTopToolBar))
{
return;
}
ToolBar = new QToolBar(_this);
ToolBar->setObjectName("dockWidgetToolBar");
Layout->addWidget(ToolBar);
@ -201,11 +195,6 @@ void DockWidgetPrivate::setupToolBar()
//============================================================================
void DockWidgetPrivate::setupScrollArea()
{
if (!LayoutFlags.testFlag(CDockWidget::WithScrollArea))
{
return;
}
ScrollArea = new QScrollArea(_this);
ScrollArea->setObjectName("dockWidgetScrollArea");
ScrollArea->setWidgetResizable(true);
@ -214,20 +203,16 @@ void DockWidgetPrivate::setupScrollArea()
//============================================================================
CDockWidget::CDockWidget(const QString &title, QWidget *parent,
LayoutFlags layoutFlags) :
CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
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);
@ -256,16 +241,14 @@ void CDockWidget::setToggleViewActionChecked(bool Checked)
//============================================================================
void CDockWidget::setWidget(QWidget* widget)
void CDockWidget::setWidget(QWidget* widget, eInsertMode InsertMode)
{
if (d->LayoutFlags.testFlag(WithScrollArea))
QScrollArea* ScrollAreaWidget = qobject_cast<QScrollArea*>(widget);
if (ScrollAreaWidget || ForceNoScrollArea != InsertMode)
{
d->setupScrollArea();
d->ScrollArea->setWidget(widget);
}
else if (d->Widget)
{
d->Layout->replaceWidget(d->Widget, widget);
}
else
{
d->Layout->addWidget(widget);
@ -545,6 +528,18 @@ QToolBar* CDockWidget::toolBar() const
}
//============================================================================
QToolBar* CDockWidget::createDefaultToolBar()
{
if (!d->ToolBar)
{
d->setupToolBar();
}
return d->ToolBar;
}
//============================================================================
void CDockWidget::setToolBar(QToolBar* ToolBar)
{

View File

@ -152,26 +152,12 @@ 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
enum eInsertMode
{
WithScrollArea = 0x01,
WithTopToolBar = 0x02
AutoScrollArea,
ForceScrollArea,
ForceNoScrollArea
};
Q_DECLARE_FLAGS(LayoutFlags, LayoutFlag)
/**
* This mode configures the behavior of the toggle view action.
@ -201,8 +187,7 @@ public:
* by calling setObjectName() after construction.
* Use the layoutFlags to configure the layout of the dock widget.
*/
CDockWidget(const QString &title, QWidget* parent = 0,
LayoutFlags layoutFlags = 0);
CDockWidget(const QString &title, QWidget* parent = 0);
/**
* Virtual Destructor
@ -216,8 +201,22 @@ public:
/**
* Sets the widget for the dock widget to widget.
* The InsertMode defines how the widget is inserted into 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 or to provide a widget that is already a scroll
* area or that contains a scroll area.
* If the InsertMode is AutoScrollArea, the DockWidget tries to automatically
* detect how to insert the given widget. If the widget is derived from
* QScrollArea (i.e. an QAbstractItemView), then the widget is inserted
* directly. If the given widget is not a scroll area, the widget will be
* inserted into a scroll area.
* To force insertion into a scroll area, you can also provide the InsertMode
* ForceScrollArea. To prevent insertion into a scroll area, you can
* provide the InsertMode ForceNoScrollArea
*/
void setWidget(QWidget* widget);
void setWidget(QWidget* widget, eInsertMode InsertMode = AutoScrollArea);
/**
* Returns the widget for the dock widget. This function returns zero if
@ -306,7 +305,7 @@ public:
void setIcon(const QIcon& Icon);
/**
* Returns tzhe icon that has been assigned to the dock widget
* Returns the icon that has been assigned to the dock widget
*/
QIcon icon() const;
@ -314,9 +313,22 @@ public:
* 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.
* This function returns the dock widget top tool bar.
* If no toolbar is assigned, this function returns nullptr. To get a vaild
* toolbar you either need to create a default empty toolbar via
* createDefaultToolBar() function or you need to assign you custom
* toolbar via setToolBar().
*/
QToolBar* toolBar() const;
/**
* If you would like to use the default top tool bar, then call this
* function to create the default tool bar.
* After this function the toolBar() function will return a valid toolBar()
* object.
*/
QToolBar* createDefaultToolBar();
/**
* 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

View File

@ -38,6 +38,8 @@
#include <QApplication>
#include <QSplitter>
#include <QDebug>
#include <QToolButton>
#include <QPushButton>
#include "ads_globals.h"
#include "DockWidget.h"
@ -46,6 +48,8 @@
#include "DockOverlay.h"
#include "DockManager.h"
#include <iostream>
namespace ads
{
/**
@ -60,6 +64,7 @@ enum eDragState
};
using tTabLabel = CElidingLabel;
using tCloseButton = QPushButton;
/**
* Private data class of CDockWidgetTab class (pimpl)
@ -76,6 +81,8 @@ struct DockWidgetTabPrivate
eDragState DragState = DraggingInactive;
CFloatingDockContainer* FloatingWidget = nullptr;
QIcon Icon;
tCloseButton* CloseButton = nullptr;
QSpacerItem* IconTextSpacer;
/**
* Private data constructor
@ -131,22 +138,39 @@ DockWidgetTabPrivate::DockWidgetTabPrivate(CDockWidgetTab* _public) :
//============================================================================
void DockWidgetTabPrivate::createLayout()
{
QBoxLayout* l = new QBoxLayout(QBoxLayout::LeftToRight);
l->setContentsMargins(0, 0, 0, 0);
_this->setLayout(l);
IconLabel = new QLabel();
IconLabel->setAlignment(Qt::AlignVCenter);
IconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
l->addWidget(IconLabel, Qt::AlignVCenter);
TitleLabel = new tTabLabel();
TitleLabel->setElideMode(Qt::ElideRight);
TitleLabel->setText(DockWidget->windowTitle());
TitleLabel->setObjectName("dockWidgetTabLabel");
l->addWidget(TitleLabel, 1);
TitleLabel->setAlignment(Qt::AlignCenter);
CloseButton = new tCloseButton();
CloseButton->setObjectName("tabCloseButton");
// The standard icons do does not look good on high DPI screens
QIcon CloseIcon = _this->style()->standardIcon(QStyle::SP_TitleBarCloseButton);
QPixmap normalPixmap = _this->style()->standardPixmap(QStyle::SP_TitleBarCloseButton, 0, CloseButton);
QPixmap disabledPixmap = internal::createTransparentPixmap(normalPixmap, 0.25);
CloseIcon.addPixmap(disabledPixmap, QIcon::Disabled);
CloseButton->setIcon(CloseIcon);
CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
CloseButton->setVisible(false);
CloseButton->setToolTip(QObject::tr("Close Tab"));
_this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeButtonClicked()));
QFontMetrics fm(TitleLabel->font());
int Spacing = qRound(fm.height() / 4.0);
// Fill the layout
QBoxLayout* Layout = new QBoxLayout(QBoxLayout::LeftToRight);
Layout->setContentsMargins(2 * Spacing,0,0,0);
Layout->setSpacing(0);
_this->setLayout(Layout);
Layout->addWidget(TitleLabel, 1);
Layout->addSpacing(Spacing);
Layout->addWidget(CloseButton);
Layout->addSpacing(qRound(Spacing * 4.0 / 3.0));
Layout->setAlignment(Qt::AlignCenter);
IconLabel->setVisible(false);
TitleLabel->setVisible(true);
}
@ -323,6 +347,7 @@ bool CDockWidgetTab::isActiveTab() const
//============================================================================
void CDockWidgetTab::setActiveTab(bool active)
{
d->CloseButton->setVisible(active && d->DockWidget->features().testFlag(CDockWidget::DockWidgetClosable));
if (d->IsActiveTab == active)
{
return;
@ -363,8 +388,15 @@ CDockAreaWidget* CDockWidgetTab::dockAreaWidget() const
//============================================================================
void CDockWidgetTab::setIcon(const QIcon& Icon)
{
QBoxLayout* Layout = qobject_cast<QBoxLayout*>(layout());
d->Icon = Icon;
d->IconLabel = new QLabel();
d->IconLabel->setAlignment(Qt::AlignVCenter);
d->IconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
d->IconLabel->setToolTip(d->TitleLabel->toolTip());
d->IconLabel->setPixmap(Icon.pixmap(this->windowHandle(), QSize(16, 16)));
Layout->insertWidget(0, d->IconLabel, Qt::AlignVCenter);
Layout->insertSpacing(1, qRound(1.5 * Layout->contentsMargins().left() / 2.0));
d->IconLabel->setVisible(true);
}
@ -405,6 +437,7 @@ void CDockWidgetTab::setVisible(bool visible)
Super::setVisible(visible);
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@ -127,6 +127,7 @@ public slots:
signals:
void activeTabChanged();
void clicked();
void closeButtonClicked();
void moved(const QPoint& GlobalPos);
}; // class DockWidgetTab
}

View File

@ -117,6 +117,7 @@ void CElidingLabel::setElideMode(Qt::TextElideMode mode)
//============================================================================
void CElidingLabel::mouseReleaseEvent(QMouseEvent* event)
{
Super::mouseReleaseEvent(event);
if (event->button() != Qt::LeftButton)
{
return;
@ -131,6 +132,7 @@ void CElidingLabel::mouseDoubleClickEvent( QMouseEvent *ev )
{
Q_UNUSED(ev)
emit doubleClicked();
Super::mouseDoubleClickEvent(ev);
}
@ -141,7 +143,7 @@ void CElidingLabel::resizeEvent(QResizeEvent *event)
{
d->elideText(event->size().width());
}
QLabel::resizeEvent(event);
Super::resizeEvent(event);
}

View File

@ -29,6 +29,7 @@
// INCLUDES
//============================================================================
#include <QVariant>
#include <QPainter>
#include "DockSplitter.h"
#include "ads_globals.h"
@ -73,6 +74,19 @@ CDockInsertParam dockAreaInsertParameters(DockWidgetArea Area)
return CDockInsertParam(Qt::Vertical, false);
}
//============================================================================
QPixmap createTransparentPixmap(const QPixmap& Source, qreal Opacity)
{
QPixmap TransparentPixmap(Source.size());
TransparentPixmap.fill(Qt::transparent);
QPainter p(&TransparentPixmap);
p.setOpacity(Opacity);
p.drawPixmap(0, 0, Source);
return TransparentPixmap;
}
} // namespace internal
} // namespace ads

View File

@ -32,6 +32,7 @@
//============================================================================
#include <QPair>
#include <QtCore/QtGlobal>
#include <QPixmap>
#ifdef ADS_SHARED_EXPORT
#define ADS_EXPORT Q_DECL_EXPORT
@ -125,6 +126,13 @@ T findParent(const QWidget* w)
return 0;
}
/**
* Creates a semi transparent pixmap from the given pixmap Source.
* The Opacity parameter defines the opacity from completely transparent (0.0)
* to completely opaque (1.0)
*/
QPixmap createTransparentPixmap(const QPixmap& Source, qreal Opacity);
} // namespace internal
} // namespace ads

View File

@ -25,19 +25,20 @@ ads--CDockAreaWidget #tabsMenuButton::menu-indicator
image: none;
}
ads--CDockWidgetTab
{
background: palette(window);
border-color: palette(light);
border-style: solid;
border-width: 0 1px 0 0;
padding: 0 9px;
padding: 0 0px;
}
ads--CDockWidgetTab[activeTab="true"]
{
/*background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:0.5, stop:0 palette(window), stop:1 palette(light));*/
background: palette(highlight);
background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:0.5, stop:0 palette(window), stop:1 palette(light));
/*background: palette(highlight);*/
}
ads--CDockWidgetTab QLabel
@ -58,14 +59,14 @@ ads--CDockWidget
border-width: 1px 0 0 0;
}
#tabsMenuButton,
#closeButton,
#tabsMenuButton
#undockButton
{
padding: 0px;
padding: 0 -2px;
}
QScrollArea#dockWidgetScrollArea
{
padding: 0px;
@ -73,3 +74,23 @@ QScrollArea#dockWidgetScrollArea
}
#tabCloseButton
{
margin-top: 2px;
background: none;
border: none;
padding: 0px -2px;
}
#tabCloseButton:hover
{
border: 1px solid rgba(0, 0, 0, 32);
background: rgba(0, 0, 0, 16);
}
#tabCloseButton:pressed
{
background: rgba(0, 0, 0, 32);
}