ADS: Integrate newest base repository commits

998fe9fa11939eb28dd021ca11d5302c4fe2a005
28dc374fc25fcf5a4100c7ad929cb8da690530ed
0e88467f94194d5bea209f6ddc364358ab92899e
d0f4ce324890197683869eafda0f3938ae619b8d
c541f2c69b519eceb76ffc54589175c9fd0da8a6
37d305e50d2c0829f031b71a61e290361eea9f07

- Fix/workaround for escape key issue with remaining overlays
- Clean up if statements according to style guide

Task-number: QDS-1883
Change-Id: I44ddaed67458a75aca91bdd74cd2b5890bd23c38
Reviewed-by: Aleksei German <aleksei.german@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Henning Gruendl
2020-04-06 14:25:11 +02:00
committed by Thomas Hartmann
parent d5ac552314
commit 92c7662acb
6 changed files with 151 additions and 51 deletions

View File

@@ -215,6 +215,7 @@ namespace ADS
DockManager *m_dockManager = nullptr;
bool m_updateTitleBarButtons = false;
DockWidgetAreas m_allowedAreas = AllDockAreas;
QSize m_minSizeHint;
/**
* Private data constructor
@@ -264,6 +265,22 @@ namespace ADS
* 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()
{
m_minSizeHint = QSize();
for (int i = 0; i < m_contentsLayout->count(); ++i)
{
auto widget = m_contentsLayout->widget(i);
m_minSizeHint.setHeight(qMax(m_minSizeHint.height(),
widget->minimumSizeHint().height()));
m_minSizeHint.setWidth(qMax(m_minSizeHint.width(),
widget->minimumSizeHint().width()));
}
}
};
// struct DockAreaWidgetPrivate
@@ -349,6 +366,10 @@ namespace ADS
d->tabBar()->blockSignals(false);
tabWidget->setVisible(!dockWidget->isClosed());
dockWidget->setProperty(INDEX_PROPERTY, index);
d->m_minSizeHint.setHeight(qMax(d->m_minSizeHint.height(),
dockWidget->minimumSizeHint().height()));
d->m_minSizeHint.setWidth(qMax(d->m_minSizeHint.width(),
dockWidget->minimumSizeHint().width()));
if (activate) {
setCurrentIndex(index);
}
@@ -381,6 +402,7 @@ namespace ADS
d->updateTitleBarButtonStates();
updateTitleBarVisibility();
d->updateMinimumSizeHint();
auto topLevelDockWidget = dockContainerWidget->topLevelDockWidget();
if (topLevelDockWidget) {
topLevelDockWidget->emitTopLevelChanged(true);
@@ -683,4 +705,9 @@ namespace ADS
DockAreaTitleBar *DockAreaWidget::titleBar() const { return d->m_titleBar; }
QSize DockAreaWidget::minimumSizeHint() const
{
return d->m_minSizeHint.isValid() ? d->m_minSizeHint : Super::minimumSizeHint();
}
} // namespace ADS

View File

@@ -291,6 +291,13 @@ public:
*/
void closeOtherAreas();
/**
* 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;
signals:
/**
* This signal is emitted when user clicks on a tab at an index.

View File

@@ -83,6 +83,7 @@ namespace ADS
QSize m_toolBarIconSizeFloating = QSize(24, 24);
bool m_isFloatingTopLevel = false;
QList<QAction *> m_titleBarActions;
DockWidget::eMinimumSizeHintMode m_minimumSizeHintMode = DockWidget::MinimumSizeHintFromDockWidget;
/**
* Private data constructor
@@ -317,6 +318,11 @@ namespace ADS
}
}
void DockWidget::setMinimumSizeHintMode(eMinimumSizeHintMode mode)
{
d->m_minimumSizeHintMode = mode;
}
void DockWidget::toggleView(bool open)
{
// If the toggle view action mode is ActionModeShow, then Open is always
@@ -545,7 +551,13 @@ namespace ADS
void DockWidget::setClosedState(bool closed) { d->m_closed = closed; }
QSize DockWidget::minimumSizeHint() const { return QSize(60, 40); }
QSize DockWidget::minimumSizeHint() const
{
if (d->m_minimumSizeHintMode == DockWidget::MinimumSizeHintFromDockWidget || !d->m_widget)
return QSize(60, 40);
else
return d->m_widget->minimumSizeHint();
}
void DockWidget::setFloating()
{
@@ -587,6 +599,7 @@ namespace ADS
floatingWidget->hide();
}
deleteDockWidget();
emit closed();
} else {
toggleView(false);
}

View File

@@ -184,6 +184,17 @@ public:
*/
enum eInsertMode { AutoScrollArea, ForceScrollArea, ForceNoScrollArea };
/**
* The mode of the minimumSizeHint() that is returned by the DockWidget
* minimumSizeHint() function.
* To ensure, that a dock widget does not block resizing, the dock widget
* reimplements minimumSizeHint() function to return a very small minimum
* size hint. If you would like to adhere the minimumSizeHint() from the
* content widget, the set the minimumSizeHintMode() to
* MinimumSizeHintFromContent.
*/
enum eMinimumSizeHintMode { MinimumSizeHintFromDockWidget, MinimumSizeHintFromContent };
/**
* This mode configures the behavior of the toggle view action.
* If the mode if ActionModeToggle, then the toggle view action is
@@ -218,7 +229,8 @@ public:
virtual ~DockWidget() override;
/**
* We return a fixed minimum size hint for all dock widgets
* We return a fixed minimum size hint or the size hint of the content
* widget if minimum size hint mode is MinimumSizeHintFromContent
*/
virtual QSize minimumSizeHint() const override;
@@ -327,6 +339,13 @@ public:
*/
void setToggleViewActionMode(eToggleViewActionMode mode);
/**
* Configures the minimum size hint that is returned by the
* minimumSizeHint() function.
* \see eMinimumSizeHintMode for a detailed description
*/
void setMinimumSizeHintMode(eMinimumSizeHintMode mode);
/**
* Sets the dock widget icon that is shown in tabs and in toggle view
* actions
@@ -339,13 +358,10 @@ 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.
* This function returns the dock widget top tool bar.
* If no toolbar is assigned, this function returns nullptr. To get a valid
* toolbar you either need to create a default empty toolbar via
* createDefaultToolBar() function or you need to assign you custom
* createDefaultToolBar() function or you need to assign your custom
* toolbar via setToolBar().
*/
QToolBar *toolBar() const;

