forked from qt-creator/qt-creator
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:
committed by
Thomas Hartmann
parent
d5ac552314
commit
92c7662acb
@@ -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
|
||||
|
@@ -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.
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user