View File

@@ -73,6 +73,7 @@ namespace ADS
QPoint m_dragStartMousePosition;
DockContainerWidget *m_dropContainer = nullptr;
DockAreaWidget *m_singleDockArea = nullptr;
QPoint m_dragStartPos;
QWidget *m_mouseEventHandler = nullptr;
FloatingWidgetTitleBar *m_titleBar = nullptr;
@@ -107,25 +108,30 @@ namespace ADS
q->setWindowTitle(text);
}
/**
* Reflect the current dock widget title in the floating widget windowTitle()
* depending on the DockManager::FloatingContainerHasWidgetTitle flag
*/
void reflectCurrentWidget(DockWidget *currentWidget)
{
// reflect CurrentWidget's title if configured to do so, otherwise display application name as window title
if (testConfigFlag(DockManager::FloatingContainerHasWidgetTitle)) {
if (testConfigFlag(DockManager::FloatingContainerHasWidgetTitle))
setWindowTitle(currentWidget->windowTitle());
} else {
else
setWindowTitle(QApplication::applicationDisplayName());
}
// reflect CurrentWidget's icon if configured to do so, otherwise display application icon as window icon
QIcon CurrentWidgetIcon = currentWidget->icon();
if (testConfigFlag(DockManager::FloatingContainerHasWidgetIcon)
&& !CurrentWidgetIcon.isNull())
{
// reflect currentWidget's icon if configured to do so, otherwise display application icon as window icon
QIcon currentWidgetIcon = currentWidget->icon();
if (testConfigFlag(DockManager::FloatingContainerHasWidgetIcon) && !currentWidgetIcon.isNull())
q->setWindowIcon(currentWidget->icon());
} else {
else
q->setWindowIcon(QApplication::windowIcon());
}
}
/**
* Handles escape key press when dragging around the floating widget
*/
void handleEscapeKey();
}; // class FloatingDockContainerPrivate
FloatingDockContainerPrivate::FloatingDockContainerPrivate(FloatingDockContainer *parent)
@@ -135,17 +141,15 @@ namespace ADS
void FloatingDockContainerPrivate::titleMouseReleaseEvent()
{
setState(DraggingInactive);
if (!m_dropContainer) {
if (!m_dropContainer)
return;
}
if (m_dockManager->dockAreaOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea
|| m_dockManager->containerOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea) {
// Resize the floating widget to the size of the highlighted drop area rectangle
DockOverlay *overlay = m_dockManager->containerOverlay();
if (!overlay->dropOverlayRect().isValid()) {
if (!overlay->dropOverlayRect().isValid())
overlay = m_dockManager->dockAreaOverlay();
}
QRect rect = overlay->dropOverlayRect();
int frameWidth = (q->frameSize().width() - q->rect().width()) / 2;
@@ -165,26 +169,22 @@ namespace ADS
void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &globalPosition)
{
if (!q->isVisible() || !m_dockManager) {
if (!q->isVisible() || !m_dockManager)
return;
}
auto containers = m_dockManager->dockContainers();
DockContainerWidget *topContainer = nullptr;
for (auto containerWidget : containers) {
if (!containerWidget->isVisible()) {
if (!containerWidget->isVisible())
continue;
}
if (m_dockContainer == containerWidget) {
if (m_dockContainer == containerWidget)
continue;
}
QPoint mappedPos = containerWidget->mapFromGlobal(globalPosition);
if (containerWidget->rect().contains(mappedPos)) {
if (!topContainer || containerWidget->isInFrontOf(topContainer)) {
if (!topContainer || containerWidget->isInFrontOf(topContainer))
topContainer = containerWidget;
}
}
}
@@ -223,6 +223,14 @@ namespace ADS
}
}
void FloatingDockContainerPrivate::handleEscapeKey()
{
qCInfo(adsLog) << Q_FUNC_INFO;
setState(DraggingInactive);
m_dockManager->containerOverlay()->hideOverlay();
m_dockManager->dockAreaOverlay()->hideOverlay();
}
FloatingDockContainer::FloatingDockContainer(DockManager *dockManager)
: FloatingWidgetBaseType(dockManager)
, d(new FloatingDockContainerPrivate(this))
@@ -268,9 +276,8 @@ namespace ADS
d->m_titleBar->enableCloseButton(isClosable());
auto dw = topLevelDockWidget();
if (dw) {
if (dw)
dw->emitTopLevelChanged(true);
}
}
FloatingDockContainer::FloatingDockContainer(DockWidget *dockWidget)
@@ -281,17 +288,16 @@ namespace ADS
d->m_titleBar->enableCloseButton(isClosable());
auto dw = topLevelDockWidget();
if (dw) {
if (dw)
dw->emitTopLevelChanged(true);
}
}
FloatingDockContainer::~FloatingDockContainer()
{
qCInfo(adsLog) << Q_FUNC_INFO;
if (d->m_dockManager) {
if (d->m_dockManager)
d->m_dockManager->removeFloatingWidget(this);
}
delete d;
}
@@ -312,6 +318,10 @@ namespace ADS
QWidget::moveEvent(event);
switch (d->m_draggingState) {
case DraggingMousePressed:
// TODO Is checking for windows only sufficient or has macOS also problems?
if (Utils::HostOsInfo::isWindowsHost())
QApplication::instance()->installEventFilter(this);
d->setState(DraggingFloatingWidget);
d->updateDropOverlays(QCursor::pos());
break;
@@ -340,9 +350,8 @@ namespace ADS
if (isClosable()) {
auto dw = topLevelDockWidget();
if (dw && dw->features().testFlag(DockWidget::DockWidgetDeleteOnClose)) {
if (!dw->closeDockWidgetInternal()) {
if (!dw->closeDockWidgetInternal())
return;
}
}
this->hide();
@@ -352,19 +361,16 @@ namespace ADS
void FloatingDockContainer::hideEvent(QHideEvent *event)
{
Super::hideEvent(event);
if (event->spontaneous()) {
if (event->spontaneous())
return;
}
// Prevent toogleView() events during restore state
if (d->m_dockManager->isRestoringState()) {
if (d->m_dockManager->isRestoringState())
return;
}
for (auto dockArea : d->m_dockContainer->openedDockAreas()) {
for (auto dockWidget : dockArea->openedDockWidgets()) {
for (auto dockWidget : dockArea->openedDockWidgets())
dockWidget->toggleView(false);
}
}
}
@@ -379,22 +385,21 @@ namespace ADS
// QEvent::NonClientAreaMouseButtonPress return the wrong mouse button
// The event always returns Qt::RightButton even if the left button is clicked.
// It is really great to work around the whole NonClientMouseArea bugs
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 2))
if (event->type()
== QEvent::
NonClientAreaMouseButtonPress /*&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)*/) {
qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::NonClientAreaMouseButtonPress"
<< event->type();
d->setState(DraggingMousePressed);
}
if (event->type() == QEvent::NonClientAreaMouseButtonPress
/*&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)*/)
#else
if (event->type() == QEvent::NonClientAreaMouseButtonPress
&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)) {
&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton))
#endif
{
qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::NonClientAreaMouseButtonPress"
<< event->type();
d->m_dragStartPos = pos();
d->setState(DraggingMousePressed);
}
#endif
} break;
case DraggingMousePressed:
@@ -440,6 +445,37 @@ namespace ADS
return QWidget::event(event);
}
bool FloatingDockContainer::eventFilter(QObject *watched, QEvent *event)
{
Q_UNUSED(watched);
// I have not found a way to detect non client area key press events to
// handle escape key presses. On Windows, if the escape key is pressed while
// dragging around a widget, the widget position is reset to its start position
// which in turn generates a QEvent::NonClientAreaMouseButtonRelease event
// if the mouse is outside of the widget after the move to its initial position
// or a QEvent::MouseButtonRelease event, if the mouse is inside of the widget
// after the position has been reset.
// So we can install an event filter on the application to get these events
// here to properly cancel dragging and hide the overlays.
// If we are in DraggingFloatingWidget state, it means the widget
// has been dragged already but if the position is the same like
// the start position, then this is an indication that the escape
// key has been pressed.
if (event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::NonClientAreaMouseButtonRelease)
{
qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::MouseButtonRelease or QEvent::NonClientAreaMouseButtonRelease"
<< "d->m_draggingState " << d->m_draggingState;
QApplication::instance()->removeEventFilter(this);
if (d->m_dragStartPos == pos())
{
d->handleEscapeKey();
return true;
}
return false;
}
return false;
}
void FloatingDockContainer::startFloating(const QPoint &dragStartMousePos,
const QSize &size,
eDragState dragState,

View File

@@ -188,6 +188,7 @@ protected: // reimplements QWidget
virtual void closeEvent(QCloseEvent *event) override;
virtual void hideEvent(QHideEvent *event) override;
virtual void showEvent(QShowEvent *event) override;
virtual bool eventFilter(QObject *watched, QEvent *event) override;
public:
using Super = QWidget;