forked from qt-creator/qt-creator
ADS: Integrate newest base repository commits
* Activate new ADS feature focus highlight * Remove resources.qrc and related *.svg files * Clean up new and existing source Base repository was merged until commit 3de877fe5635ff51a6d1205ca98aad85d204427f Merged changes from base repository include the following: * Fix wrong current index when removing a widget from DockAreaLayout * Fix invisible TabWidget for DockWidgets that are not part of a restored state * Enable ClickFocus for DockWidget to support focussing in case the content does not support it * Move focus related functionality into DockFocusController class * Add new DockManger config flag FocusStyling * Add support for focus styling of FloatingWidgetTitleBar * Improve focus handling when dropping a DockWidget * Improve highlighting focused DockWidget * Improve setting of DockWidgetTab focus * Add styling of focused DockWidget * Fix docking of floating widgets for macOS * Fix setting of DockingStateReader file version - use internal file version instead of user file version * Fix saveState() and restoreState() version handling to work like the function from QMainWindow * Fix escape key handling in native window event function if event WM_EXITSIZEMOVE occurs * Implement windows drag handling with native WM_ nonclient area messages * Fix showing DockArea when inserting a DockWidget in a hidden DockArea * Fix setting DockAreaTabBar index to prevent showing of tab 0 when inserting a DockWidget into an area with no current index tab * Fix wrong insertion order of DockWidget when dropping a floating widget to the left or top container drop area * Fix tab changes position when redocking it to the same position * Add nullptr check to fix potential nullptr access when closing a FloatingDockContainer * Fix single DockArea cannot be split * Fix visibility issue when adding dock widget after all other dock widgets have ben closed * Fix FloatingDragPreview flashing of hidden overlay when dragging the last visible DockWidget in non opaque docking mode * Fix FloatingDragPreview preventing dock widget from floating when dragging over another dock widget * Fix DockWidget::setWidget function to test for QAbstractScrollArea instead of QScrollArea. Now setWidget properly supports ItemViews like QTreeView or QTableView * Fix wrong display of center drop area when dragging over invisible dock area title bar * Fix bug that drop overlay sometimes was not visible when moving the drag preview over a floating window * Fix dropping of FloatingDragPreview into center of dock container with only one single visible dock area. If this happens the dropped dock widget needs to get tabified * Fix crash when trying to make a DockWidget floating in non-opaque mode if the DockWidget is not floatable * Fix DockWidgetTab to provide the right size when starting floating * Add DockWidget functions setAsCurrentTab, raise, isCurrentTab, isTabbed * Add new config flag HideSingleCentralWidgetTitleBar to enable a central single dock widget in the main dock container (dock manager) without titlebar * Fix DockContainerWidget::hasTopLevelDockWidget() and DockContainerWidget::topLevelDockArea() to work properly also for the main non floating dock container * Fix ElidingLabel to properly support Qt::ElideNone * Add setElideMode function to DockWidgetTab * Add setFullScreen(), setNormal() and isFullScreen() function to DockWidget * Fix takeWidget() function and fixed setWidget() function to handle case when there is already a content widget Task-number: QDS-2180 Change-Id: Ie30648ba329016c91fd19e9b4e12e31e47614b18 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
committed by
Henning Gründl
parent
e5d9cb3779
commit
a98c254c59
@@ -7,6 +7,7 @@ add_qtc_library(AdvancedDockingSystem
|
||||
dockareawidget.cpp dockareawidget.h
|
||||
dockcomponentsfactory.cpp dockcomponentsfactory.h
|
||||
dockcontainerwidget.cpp dockcontainerwidget.h
|
||||
dockfocuscontroller.cpp dockfocuscontroller.h
|
||||
dockingstatereader.cpp dockingstatereader.h
|
||||
dockmanager.cpp dockmanager.h
|
||||
dockoverlay.cpp dockoverlay.h
|
||||
@@ -21,7 +22,6 @@ add_qtc_library(AdvancedDockingSystem
|
||||
workspacemodel.cpp workspacemodel.h
|
||||
workspaceview.cpp workspaceview.h
|
||||
workspacedialog.ui
|
||||
resources.qrc
|
||||
)
|
||||
|
||||
extend_qtc_library(AdvancedDockingSystem
|
||||
|
@@ -41,6 +41,7 @@
|
||||
|
||||
#include <QAbstractButton>
|
||||
#include <QPainter>
|
||||
#include <QStyle>
|
||||
#include <QVariant>
|
||||
|
||||
namespace ADS {
|
||||
@@ -93,7 +94,7 @@ void hideEmptyParentSplitters(DockSplitter *splitter)
|
||||
}
|
||||
}
|
||||
|
||||
void setButtonIcon(QAbstractButton* button,
|
||||
void setButtonIcon(QAbstractButton *button,
|
||||
QStyle::StandardPixmap standarPixmap,
|
||||
ADS::eIcon customIconId)
|
||||
{
|
||||
@@ -116,5 +117,25 @@ void setButtonIcon(QAbstractButton* button,
|
||||
}
|
||||
}
|
||||
|
||||
void repolishStyle(QWidget *widget, eRepolishChildOptions options)
|
||||
{
|
||||
if (!widget)
|
||||
return;
|
||||
|
||||
widget->style()->unpolish(widget);
|
||||
widget->style()->polish(widget);
|
||||
|
||||
if (RepolishIgnoreChildren == options)
|
||||
return;
|
||||
|
||||
QList<QWidget*> children = widget->findChildren<QWidget *>(QString(),
|
||||
(RepolishDirectChildren == options) ? Qt::FindDirectChildrenOnly : Qt::FindChildrenRecursively);
|
||||
for (auto w : children)
|
||||
{
|
||||
w->style()->unpolish(w);
|
||||
w->style()->polish(w);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ADS
|
||||
|
@@ -72,8 +72,6 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace ADS {
|
||||
|
||||
enum eStateFileVersion { InitialVerison = 0, Version1 = 1, CurrentVersion = Version1 };
|
||||
|
||||
class DockSplitter;
|
||||
|
||||
enum DockWidgetArea {
|
||||
@@ -228,5 +226,18 @@ void setToolTip(QObjectPtr obj, const QString &tip)
|
||||
void setButtonIcon(QAbstractButton *button, QStyle::StandardPixmap standarPixmap,
|
||||
ADS::eIcon CustomIconId);
|
||||
|
||||
enum eRepolishChildOptions
|
||||
{
|
||||
RepolishIgnoreChildren,
|
||||
RepolishDirectChildren,
|
||||
RepolishChildrenRecursively
|
||||
};
|
||||
|
||||
/**
|
||||
* Calls unpolish() / polish for the style of the given widget to update
|
||||
* stylesheet if a property changes
|
||||
*/
|
||||
void repolishStyle(QWidget *widget, eRepolishChildOptions options = RepolishIgnoreChildren);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ADS
|
||||
|
@@ -5,9 +5,6 @@ shared {
|
||||
}
|
||||
|
||||
## Input
|
||||
RESOURCES += \
|
||||
resources.qrc
|
||||
|
||||
HEADERS += \
|
||||
ads_globals.h \
|
||||
dockareatabbar.h \
|
||||
@@ -15,6 +12,7 @@ HEADERS += \
|
||||
dockareawidget.h \
|
||||
dockcomponentsfactory.h \
|
||||
dockcontainerwidget.h \
|
||||
dockfocuscontroller.h \
|
||||
dockingstatereader.h \
|
||||
dockmanager.h \
|
||||
dockoverlay.h \
|
||||
@@ -36,6 +34,7 @@ SOURCES += \
|
||||
dockareawidget.cpp \
|
||||
dockcomponentsfactory.cpp \
|
||||
dockcontainerwidget.cpp \
|
||||
dockfocuscontroller.cpp \
|
||||
dockingstatereader.cpp \
|
||||
dockmanager.cpp \
|
||||
dockoverlay.cpp \
|
||||
|
@@ -19,6 +19,7 @@ QtcLibrary {
|
||||
"dockareawidget.cpp", "dockareawidget.h",
|
||||
"dockcomponentsfactory.cpp", "dockcomponentsfactory.h",
|
||||
"dockcontainerwidget.cpp", "dockcontainerwidget.h",
|
||||
"dockfocuscontroller.cpp", "dockfocuscontroller.h",
|
||||
"dockingstatereader.cpp", "dockingstatereader.h",
|
||||
"dockmanager.cpp", "dockmanager.h",
|
||||
"dockoverlay.cpp", "dockoverlay.h",
|
||||
@@ -32,8 +33,7 @@ QtcLibrary {
|
||||
"workspacedialog.cpp", "workspacedialog.h",
|
||||
"workspacemodel.cpp", "workspacemodel.h",
|
||||
"workspaceview.cpp", "workspaceview.h",
|
||||
"workspacedialog.ui",
|
||||
"resources.qrc"
|
||||
"workspacedialog.ui"
|
||||
]
|
||||
}
|
||||
|
||||
|
@@ -82,12 +82,12 @@ namespace ADS
|
||||
/**
|
||||
* Convenience function to access first tab
|
||||
*/
|
||||
DockWidgetTab *firstTab() const {return q->tab(0);}
|
||||
DockWidgetTab *firstTab() const { return q->tab(0); }
|
||||
|
||||
/**
|
||||
* Convenience function to access last tab
|
||||
*/
|
||||
DockWidgetTab *lastTab() const {return q->tab(q->count() - 1);}
|
||||
DockWidgetTab *lastTab() const { return q->tab(q->count() - 1); }
|
||||
}; // class DockAreaTabBarPrivate
|
||||
|
||||
DockAreaTabBarPrivate::DockAreaTabBarPrivate(DockAreaTabBar *parent)
|
||||
@@ -140,12 +140,11 @@ namespace ADS
|
||||
{
|
||||
event->accept();
|
||||
const int direction = event->angleDelta().y();
|
||||
if (direction < 0) {
|
||||
if (direction < 0)
|
||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + 20);
|
||||
} else {
|
||||
else
|
||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - 20);
|
||||
}
|
||||
}
|
||||
|
||||
void DockAreaTabBar::setCurrentIndex(int index)
|
||||
{
|
||||
@@ -189,9 +188,11 @@ namespace ADS
|
||||
&DockAreaTabBar::elidedChanged);
|
||||
dockWidgetTab->installEventFilter(this);
|
||||
emit tabInserted(index);
|
||||
if (index <= d->m_currentIndex || d->m_currentIndex == -1) {
|
||||
if (index <= d->m_currentIndex)
|
||||
setCurrentIndex(d->m_currentIndex + 1);
|
||||
}
|
||||
else if (d->m_currentIndex == -1)
|
||||
setCurrentIndex(index);
|
||||
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
@@ -235,11 +236,11 @@ namespace ADS
|
||||
dockWidgetTab->disconnect(this);
|
||||
dockWidgetTab->removeEventFilter(this);
|
||||
qCInfo(adsLog) << "NewCurrentIndex " << newCurrentIndex;
|
||||
if (newCurrentIndex != d->m_currentIndex) {
|
||||
if (newCurrentIndex != d->m_currentIndex)
|
||||
setCurrentIndex(newCurrentIndex);
|
||||
} else {
|
||||
else
|
||||
d->updateTabs();
|
||||
}
|
||||
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
@@ -247,13 +248,12 @@ namespace ADS
|
||||
|
||||
DockWidgetTab *DockAreaTabBar::currentTab() const
|
||||
{
|
||||
if (d->m_currentIndex < 0) {
|
||||
if (d->m_currentIndex < 0)
|
||||
return nullptr;
|
||||
} else {
|
||||
else
|
||||
return qobject_cast<DockWidgetTab *>(
|
||||
d->m_tabsLayout->itemAt(d->m_currentIndex)->widget());
|
||||
}
|
||||
}
|
||||
|
||||
void DockAreaTabBar::onTabClicked()
|
||||
{
|
||||
@@ -292,12 +292,11 @@ namespace ADS
|
||||
// If the the dock widget blocks closing, i.e. if the flag
|
||||
// CustomCloseHandling is set, and the dock widget is still open,
|
||||
// then we do not need to correct the index
|
||||
if (currentTab->dockWidget()->isClosed()) {
|
||||
if (currentTab->dockWidget()->isClosed())
|
||||
i -= offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DockWidgetTab *DockAreaTabBar::tab(int index) const
|
||||
{
|
||||
|
@@ -103,10 +103,11 @@ namespace ADS
|
||||
|
||||
/**
|
||||
* Returns true if the given config flag is set
|
||||
* Convenience function to ease config flag testing
|
||||
*/
|
||||
static bool testConfigFlag(DockManager::eConfigFlag flag)
|
||||
{
|
||||
return DockManager::configFlags().testFlag(flag);
|
||||
return DockManager::testConfigFlag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,7 +160,7 @@ namespace ADS
|
||||
|
||||
// Undock button
|
||||
m_undockButton = new TitleBarButton(testConfigFlag(DockManager::DockAreaHasUndockButton));
|
||||
m_undockButton->setObjectName("undockButton");
|
||||
m_undockButton->setObjectName("detachGroupButton");
|
||||
m_undockButton->setAutoRaise(true);
|
||||
internal::setToolTip(m_undockButton, QObject::tr("Detach Group"));
|
||||
internal::setButtonIcon(m_undockButton,
|
||||
@@ -175,16 +176,16 @@ namespace ADS
|
||||
|
||||
// Close button
|
||||
m_closeButton = new TitleBarButton(testConfigFlag(DockManager::DockAreaHasCloseButton));
|
||||
m_closeButton->setObjectName("closeButton");
|
||||
m_closeButton->setObjectName("dockAreaCloseButton");
|
||||
m_closeButton->setAutoRaise(true);
|
||||
internal::setButtonIcon(m_closeButton,
|
||||
QStyle::SP_TitleBarCloseButton,
|
||||
ADS::DockAreaCloseIcon);
|
||||
if (testConfigFlag(DockManager::DockAreaCloseButtonClosesTab)) {
|
||||
if (testConfigFlag(DockManager::DockAreaCloseButtonClosesTab))
|
||||
internal::setToolTip(m_closeButton, QObject::tr("Close Active Tab"));
|
||||
} else {
|
||||
else
|
||||
internal::setToolTip(m_closeButton, QObject::tr("Close Group"));
|
||||
}
|
||||
|
||||
m_closeButton->setSizePolicy(sizePolicy);
|
||||
m_closeButton->setIconSize(iconSize);
|
||||
m_layout->addWidget(m_closeButton, 0);
|
||||
@@ -238,7 +239,7 @@ namespace ADS
|
||||
{
|
||||
QSize size = m_dockArea->size();
|
||||
m_dragState = dragState;
|
||||
bool opaqueUndocking = DockManager::configFlags().testFlag(DockManager::OpaqueUndocking)
|
||||
bool opaqueUndocking = DockManager::testConfigFlag(DockManager::OpaqueUndocking)
|
||||
|| (DraggingFloatingWidget != dragState);
|
||||
FloatingDockContainer *floatingDockContainer = nullptr;
|
||||
AbstractFloatingWidget *floatingWidget;
|
||||
@@ -269,9 +270,9 @@ namespace ADS
|
||||
}
|
||||
|
||||
TitleBarButton::TitleBarButton(bool visible, QWidget *parent)
|
||||
: TitleBarButtonType(parent),
|
||||
m_visible(visible),
|
||||
m_hideWhenDisabled(DockAreaTitleBarPrivate::testConfigFlag(DockManager::DockAreaHideDisabledButtons))
|
||||
: TitleBarButtonType(parent)
|
||||
, m_visible(visible)
|
||||
, m_hideWhenDisabled(DockAreaTitleBarPrivate::testConfigFlag(DockManager::DockAreaHideDisabledButtons))
|
||||
{}
|
||||
|
||||
void TitleBarButton::setVisible(bool visible)
|
||||
@@ -281,9 +282,8 @@ namespace ADS
|
||||
|
||||
// 'visible' can stay 'true' unless: this button is configured to be invisible when it
|
||||
// is disabled and it is currently disabled:
|
||||
if (visible && m_hideWhenDisabled) {
|
||||
if (visible && m_hideWhenDisabled)
|
||||
visible = isEnabled();
|
||||
}
|
||||
|
||||
Super::setVisible(visible);
|
||||
}
|
||||
@@ -360,9 +360,8 @@ namespace ADS
|
||||
|
||||
void DockAreaTitleBar::onTabsMenuAboutToShow()
|
||||
{
|
||||
if (!d->m_menuOutdated) {
|
||||
if (!d->m_menuOutdated)
|
||||
return;
|
||||
}
|
||||
|
||||
QMenu *menu = d->m_tabsMenuButton->menu();
|
||||
menu->clear();
|
||||
@@ -382,19 +381,17 @@ namespace ADS
|
||||
void DockAreaTitleBar::onCloseButtonClicked()
|
||||
{
|
||||
qCInfo(adsLog) << Q_FUNC_INFO;
|
||||
if (d->testConfigFlag(DockManager::DockAreaCloseButtonClosesTab)) {
|
||||
if (d->testConfigFlag(DockManager::DockAreaCloseButtonClosesTab))
|
||||
d->m_tabBar->closeTab(d->m_tabBar->currentIndex());
|
||||
} else {
|
||||
else
|
||||
d->m_dockArea->closeArea();
|
||||
}
|
||||
}
|
||||
|
||||
void DockAreaTitleBar::onUndockButtonClicked()
|
||||
{
|
||||
if (d->m_dockArea->features().testFlag(DockWidget::DockWidgetFloatable)) {
|
||||
if (d->m_dockArea->features().testFlag(DockWidget::DockWidgetFloatable))
|
||||
d->makeAreaFloating(mapFromGlobal(QCursor::pos()), DraggingInactive);
|
||||
}
|
||||
}
|
||||
|
||||
void DockAreaTitleBar::onTabsMenuActionTriggered(QAction *action)
|
||||
{
|
||||
@@ -470,6 +467,9 @@ namespace ADS
|
||||
event->accept();
|
||||
d->m_dragStartMousePos = event->pos();
|
||||
d->m_dragState = DraggingMousePressed;
|
||||
if (DockManager::testConfigFlag(DockManager::FocusHighlighting))
|
||||
d->m_tabBar->currentTab()->setFocus(Qt::OtherFocusReason);
|
||||
|
||||
return;
|
||||
}
|
||||
Super::mousePressEvent(event);
|
||||
@@ -505,7 +505,7 @@ namespace ADS
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is the last dock area in a dock container it does not make
|
||||
// If this is the last dock area in a floating dock container it does not make
|
||||
// sense to move it to a new floating widget and leave this one empty
|
||||
if (d->m_dockArea->dockContainer()->isFloating()
|
||||
&& d->m_dockArea->dockContainer()->visibleDockAreaCount() == 1) {
|
||||
@@ -525,7 +525,7 @@ namespace ADS
|
||||
|
||||
int dragDistance = (d->m_dragStartMousePos - event->pos()).manhattanLength();
|
||||
if (dragDistance >= DockManager::startDragDistance()) {
|
||||
qCInfo(adsLog) << "TabsScrollArea::startFloating";
|
||||
qCInfo(adsLog) << "DockAreaTitlBar::startFloating";
|
||||
d->startFloating(d->m_dragStartMousePos);
|
||||
auto overlay = d->m_dockArea->dockManager()->containerOverlay();
|
||||
overlay->setAllowedAreas(OuterDockAreas);
|
||||
|
@@ -103,18 +103,17 @@ namespace ADS
|
||||
void insertWidget(int index, QWidget *widget)
|
||||
{
|
||||
widget->setParent(nullptr);
|
||||
if (index < 0) {
|
||||
if (index < 0)
|
||||
index = m_widgets.count();
|
||||
}
|
||||
|
||||
m_widgets.insert(index, widget);
|
||||
if (m_currentIndex < 0) {
|
||||
setCurrentIndex(index);
|
||||
} else {
|
||||
if (index <= m_currentIndex) {
|
||||
if (index <= m_currentIndex)
|
||||
++m_currentIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given widget from the layout
|
||||
@@ -123,11 +122,13 @@ namespace ADS
|
||||
{
|
||||
if (currentWidget() == widget) {
|
||||
auto layoutItem = m_parentLayout->takeAt(1);
|
||||
if (layoutItem) {
|
||||
if (layoutItem)
|
||||
layoutItem->widget()->setParent(nullptr);
|
||||
}
|
||||
|
||||
m_currentWidget = nullptr;
|
||||
m_currentIndex = -1;
|
||||
} else if (indexOf(widget) < m_currentIndex) {
|
||||
--m_currentIndex;
|
||||
}
|
||||
m_widgets.removeOne(widget);
|
||||
}
|
||||
@@ -144,9 +145,8 @@ namespace ADS
|
||||
{
|
||||
QWidget *prev = currentWidget();
|
||||
QWidget *next = widget(index);
|
||||
if (!next || (next == prev && !m_currentWidget)) {
|
||||
if (!next || (next == prev && !m_currentWidget))
|
||||
return;
|
||||
}
|
||||
|
||||
bool reenableUpdates = false;
|
||||
QWidget *parent = m_parentLayout->parentWidget();
|
||||
@@ -156,23 +156,19 @@ namespace ADS
|
||||
parent->setUpdatesEnabled(false);
|
||||
}
|
||||
|
||||
// TODO
|
||||
auto layoutItem = m_parentLayout->takeAt(1);
|
||||
if (layoutItem) {
|
||||
if (auto layoutItem = m_parentLayout->takeAt(1))
|
||||
layoutItem->widget()->setParent(nullptr);
|
||||
}
|
||||
|
||||
m_parentLayout->addWidget(next);
|
||||
if (prev) {
|
||||
if (prev)
|
||||
prev->hide();
|
||||
}
|
||||
|
||||
m_currentIndex = index;
|
||||
m_currentWidget = next;
|
||||
|
||||
if (reenableUpdates) {
|
||||
if (reenableUpdates)
|
||||
parent->setUpdatesEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the current active widget
|
||||
@@ -262,7 +258,7 @@ namespace ADS
|
||||
DockAreaTabBar *tabBar() const { return m_titleBar->tabBar(); }
|
||||
|
||||
/**
|
||||
* Udpates the enable state of the close and detach button
|
||||
* Updates the enable state of the close and detach button
|
||||
*/
|
||||
void updateTitleBarButtonStates();
|
||||
|
||||
@@ -330,10 +326,9 @@ namespace ADS
|
||||
|
||||
d->createTitleBar();
|
||||
d->m_contentsLayout = new DockAreaLayout(d->m_layout);
|
||||
if (d->m_dockManager) {
|
||||
if (d->m_dockManager)
|
||||
emit d->m_dockManager->dockAreaCreated(this);
|
||||
}
|
||||
}
|
||||
|
||||
DockAreaWidget::~DockAreaWidget()
|
||||
{
|
||||
@@ -357,6 +352,7 @@ namespace ADS
|
||||
void DockAreaWidget::insertDockWidget(int index, DockWidget *dockWidget, bool activate)
|
||||
{
|
||||
d->m_contentsLayout->insertWidget(index, dockWidget);
|
||||
dockWidget->setDockArea(this);
|
||||
dockWidget->tabWidget()->setDockAreaWidget(this);
|
||||
auto tabWidget = dockWidget->tabWidget();
|
||||
// Inserting the tab will change the current index which in turn will
|
||||
@@ -370,10 +366,14 @@ namespace ADS
|
||||
dockWidget->minimumSizeHint().height()));
|
||||
d->m_minSizeHint.setWidth(qMax(d->m_minSizeHint.width(),
|
||||
dockWidget->minimumSizeHint().width()));
|
||||
if (activate) {
|
||||
if (activate)
|
||||
setCurrentIndex(index);
|
||||
}
|
||||
dockWidget->setDockArea(this);
|
||||
|
||||
// If this dock area is hidden, then we need to make it visible again
|
||||
// by calling dockWidget->toggleViewInternal(true);
|
||||
if (!this->isVisible() && d->m_contentsLayout->count() > 1 && !dockManager()->isRestoringState())
|
||||
dockWidget->toggleViewInternal(true);
|
||||
|
||||
d->updateTitleBarButtonStates();
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ namespace ADS
|
||||
DockContainerWidget *dockContainerWidget = dockContainer();
|
||||
if (nextOpen) {
|
||||
setCurrentDockWidget(nextOpen);
|
||||
} else if (d->m_contentsLayout->isEmpty() && dockContainerWidget->dockAreaCount() > 1) {
|
||||
} else if (d->m_contentsLayout->isEmpty() && dockContainerWidget->dockAreaCount() >= 1) {
|
||||
qCInfo(adsLog) << "Dock Area empty";
|
||||
dockContainerWidget->removeDockArea(this);
|
||||
this->deleteLater();
|
||||
@@ -404,9 +404,8 @@ namespace ADS
|
||||
updateTitleBarVisibility();
|
||||
d->updateMinimumSizeHint();
|
||||
auto topLevelDockWidget = dockContainerWidget->topLevelDockWidget();
|
||||
if (topLevelDockWidget) {
|
||||
if (topLevelDockWidget)
|
||||
topLevelDockWidget->emitTopLevelChanged(true);
|
||||
}
|
||||
|
||||
#if (ADS_DEBUG_LEVEL > 0)
|
||||
dockContainerWidget->dumpLayout();
|
||||
@@ -423,17 +422,19 @@ namespace ADS
|
||||
|
||||
//Hide empty floating widget
|
||||
DockContainerWidget *container = this->dockContainer();
|
||||
if (!container->isFloating()) {
|
||||
if (!container->isFloating()
|
||||
&& DockManager::testConfigFlag(DockManager::HideSingleCentralWidgetTitleBar))
|
||||
return;
|
||||
}
|
||||
|
||||
updateTitleBarVisibility();
|
||||
auto topLevelWidget = container->topLevelDockWidget();
|
||||
auto floatingWidget = container->floatingWidget();
|
||||
if (topLevelWidget) {
|
||||
if (floatingWidget)
|
||||
floatingWidget->updateWindowTitle();
|
||||
|
||||
DockWidget::emitTopLevelEventForWidget(topLevelWidget, true);
|
||||
} else if (container->openedDockAreas().isEmpty()) {
|
||||
} else if (container->openedDockAreas().isEmpty() && floatingWidget) {
|
||||
floatingWidget->hide();
|
||||
}
|
||||
}
|
||||
@@ -442,28 +443,25 @@ namespace ADS
|
||||
{
|
||||
qCInfo(adsLog) << Q_FUNC_INFO << "index" << index;
|
||||
auto *currentDockWidget = dockWidget(index);
|
||||
if (currentDockWidget->features().testFlag(DockWidget::DockWidgetDeleteOnClose)) {
|
||||
if (currentDockWidget->features().testFlag(DockWidget::DockWidgetDeleteOnClose))
|
||||
currentDockWidget->closeDockWidgetInternal();
|
||||
} else {
|
||||
else
|
||||
currentDockWidget->toggleView(false);
|
||||
}
|
||||
}
|
||||
|
||||
DockWidget *DockAreaWidget::currentDockWidget() const
|
||||
{
|
||||
int currentIdx = currentIndex();
|
||||
if (currentIdx < 0) {
|
||||
if (currentIdx < 0)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return dockWidget(currentIdx);
|
||||
}
|
||||
|
||||
void DockAreaWidget::setCurrentDockWidget(DockWidget *dockWidget)
|
||||
{
|
||||
if (dockManager()->isRestoringState()) {
|
||||
if (dockManager()->isRestoringState())
|
||||
return;
|
||||
}
|
||||
|
||||
internalSetCurrentDockWidget(dockWidget);
|
||||
}
|
||||
@@ -471,9 +469,8 @@ namespace ADS
|
||||
void DockAreaWidget::internalSetCurrentDockWidget(DockWidget *dockWidget)
|
||||
{
|
||||
int index = indexOf(dockWidget);
|
||||
if (index < 0) {
|
||||
if (index < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
setCurrentIndex(index);
|
||||
}
|
||||
@@ -488,9 +485,8 @@ namespace ADS
|
||||
|
||||
auto cw = d->m_contentsLayout->currentWidget();
|
||||
auto nw = d->m_contentsLayout->widget(index);
|
||||
if (cw == nw && !nw->isHidden()) {
|
||||
if (cw == nw && !nw->isHidden())
|
||||
return;
|
||||
}
|
||||
|
||||
emit currentChanging(index);
|
||||
currentTabBar->setCurrentIndex(index);
|
||||
@@ -513,9 +509,9 @@ namespace ADS
|
||||
QList<DockWidget *> DockAreaWidget::dockWidgets() const
|
||||
{
|
||||
QList<DockWidget *> dockWidgetList;
|
||||
for (int i = 0; i < d->m_contentsLayout->count(); ++i) {
|
||||
for (int i = 0; i < d->m_contentsLayout->count(); ++i)
|
||||
dockWidgetList.append(dockWidget(i));
|
||||
}
|
||||
|
||||
return dockWidgetList;
|
||||
}
|
||||
|
||||
@@ -523,10 +519,9 @@ namespace ADS
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < d->m_contentsLayout->count(); ++i) {
|
||||
if (!dockWidget(i)->isClosed()) {
|
||||
if (!dockWidget(i)->isClosed())
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -535,22 +530,20 @@ namespace ADS
|
||||
QList<DockWidget *> dockWidgetList;
|
||||
for (int i = 0; i < d->m_contentsLayout->count(); ++i) {
|
||||
DockWidget *currentDockWidget = dockWidget(i);
|
||||
if (!currentDockWidget->isClosed()) {
|
||||
if (!currentDockWidget->isClosed())
|
||||
dockWidgetList.append(dockWidget(i));
|
||||
}
|
||||
}
|
||||
return dockWidgetList;
|
||||
}
|
||||
|
||||
int DockAreaWidget::indexOfFirstOpenDockWidget() const
|
||||
{
|
||||
for (int i = 0; i < d->m_contentsLayout->count(); ++i) {
|
||||
if (!dockWidget(i)->isClosed()) {
|
||||
if (!dockWidget(i)->isClosed())
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return - 1;
|
||||
}
|
||||
|
||||
int DockAreaWidget::dockWidgetsCount() const { return d->m_contentsLayout->count(); }
|
||||
@@ -585,25 +578,24 @@ namespace ADS
|
||||
void DockAreaWidget::updateTitleBarVisibility()
|
||||
{
|
||||
DockContainerWidget *container = dockContainer();
|
||||
if (!container) {
|
||||
if (!container)
|
||||
return;
|
||||
}
|
||||
|
||||
if (DockManager::configFlags().testFlag(DockManager::AlwaysShowTabs)) {
|
||||
if (DockManager::testConfigFlag(DockManager::AlwaysShowTabs))
|
||||
return;
|
||||
}
|
||||
|
||||
if (d->m_titleBar) {
|
||||
d->m_titleBar->setVisible(!container->isFloating() || !container->hasTopLevelDockWidget());
|
||||
bool hidden = container->hasTopLevelDockWidget() && (container->isFloating()
|
||||
|| DockManager::testConfigFlag(DockManager::HideSingleCentralWidgetTitleBar));
|
||||
d->m_titleBar->setVisible(!hidden);
|
||||
}
|
||||
}
|
||||
|
||||
void DockAreaWidget::markTitleBarMenuOutdated()
|
||||
{
|
||||
if (d->m_titleBar) {
|
||||
if (d->m_titleBar)
|
||||
d->m_titleBar->markTabsMenuOutdated();
|
||||
}
|
||||
}
|
||||
|
||||
void DockAreaWidget::saveState(QXmlStreamWriter &stream) const
|
||||
{
|
||||
@@ -614,9 +606,9 @@ namespace ADS
|
||||
stream.writeAttribute("current", name);
|
||||
qCInfo(adsLog) << Q_FUNC_INFO << "TabCount: " << d->m_contentsLayout->count()
|
||||
<< " Current: " << name;
|
||||
for (int i = 0; i < d->m_contentsLayout->count(); ++i) {
|
||||
for (int i = 0; i < d->m_contentsLayout->count(); ++i)
|
||||
dockWidget(i)->saveState(stream);
|
||||
}
|
||||
|
||||
stream.writeEndElement();
|
||||
}
|
||||
|
||||
@@ -643,15 +635,15 @@ namespace ADS
|
||||
{
|
||||
if (BitwiseAnd == mode) {
|
||||
DockWidget::DockWidgetFeatures features(DockWidget::AllDockWidgetFeatures);
|
||||
for (const auto dockWidget : dockWidgets()) {
|
||||
for (const auto dockWidget : dockWidgets())
|
||||
features &= dockWidget->features();
|
||||
}
|
||||
|
||||
return features;
|
||||
} else {
|
||||
DockWidget::DockWidgetFeatures features(DockWidget::NoDockWidgetFeatures);
|
||||
for (const auto dockWidget : dockWidgets()) {
|
||||
for (const auto dockWidget : dockWidgets())
|
||||
features |= dockWidget->features();
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
}
|
||||
@@ -666,10 +658,9 @@ namespace ADS
|
||||
void DockAreaWidget::setVisible(bool visible)
|
||||
{
|
||||
Super::setVisible(visible);
|
||||
if (d->m_updateTitleBarButtons) {
|
||||
if (d->m_updateTitleBarButtons)
|
||||
d->updateTitleBarButtonStates();
|
||||
}
|
||||
}
|
||||
|
||||
void DockAreaWidget::setAllowedAreas(DockWidgetAreas areas)
|
||||
{
|
||||
@@ -695,11 +686,10 @@ namespace ADS
|
||||
&& openDockWidgets[0]->features().testFlag(DockWidget::DockWidgetDeleteOnClose)) {
|
||||
openDockWidgets[0]->closeDockWidgetInternal();
|
||||
} else {
|
||||
for (auto dockWidget : openedDockWidgets()) {
|
||||
for (auto dockWidget : openedDockWidgets())
|
||||
dockWidget->toggleView(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DockAreaWidget::closeOtherAreas() { dockContainer()->closeOtherAreas(this); }
|
||||
|
||||
|
@@ -95,12 +95,11 @@ namespace ADS
|
||||
*/
|
||||
static void insertWidgetIntoSplitter(QSplitter *splitter, QWidget *widget, bool append)
|
||||
{
|
||||
if (append) {
|
||||
if (append)
|
||||
splitter->addWidget(widget);
|
||||
} else {
|
||||
else
|
||||
splitter->insertWidget(0, widget);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Private data class of DockContainerWidget class (pimpl)
|
||||
@@ -128,12 +127,12 @@ namespace ADS
|
||||
* Adds dock widget to container and returns the dock area that contains
|
||||
* the inserted dock widget
|
||||
*/
|
||||
DockAreaWidget *dockWidgetIntoContainer(DockWidgetArea area, DockWidget *dockWidget);
|
||||
DockAreaWidget *addDockWidgetToContainer(DockWidgetArea area, DockWidget *dockWidget);
|
||||
|
||||
/**
|
||||
* Adds dock widget to a existing DockWidgetArea
|
||||
*/
|
||||
DockAreaWidget *dockWidgetIntoDockArea(DockWidgetArea area,
|
||||
DockAreaWidget *addDockWidgetToDockArea(DockWidgetArea area,
|
||||
DockWidget *dockWidget,
|
||||
DockAreaWidget *targetDockArea);
|
||||
|
||||
@@ -233,22 +232,20 @@ namespace ADS
|
||||
*/
|
||||
void initVisibleDockAreaCount()
|
||||
{
|
||||
if (m_visibleDockAreaCount > -1) {
|
||||
if (m_visibleDockAreaCount > -1)
|
||||
return;
|
||||
}
|
||||
|
||||
m_visibleDockAreaCount = 0;
|
||||
for (auto dockArea : m_dockAreas) {
|
||||
for (auto dockArea : m_dockAreas)
|
||||
m_visibleDockAreaCount += dockArea->isHidden() ? 0 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Access function for the visible dock area counter
|
||||
*/
|
||||
int visibleDockAreaCount()
|
||||
{
|
||||
// Lazy initialization - we initialize the VisibleDockAreaCount variable
|
||||
// Lazy initialization - we initialize the m_visibleDockAreaCount variable
|
||||
// on first use
|
||||
initVisibleDockAreaCount();
|
||||
return m_visibleDockAreaCount;
|
||||
@@ -278,12 +275,29 @@ namespace ADS
|
||||
DockSplitter *createSplitter(Qt::Orientation orientation, QWidget *parent = nullptr)
|
||||
{
|
||||
auto *splitter = new DockSplitter(orientation, parent);
|
||||
splitter->setOpaqueResize(
|
||||
DockManager::configFlags().testFlag(DockManager::OpaqueSplitterResize));
|
||||
splitter->setOpaqueResize(DockManager::testConfigFlag(DockManager::OpaqueSplitterResize));
|
||||
splitter->setChildrenCollapsible(false);
|
||||
return splitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures equal distribution of the sizes of a splitter if an dock widget
|
||||
* is inserted from code
|
||||
*/
|
||||
void adjustSplitterSizesOnInsertion(QSplitter *splitter, qreal lastRatio = 1.0)
|
||||
{
|
||||
const int areaSize = (splitter->orientation() == Qt::Horizontal) ? splitter->width()
|
||||
: splitter->height();
|
||||
auto splitterSizes = splitter->sizes();
|
||||
|
||||
const qreal totalRatio = splitterSizes.size() - 1.0 + lastRatio;
|
||||
for (int i = 0; i < splitterSizes.size() - 1; ++i)
|
||||
splitterSizes[i] = areaSize / totalRatio;
|
||||
|
||||
splitterSizes.back() = areaSize * lastRatio / totalRatio;
|
||||
splitter->setSizes(splitterSizes);
|
||||
}
|
||||
|
||||
void onDockAreaViewToggled(bool visible)
|
||||
{
|
||||
DockAreaWidget *dockArea = qobject_cast<DockAreaWidget *>(q->sender());
|
||||
@@ -309,9 +323,8 @@ namespace ADS
|
||||
auto dropOverlay = m_dockManager->dockAreaOverlay();
|
||||
dropOverlay->setAllowedAreas(dockArea->allowedAreas());
|
||||
dropArea = dropOverlay->showOverlay(dockArea);
|
||||
if (containerDropArea != InvalidDockWidgetArea && containerDropArea != dropArea) {
|
||||
if (containerDropArea != InvalidDockWidgetArea && containerDropArea != dropArea)
|
||||
dropArea = InvalidDockWidgetArea;
|
||||
}
|
||||
|
||||
if (dropArea != InvalidDockWidgetArea) {
|
||||
qCInfo(adsLog) << "Dock Area Drop Content: " << dropArea;
|
||||
@@ -323,10 +336,9 @@ namespace ADS
|
||||
if (InvalidDockWidgetArea == dropArea) {
|
||||
dropArea = containerDropArea;
|
||||
qCInfo(adsLog) << "Container Drop Content: " << dropArea;
|
||||
if (dropArea != InvalidDockWidgetArea) {
|
||||
if (dropArea != InvalidDockWidgetArea)
|
||||
return DropModeIntoContainer;
|
||||
}
|
||||
}
|
||||
|
||||
return DropModeInvalid;
|
||||
}
|
||||
@@ -373,11 +385,9 @@ namespace ADS
|
||||
if (floatingSplitter->count() == 1) {
|
||||
insertWidgetIntoSplitter(splitter, floatingSplitter->widget(0), insertParam.append());
|
||||
} else if (floatingSplitter->orientation() == insertParam.orientation()) {
|
||||
while (floatingSplitter->count()) {
|
||||
insertWidgetIntoSplitter(splitter,
|
||||
floatingSplitter->widget(0),
|
||||
insertParam.append());
|
||||
}
|
||||
int insertIndex = insertParam.append() ? splitter->count() : 0;
|
||||
while (floatingSplitter->count())
|
||||
splitter->insertWidget(insertIndex++, floatingSplitter->widget(0));
|
||||
} else {
|
||||
insertWidgetIntoSplitter(splitter, floatingSplitter, insertParam.append());
|
||||
}
|
||||
@@ -388,9 +398,9 @@ namespace ADS
|
||||
// If we dropped the floating widget into the main dock container that does
|
||||
// not contain any dock widgets, then splitter is invisible and we need to
|
||||
// show it to display the docked widgets
|
||||
if (!splitter->isVisible()) {
|
||||
if (!splitter->isVisible())
|
||||
splitter->show();
|
||||
}
|
||||
|
||||
q->dumpLayout();
|
||||
}
|
||||
|
||||
@@ -405,9 +415,8 @@ namespace ADS
|
||||
// If the floating widget contains only one single dock are, then the
|
||||
// current dock widget of the dock area will also be the future current
|
||||
// dock widget in the drop area.
|
||||
if (topLevelDockArea) {
|
||||
if (topLevelDockArea)
|
||||
newCurrentIndex = topLevelDockArea->currentIndex();
|
||||
}
|
||||
|
||||
for (int i = 0; i < newDockWidgets.count(); ++i) {
|
||||
DockWidget *dockWidget = newDockWidgets[i];
|
||||
@@ -415,10 +424,9 @@ namespace ADS
|
||||
// If the floating widget contains multiple visible dock areas, then we
|
||||
// simply pick the first visible open dock widget and make it
|
||||
// the current one.
|
||||
if (newCurrentIndex < 0 && !dockWidget->isClosed()) {
|
||||
if (newCurrentIndex < 0 && !dockWidget->isClosed())
|
||||
newCurrentIndex = i;
|
||||
}
|
||||
}
|
||||
targetArea->setCurrentIndex(newCurrentIndex);
|
||||
targetArea->updateTitleBarVisibility();
|
||||
return;
|
||||
@@ -464,10 +472,9 @@ namespace ADS
|
||||
} else {
|
||||
adjustSplitterSizes = (floatingSplitter->count() == 1);
|
||||
int insertIndex = areaIndex + insertParam.insertOffset();
|
||||
while (floatingSplitter->count()) {
|
||||
while (floatingSplitter->count())
|
||||
targetAreaSplitter->insertWidget(insertIndex++, floatingSplitter->widget(0));
|
||||
}
|
||||
}
|
||||
|
||||
if (adjustSplitterSizes) {
|
||||
int size = (targetAreaSize - targetAreaSplitter->handleWidth()) / 2;
|
||||
@@ -516,9 +523,12 @@ namespace ADS
|
||||
|
||||
if (droppedDockWidget) {
|
||||
DockAreaWidget *oldDockArea = droppedDockWidget->dockAreaWidget();
|
||||
if (oldDockArea) {
|
||||
if (oldDockArea == targetArea)
|
||||
return;
|
||||
|
||||
if (oldDockArea)
|
||||
oldDockArea->removeDockWidget(droppedDockWidget);
|
||||
}
|
||||
|
||||
targetArea->insertDockWidget(0, droppedDockWidget, true);
|
||||
} else {
|
||||
QList<DockWidget *> newDockWidgets = droppedArea->dockWidgets();
|
||||
@@ -553,9 +563,9 @@ namespace ADS
|
||||
if (droppedDockWidget) {
|
||||
newDockArea = new DockAreaWidget(m_dockManager, q);
|
||||
DockAreaWidget *oldDockArea = droppedDockWidget->dockAreaWidget();
|
||||
if (oldDockArea) {
|
||||
if (oldDockArea)
|
||||
oldDockArea->removeDockWidget(droppedDockWidget);
|
||||
}
|
||||
|
||||
newDockArea->addDockWidget(droppedDockWidget);
|
||||
} else {
|
||||
droppedDockArea->dockContainer()->removeDockArea(droppedDockArea);
|
||||
@@ -564,25 +574,25 @@ namespace ADS
|
||||
|
||||
auto insertParam = internal::dockAreaInsertParameters(area);
|
||||
QSplitter *targetAreaSplitter = internal::findParent<QSplitter *>(targetArea);
|
||||
int areaIndex = targetAreaSplitter->indexOf(targetArea);
|
||||
const int areaIndex = targetAreaSplitter->indexOf(targetArea);
|
||||
auto sizes = targetAreaSplitter->sizes();
|
||||
if (targetAreaSplitter->orientation() == insertParam.orientation()) {
|
||||
int targetAreaSize = (insertParam.orientation() == Qt::Horizontal)
|
||||
const int targetAreaSize = (insertParam.orientation() == Qt::Horizontal)
|
||||
? targetArea->width()
|
||||
: targetArea->height();
|
||||
targetAreaSplitter->insertWidget(areaIndex + insertParam.insertOffset(), newDockArea);
|
||||
int size = (targetAreaSize - targetAreaSplitter->handleWidth()) / 2;
|
||||
const int size = (targetAreaSize - targetAreaSplitter->handleWidth()) / 2;
|
||||
sizes[areaIndex] = size;
|
||||
sizes.insert(areaIndex, size);
|
||||
} else {
|
||||
auto sizes = targetAreaSplitter->sizes();
|
||||
int targetAreaSize = (insertParam.orientation() == Qt::Horizontal)
|
||||
const int targetAreaSize = (insertParam.orientation() == Qt::Horizontal)
|
||||
? targetArea->width()
|
||||
: targetArea->height();
|
||||
QSplitter *newSplitter = createSplitter(insertParam.orientation());
|
||||
newSplitter->addWidget(targetArea);
|
||||
insertWidgetIntoSplitter(newSplitter, newDockArea, insertParam.append());
|
||||
int size = targetAreaSize / 2;
|
||||
const int size = targetAreaSize / 2;
|
||||
newSplitter->setSizes({size, size});
|
||||
targetAreaSplitter->insertWidget(areaIndex, newSplitter);
|
||||
}
|
||||
@@ -600,9 +610,9 @@ namespace ADS
|
||||
if (droppedDockWidget) {
|
||||
newDockArea = new DockAreaWidget(m_dockManager, q);
|
||||
DockAreaWidget *oldDockArea = droppedDockWidget->dockAreaWidget();
|
||||
if (oldDockArea) {
|
||||
if (oldDockArea)
|
||||
oldDockArea->removeDockWidget(droppedDockWidget);
|
||||
}
|
||||
|
||||
newDockArea->addDockWidget(droppedDockWidget);
|
||||
} else {
|
||||
// We check, if we insert the dropped widget into the same place that
|
||||
@@ -627,8 +637,8 @@ namespace ADS
|
||||
|
||||
void DockContainerWidgetPrivate::addDockAreasToList(const QList<DockAreaWidget *> newDockAreas)
|
||||
{
|
||||
int countBefore = m_dockAreas.count();
|
||||
int newAreaCount = newDockAreas.count();
|
||||
const int countBefore = m_dockAreas.count();
|
||||
const int newAreaCount = newDockAreas.count();
|
||||
appendDockAreas(newDockAreas);
|
||||
// If the user dropped a floating widget that contains only one single
|
||||
// visible dock area, then its title bar button TitleBarButtonUndock is
|
||||
@@ -640,13 +650,11 @@ namespace ADS
|
||||
|
||||
// We need to ensure, that the dock area title bar is visible. The title bar
|
||||
// is invisible, if the dock are is a single dock area in a floating widget.
|
||||
if (1 == countBefore) {
|
||||
if (1 == countBefore)
|
||||
m_dockAreas.at(0)->updateTitleBarVisibility();
|
||||
}
|
||||
|
||||
if (1 == newAreaCount) {
|
||||
if (1 == newAreaCount)
|
||||
m_dockAreas.last()->updateTitleBarVisibility();
|
||||
}
|
||||
|
||||
emitDockAreasAdded();
|
||||
}
|
||||
@@ -674,25 +682,23 @@ namespace ADS
|
||||
stream.writeAttribute("count", QString::number(splitter->count()));
|
||||
qCInfo(adsLog) << "NodeSplitter orient: " << splitter->orientation()
|
||||
<< " WidgetCont: " << splitter->count();
|
||||
for (int i = 0; i < splitter->count(); ++i) {
|
||||
for (int i = 0; i < splitter->count(); ++i)
|
||||
saveChildNodesState(stream, splitter->widget(i));
|
||||
}
|
||||
|
||||
stream.writeStartElement("sizes");
|
||||
QStringList sizes;
|
||||
for (auto size : splitter->sizes()) {
|
||||
for (auto size : splitter->sizes())
|
||||
sizes.append(QString::number(size));
|
||||
}
|
||||
|
||||
stream.writeCharacters(sizes.join(" "));
|
||||
stream.writeEndElement();
|
||||
stream.writeEndElement();
|
||||
stream.writeEndElement(); // sizes
|
||||
stream.writeEndElement(); // splitter
|
||||
} else {
|
||||
DockAreaWidget *dockArea = qobject_cast<DockAreaWidget *>(widget);
|
||||
if (dockArea) {
|
||||
if (dockArea)
|
||||
dockArea->saveState(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DockContainerWidgetPrivate::restoreSplitter(DockingStateReader &stateReader,
|
||||
QWidget *&createdWidget,
|
||||
@@ -701,22 +707,22 @@ namespace ADS
|
||||
QVariant orientationVar = QVariant(stateReader.attributes().value("orientation").toString());
|
||||
|
||||
// Check if the orientation string is convertable
|
||||
if (!orientationVar.canConvert<Qt::Orientation>()) {
|
||||
if (!orientationVar.canConvert<Qt::Orientation>())
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::Orientation orientation = orientationVar.value<Qt::Orientation>();
|
||||
|
||||
bool ok;
|
||||
int widgetCount = stateReader.attributes().value("count").toInt(&ok);
|
||||
if (!ok) {
|
||||
if (!ok)
|
||||
return false;
|
||||
}
|
||||
|
||||
qCInfo(adsLog) << "Restore NodeSplitter Orientation: " << orientation
|
||||
<< " WidgetCount: " << widgetCount;
|
||||
QSplitter *splitter = nullptr;
|
||||
if (!testing) {
|
||||
if (!testing)
|
||||
splitter = createSplitter(orientation);
|
||||
}
|
||||
|
||||
bool visible = false;
|
||||
QList<int> sizes;
|
||||
while (stateReader.readNextStartElement()) {
|
||||
@@ -739,13 +745,11 @@ namespace ADS
|
||||
stateReader.skipCurrentElement();
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
if (!result)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (testing || !childNode) {
|
||||
if (testing || !childNode)
|
||||
continue;
|
||||
}
|
||||
|
||||
qCInfo(adsLog) << "ChildNode isVisible " << childNode->isVisible() << " isVisibleTo "
|
||||
<< childNode->isVisibleTo(splitter);
|
||||
@@ -753,9 +757,8 @@ namespace ADS
|
||||
visible |= childNode->isVisibleTo(splitter);
|
||||
}
|
||||
|
||||
if (sizes.count() != widgetCount) {
|
||||
if (sizes.count() != widgetCount)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!testing) {
|
||||
if (!splitter->count()) {
|
||||
@@ -782,22 +785,20 @@ namespace ADS
|
||||
#ifdef ADS_DEBUG_PRINT
|
||||
bool ok;
|
||||
int tabs = stateReader.attributes().value("tabs").toInt(&ok);
|
||||
if (!ok) {
|
||||
if (!ok)
|
||||
return false;
|
||||
}
|
||||
|
||||
qCInfo(adsLog) << "Restore NodeDockArea Tabs: " << tabs
|
||||
<< " Current: " << currentDockWidget;
|
||||
#endif
|
||||
|
||||
DockAreaWidget *dockArea = nullptr;
|
||||
if (!testing) {
|
||||
if (!testing)
|
||||
dockArea = new DockAreaWidget(m_dockManager, q);
|
||||
}
|
||||
|
||||
while (stateReader.readNextStartElement()) {
|
||||
if (stateReader.name() != "widget") {
|
||||
if (stateReader.name() != "widget")
|
||||
continue;
|
||||
}
|
||||
|
||||
auto objectName = stateReader.attributes().value("name");
|
||||
if (objectName.isEmpty()) {
|
||||
@@ -806,16 +807,15 @@ namespace ADS
|
||||
}
|
||||
|
||||
QVariant closedVar = QVariant(stateReader.attributes().value("closed").toString());
|
||||
if (!closedVar.canConvert<bool>()) {
|
||||
if (!closedVar.canConvert<bool>())
|
||||
return false;
|
||||
}
|
||||
|
||||
bool closed = closedVar.value<bool>();
|
||||
|
||||
stateReader.skipCurrentElement();
|
||||
DockWidget *dockWidget = m_dockManager->findDockWidget(objectName.toString());
|
||||
if (!dockWidget || testing) {
|
||||
if (!dockWidget || testing)
|
||||
continue;
|
||||
}
|
||||
|
||||
qCInfo(adsLog) << "Dock Widget found - parent " << dockWidget->parent();
|
||||
// We hide the DockArea here to prevent the short display (the flashing)
|
||||
@@ -828,9 +828,8 @@ namespace ADS
|
||||
dockWidget->setProperty(internal::dirtyProperty, false);
|
||||
}
|
||||
|
||||
if (testing) {
|
||||
if (testing)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!dockArea->dockWidgetsCount()) {
|
||||
delete dockArea;
|
||||
@@ -865,7 +864,7 @@ namespace ADS
|
||||
return result;
|
||||
}
|
||||
|
||||
DockAreaWidget *DockContainerWidgetPrivate::dockWidgetIntoContainer(DockWidgetArea area,
|
||||
DockAreaWidget *DockContainerWidgetPrivate::addDockWidgetToContainer(DockWidgetArea area,
|
||||
DockWidget *dockWidget)
|
||||
{
|
||||
DockAreaWidget *newDockArea = new DockAreaWidget(m_dockManager, q);
|
||||
@@ -880,13 +879,15 @@ namespace ADS
|
||||
{
|
||||
auto insertParam = internal::dockAreaInsertParameters(area);
|
||||
// As long as we have only one dock area in the splitter we can adjust its orientation
|
||||
if (m_dockAreas.count() <= 1) {
|
||||
if (m_dockAreas.count() <= 1)
|
||||
m_rootSplitter->setOrientation(insertParam.orientation());
|
||||
}
|
||||
|
||||
QSplitter *splitter = m_rootSplitter;
|
||||
if (splitter->orientation() == insertParam.orientation()) {
|
||||
insertWidgetIntoSplitter(splitter, newDockArea, insertParam.append());
|
||||
if (splitter->isHidden())
|
||||
splitter->show();
|
||||
|
||||
} else {
|
||||
QSplitter *newSplitter = createSplitter(insertParam.orientation());
|
||||
if (insertParam.append()) {
|
||||
@@ -924,14 +925,13 @@ namespace ADS
|
||||
<< (splitter->isHidden() ? " " : "v") << " "
|
||||
<< QString::number(splitter->count()).toStdString() << std::endl;
|
||||
#endif
|
||||
for (int i = 0; i < splitter->count(); ++i) {
|
||||
for (int i = 0; i < splitter->count(); ++i)
|
||||
dumpRecursive(level + 1, splitter->widget(i));
|
||||
}
|
||||
} else {
|
||||
DockAreaWidget *dockArea = qobject_cast<DockAreaWidget *>(widget);
|
||||
if (!dockArea) {
|
||||
if (!dockArea)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ADS_DEBUG_PRINT
|
||||
qDebug("%sDockArea", buf.data());
|
||||
std::cout << buf.data() << (dockArea->isHidden() ? " " : "v")
|
||||
@@ -953,10 +953,9 @@ namespace ADS
|
||||
#endif
|
||||
}
|
||||
|
||||
DockAreaWidget *DockContainerWidgetPrivate::dockWidgetIntoDockArea(DockWidgetArea area,
|
||||
DockAreaWidget *DockContainerWidgetPrivate::addDockWidgetToDockArea(DockWidgetArea area,
|
||||
DockWidget *dockWidget,
|
||||
DockAreaWidget
|
||||
*targetDockArea)
|
||||
DockAreaWidget *targetDockArea)
|
||||
{
|
||||
if (CenterDockWidgetArea == area) {
|
||||
targetDockArea->addDockWidget(dockWidget);
|
||||
@@ -973,12 +972,20 @@ namespace ADS
|
||||
if (targetAreaSplitter->orientation() == insertParam.orientation()) {
|
||||
qCInfo(adsLog) << "TargetAreaSplitter->orientation() == InsertParam.orientation()";
|
||||
targetAreaSplitter->insertWidget(index + insertParam.insertOffset(), newDockArea);
|
||||
// do nothing, if flag is not enabled
|
||||
if (DockManager::testConfigFlag(DockManager::EqualSplitOnInsertion))
|
||||
adjustSplitterSizesOnInsertion(targetAreaSplitter);
|
||||
} else {
|
||||
qCInfo(adsLog) << "TargetAreaSplitter->orientation() != InsertParam.orientation()";
|
||||
auto targetAreaSizes = targetAreaSplitter->sizes();
|
||||
QSplitter *newSplitter = createSplitter(insertParam.orientation());
|
||||
newSplitter->addWidget(targetDockArea);
|
||||
insertWidgetIntoSplitter(newSplitter, newDockArea, insertParam.append());
|
||||
targetAreaSplitter->insertWidget(index, newSplitter);
|
||||
if (DockManager::testConfigFlag(DockManager::EqualSplitOnInsertion)) {
|
||||
targetAreaSplitter->setSizes(targetAreaSizes);
|
||||
adjustSplitterSizesOnInsertion(newSplitter);
|
||||
}
|
||||
}
|
||||
|
||||
appendDockAreas({newDockArea});
|
||||
@@ -1011,9 +1018,9 @@ namespace ADS
|
||||
|
||||
DockContainerWidget::~DockContainerWidget()
|
||||
{
|
||||
if (d->m_dockManager) {
|
||||
if (d->m_dockManager)
|
||||
d->m_dockManager->removeDockContainer(this);
|
||||
}
|
||||
|
||||
delete d;
|
||||
}
|
||||
|
||||
@@ -1022,25 +1029,22 @@ namespace ADS
|
||||
DockAreaWidget *dockAreaWidget)
|
||||
{
|
||||
DockAreaWidget *oldDockArea = dockWidget->dockAreaWidget();
|
||||
if (oldDockArea) {
|
||||
if (oldDockArea)
|
||||
oldDockArea->removeDockWidget(dockWidget);
|
||||
}
|
||||
|
||||
dockWidget->setDockManager(d->m_dockManager);
|
||||
if (dockAreaWidget) {
|
||||
return d->dockWidgetIntoDockArea(area, dockWidget, dockAreaWidget);
|
||||
} else {
|
||||
return d->dockWidgetIntoContainer(area, dockWidget);
|
||||
}
|
||||
if (dockAreaWidget)
|
||||
return d->addDockWidgetToDockArea(area, dockWidget, dockAreaWidget);
|
||||
else
|
||||
return d->addDockWidgetToContainer(area, dockWidget);
|
||||
}
|
||||
|
||||
void DockContainerWidget::removeDockWidget(DockWidget * dockWidget)
|
||||
{
|
||||
DockAreaWidget *area = dockWidget->dockAreaWidget();
|
||||
if (area) {
|
||||
if (area)
|
||||
area->removeDockWidget(dockWidget);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int DockContainerWidget::zOrderIndex() const { return d->m_zOrderIndex; }
|
||||
|
||||
@@ -1052,11 +1056,10 @@ namespace ADS
|
||||
bool DockContainerWidget::event(QEvent *event)
|
||||
{
|
||||
bool result = QWidget::event(event);
|
||||
if (event->type() == QEvent::WindowActivate) {
|
||||
if (event->type() == QEvent::WindowActivate)
|
||||
d->m_zOrderIndex = ++zOrderCounter;
|
||||
} else if (event->type() == QEvent::Show && !d->m_zOrderIndex) {
|
||||
else if (event->type() == QEvent::Show && !d->m_zOrderIndex)
|
||||
d->m_zOrderIndex = ++zOrderCounter;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1064,9 +1067,8 @@ namespace ADS
|
||||
void DockContainerWidget::addDockArea(DockAreaWidget *dockAreaWidget, DockWidgetArea area)
|
||||
{
|
||||
DockContainerWidget *container = dockAreaWidget->dockContainer();
|
||||
if (container && container != this) {
|
||||
if (container && container != this)
|
||||
container->removeDockArea(dockAreaWidget);
|
||||
}
|
||||
|
||||
d->addDockArea(dockAreaWidget, area);
|
||||
}
|
||||
@@ -1085,9 +1087,8 @@ namespace ADS
|
||||
|
||||
// Remove this area from cached areas
|
||||
const auto &cache = d->m_lastAddedAreaCache;
|
||||
if (auto p = std::find(cache, cache + sizeof(cache) / sizeof(cache[0]), area)) {
|
||||
if (auto p = std::find(cache, cache + sizeof(cache) / sizeof(cache[0]), area))
|
||||
d->m_lastAddedAreaCache[std::distance(cache, p)] = nullptr;
|
||||
}
|
||||
|
||||
// If splitter has more than 1 widgets, we are finished and can leave
|
||||
if (splitter->count() > 1) {
|
||||
@@ -1149,10 +1150,9 @@ namespace ADS
|
||||
{
|
||||
for (auto dockArea : d->m_dockAreas) {
|
||||
if (dockArea->isVisible()
|
||||
&& dockArea->rect().contains(dockArea->mapFromGlobal(globalPosition))) {
|
||||
&& dockArea->rect().contains(dockArea->mapFromGlobal(globalPosition)))
|
||||
return dockArea;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1169,9 +1169,8 @@ namespace ADS
|
||||
int DockContainerWidget::visibleDockAreaCount() const
|
||||
{
|
||||
int result = 0;
|
||||
for (auto dockArea : d->m_dockAreas) {
|
||||
for (auto dockArea : d->m_dockAreas)
|
||||
result += dockArea->isHidden() ? 0 : 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -1195,9 +1194,8 @@ namespace ADS
|
||||
auto dropOverlay = d->m_dockManager->dockAreaOverlay();
|
||||
dropOverlay->setAllowedAreas(dockArea->allowedAreas());
|
||||
dropArea = dropOverlay->showOverlay(dockArea);
|
||||
if (containerDropArea != InvalidDockWidgetArea && containerDropArea != dropArea) {
|
||||
if (containerDropArea != InvalidDockWidgetArea && containerDropArea != dropArea)
|
||||
dropArea = InvalidDockWidgetArea;
|
||||
}
|
||||
|
||||
if (dropArea != InvalidDockWidgetArea) {
|
||||
qCInfo(adsLog) << "Dock Area Drop Content: " << dropArea;
|
||||
@@ -1227,6 +1225,11 @@ namespace ADS
|
||||
// level widget anymore
|
||||
DockWidget::emitTopLevelEventForWidget(singleDockWidget, false);
|
||||
}
|
||||
window()->activateWindow();
|
||||
if (singleDroppedDockWidget)
|
||||
d->m_dockManager->notifyWidgetOrAreaRelocation(singleDroppedDockWidget);
|
||||
|
||||
d->m_dockManager->notifyFloatingWidgetDrop(floatingWidget);
|
||||
}
|
||||
|
||||
void DockContainerWidget::dropWidget(QWidget *widget, DockWidgetArea dropArea, DockAreaWidget *targetAreaWidget)
|
||||
@@ -1240,16 +1243,26 @@ namespace ADS
|
||||
// If there was a top level widget before the drop, then it is not top
|
||||
// level widget anymore
|
||||
DockWidget::emitTopLevelEventForWidget(singleDockWidget, false);
|
||||
DockWidget *dockWidget = qobject_cast<DockWidget *>(widget);
|
||||
if (!dockWidget)
|
||||
{
|
||||
DockAreaWidget *dockArea = qobject_cast<DockAreaWidget *>(widget);
|
||||
auto openDockWidgets = dockArea->openedDockWidgets();
|
||||
if (openDockWidgets.count() == 1)
|
||||
dockWidget = openDockWidgets[0];
|
||||
}
|
||||
|
||||
window()->activateWindow();
|
||||
d->m_dockManager->notifyWidgetOrAreaRelocation(widget);
|
||||
}
|
||||
|
||||
QList<DockAreaWidget *> DockContainerWidget::openedDockAreas() const
|
||||
{
|
||||
QList<DockAreaWidget *> result;
|
||||
for (auto dockArea : d->m_dockAreas) {
|
||||
if (!dockArea->isHidden()) {
|
||||
if (!dockArea->isHidden())
|
||||
result.append(dockArea);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1272,9 +1285,9 @@ namespace ADS
|
||||
bool DockContainerWidget::restoreState(DockingStateReader &stateReader, bool testing)
|
||||
{
|
||||
QVariant floatingVar = QVariant(stateReader.attributes().value("floating").toString());
|
||||
if (!floatingVar.canConvert<bool>()) {
|
||||
if (!floatingVar.canConvert<bool>())
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isFloating = floatingVar.value<bool>();
|
||||
qCInfo(adsLog) << "Restore DockContainerWidget Floating" << isFloating;
|
||||
|
||||
@@ -1289,18 +1302,16 @@ namespace ADS
|
||||
|
||||
if (isFloating) {
|
||||
qCInfo(adsLog) << "Restore floating widget";
|
||||
if (!stateReader.readNextStartElement() || stateReader.name() != "geometry") {
|
||||
if (!stateReader.readNextStartElement() || stateReader.name() != "geometry")
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray geometryString = stateReader
|
||||
.readElementText(
|
||||
DockingStateReader::ErrorOnUnexpectedElement)
|
||||
.toLocal8Bit();
|
||||
QByteArray geometry = QByteArray::fromBase64(geometryString);
|
||||
if (geometry.isEmpty()) {
|
||||
if (geometry.isEmpty())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!testing) {
|
||||
FloatingDockContainer *floatingDockContainer = floatingWidget();
|
||||
@@ -1308,19 +1319,16 @@ namespace ADS
|
||||
}
|
||||
}
|
||||
|
||||
if (!d->restoreChildNodes(stateReader, newRootSplitter, testing)) {
|
||||
if (!d->restoreChildNodes(stateReader, newRootSplitter, testing))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (testing) {
|
||||
if (testing)
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the root splitter is empty, rostoreChildNodes returns a 0 pointer
|
||||
// and we need to create a new empty root splitter
|
||||
if (!newRootSplitter) {
|
||||
if (!newRootSplitter)
|
||||
newRootSplitter = d->createSplitter(Qt::Horizontal);
|
||||
}
|
||||
|
||||
d->m_layout->replaceWidget(d->m_rootSplitter, newRootSplitter);
|
||||
QSplitter *oldRoot = d->m_rootSplitter;
|
||||
@@ -1334,9 +1342,9 @@ namespace ADS
|
||||
|
||||
void DockContainerWidget::createRootSplitter()
|
||||
{
|
||||
if (d->m_rootSplitter) {
|
||||
if (d->m_rootSplitter)
|
||||
return;
|
||||
}
|
||||
|
||||
d->m_rootSplitter = d->createSplitter(Qt::Horizontal);
|
||||
d->m_layout->addWidget(d->m_rootSplitter);
|
||||
}
|
||||
@@ -1359,14 +1367,9 @@ namespace ADS
|
||||
|
||||
bool DockContainerWidget::hasTopLevelDockWidget() const
|
||||
{
|
||||
if (!isFloating()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto dockAreas = openedDockAreas();
|
||||
if (dockAreas.count() != 1) {
|
||||
if (dockAreas.count() != 1)
|
||||
return false;
|
||||
}
|
||||
|
||||
return dockAreas[0]->openDockWidgetsCount() == 1;
|
||||
}
|
||||
@@ -1374,28 +1377,21 @@ namespace ADS
|
||||
DockWidget *DockContainerWidget::topLevelDockWidget() const
|
||||
{
|
||||
auto dockArea = topLevelDockArea();
|
||||
if (!dockArea) {
|
||||
if (!dockArea)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto dockWidgets = dockArea->openedDockWidgets();
|
||||
if (dockWidgets.count() != 1) {
|
||||
if (dockWidgets.count() != 1)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return dockWidgets[0];
|
||||
}
|
||||
|
||||
DockAreaWidget *DockContainerWidget::topLevelDockArea() const
|
||||
{
|
||||
if (!isFloating()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto dockAreas = openedDockAreas();
|
||||
if (dockAreas.count() != 1) {
|
||||
if (dockAreas.count() != 1)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return dockAreas[0];
|
||||
}
|
||||
@@ -1403,9 +1399,8 @@ namespace ADS
|
||||
QList<DockWidget *> DockContainerWidget::dockWidgets() const
|
||||
{
|
||||
QList<DockWidget *> result;
|
||||
for (const auto dockArea : d->m_dockAreas) {
|
||||
for (const auto dockArea : d->m_dockAreas)
|
||||
result.append(dockArea->dockWidgets());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1413,9 +1408,8 @@ namespace ADS
|
||||
DockWidget::DockWidgetFeatures DockContainerWidget::features() const
|
||||
{
|
||||
DockWidget::DockWidgetFeatures features(DockWidget::AllDockWidgetFeatures);
|
||||
for (const auto dockArea : d->m_dockAreas) {
|
||||
for (const auto dockArea : d->m_dockAreas)
|
||||
features &= dockArea->features();
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
@@ -1428,18 +1422,15 @@ namespace ADS
|
||||
void DockContainerWidget::closeOtherAreas(DockAreaWidget *keepOpenArea)
|
||||
{
|
||||
for (const auto dockArea : d->m_dockAreas) {
|
||||
if (dockArea == keepOpenArea) {
|
||||
if (dockArea == keepOpenArea)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!dockArea->features(BitwiseAnd).testFlag(DockWidget::DockWidgetClosable)) {
|
||||
if (!dockArea->features(BitwiseAnd).testFlag(DockWidget::DockWidgetClosable))
|
||||
continue;
|
||||
}
|
||||
|
||||
// We do not close areas with widgets with custom close handling
|
||||
if (dockArea->features(BitwiseOr).testFlag(DockWidget::CustomCloseHandling)) {
|
||||
if (dockArea->features(BitwiseOr).testFlag(DockWidget::CustomCloseHandling))
|
||||
continue;
|
||||
}
|
||||
|
||||
dockArea->closeArea();
|
||||
}
|
||||
|
@@ -59,10 +59,10 @@ class FloatingDragPreviewPrivate;
|
||||
|
||||
/**
|
||||
* Container that manages a number of dock areas with single dock widgets
|
||||
* or tabyfied dock widgets in each area.
|
||||
* or tabified dock widgets in each area.
|
||||
* Each window that support docking has a DockContainerWidget. That means
|
||||
* the main application window and all floating windows contain
|
||||
* a DockContainerWidget.
|
||||
* the main application window and all floating windows contain a
|
||||
* DockContainerWidget instance.
|
||||
*/
|
||||
class ADS_EXPORT DockContainerWidget : public QFrame
|
||||
{
|
||||
@@ -86,13 +86,11 @@ protected:
|
||||
*/
|
||||
bool event(QEvent *event) override;
|
||||
|
||||
public: // TODO temporary
|
||||
/**
|
||||
* Access function for the internal root splitter
|
||||
*/
|
||||
QSplitter *rootSplitter() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Helper function for creation of the root splitter
|
||||
*/
|
||||
|
273
src/libs/advanceddockingsystem/dockfocuscontroller.cpp
Normal file
273
src/libs/advanceddockingsystem/dockfocuscontroller.cpp
Normal file
@@ -0,0 +1,273 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Uwe Kindler
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or (at your option) any later version.
|
||||
** The licenses are as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.LGPLv21 included in the packaging
|
||||
** of this file. Please review the following information to ensure
|
||||
** the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 or (at your option) any later version
|
||||
** approved by the KDE Free Qt Foundation. The licenses are as published by
|
||||
** the Free Software Foundation and appearing in the file LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "dockfocuscontroller.h"
|
||||
|
||||
#include "dockareawidget.h"
|
||||
#include "dockareatitlebar.h"
|
||||
#include "dockcontainerwidget.h"
|
||||
#include "dockmanager.h"
|
||||
#include "dockwidget.h"
|
||||
#include "dockwidgettab.h"
|
||||
#include "floatingdockcontainer.h"
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include "linux/floatingwidgettitlebar.h"
|
||||
#endif
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPointer>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
namespace ADS
|
||||
{
|
||||
/**
|
||||
* Private data class of CDockFocusController class (pimpl)
|
||||
*/
|
||||
class DockFocusControllerPrivate
|
||||
{
|
||||
public:
|
||||
DockFocusController *q;
|
||||
QPointer<DockWidget> m_focusedDockWidget = nullptr;
|
||||
QPointer<DockAreaWidget> m_focusedArea = nullptr;
|
||||
#ifdef Q_OS_LINUX
|
||||
QPointer<FloatingDockContainer> m_floatingWidget = nullptr;
|
||||
#endif
|
||||
DockManager *m_dockManager;
|
||||
|
||||
/**
|
||||
* Private data constructor
|
||||
*/
|
||||
DockFocusControllerPrivate(DockFocusController *parent);
|
||||
|
||||
/**
|
||||
* This function updates the focus style of the given dock widget and
|
||||
* the dock area that it belongs to
|
||||
*/
|
||||
void updateDockWidgetFocus(DockWidget *dockWidget);
|
||||
}; // class DockFocusControllerPrivate
|
||||
|
||||
static void updateDockWidgetFocusStyle(DockWidget *dockWidget, bool focused)
|
||||
{
|
||||
dockWidget->setProperty("focused", focused);
|
||||
dockWidget->tabWidget()->setProperty("focused", focused);
|
||||
dockWidget->tabWidget()->updateStyle();
|
||||
internal::repolishStyle(dockWidget);
|
||||
}
|
||||
|
||||
static void updateDockAreaFocusStyle(DockAreaWidget *dockArea, bool focused)
|
||||
{
|
||||
dockArea->setProperty("focused", focused);
|
||||
internal::repolishStyle(dockArea);
|
||||
internal::repolishStyle(dockArea->titleBar());
|
||||
}
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
static void updateFloatingWidgetFocusStyle(FloatingDockContainer *floatingWidget, bool focused)
|
||||
{
|
||||
auto titleBar = qobject_cast<FloatingWidgetTitleBar *>(floatingWidget->titleBarWidget());
|
||||
if (!titleBar)
|
||||
return;
|
||||
|
||||
titleBar->setProperty("focused", focused);
|
||||
titleBar->updateStyle();
|
||||
}
|
||||
#endif
|
||||
|
||||
DockFocusControllerPrivate::DockFocusControllerPrivate(DockFocusController *parent)
|
||||
: q(parent)
|
||||
{}
|
||||
|
||||
void DockFocusControllerPrivate::updateDockWidgetFocus(DockWidget *dockWidget)
|
||||
{
|
||||
DockAreaWidget *newFocusedDockArea = nullptr;
|
||||
if (m_focusedDockWidget)
|
||||
updateDockWidgetFocusStyle(m_focusedDockWidget, false);
|
||||
|
||||
DockWidget *old = m_focusedDockWidget;
|
||||
m_focusedDockWidget = dockWidget;
|
||||
updateDockWidgetFocusStyle(m_focusedDockWidget, true);
|
||||
newFocusedDockArea = m_focusedDockWidget->dockAreaWidget();
|
||||
if (newFocusedDockArea && (m_focusedArea != newFocusedDockArea))
|
||||
{
|
||||
if (m_focusedArea)
|
||||
{
|
||||
QObject::disconnect(m_focusedArea, &DockAreaWidget::viewToggled,
|
||||
q, &DockFocusController::onFocusedDockAreaViewToggled);
|
||||
updateDockAreaFocusStyle(m_focusedArea, false);
|
||||
}
|
||||
|
||||
m_focusedArea = newFocusedDockArea;
|
||||
updateDockAreaFocusStyle(m_focusedArea, true);
|
||||
QObject::connect(m_focusedArea, &DockAreaWidget::viewToggled,
|
||||
q, &DockFocusController::onFocusedDockAreaViewToggled);
|
||||
}
|
||||
|
||||
auto newFloatingWidget = m_focusedDockWidget->dockContainer()->floatingWidget();
|
||||
if (newFloatingWidget)
|
||||
newFloatingWidget->setProperty("FocusedDockWidget", QVariant::fromValue(dockWidget));
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
// This code is required for styling the floating widget titlebar for linux
|
||||
// depending on the current focus state
|
||||
if (m_floatingWidget == newFloatingWidget)
|
||||
return;
|
||||
|
||||
if (m_floatingWidget)
|
||||
updateFloatingWidgetFocusStyle(m_floatingWidget, false);
|
||||
|
||||
m_floatingWidget = newFloatingWidget;
|
||||
|
||||
if (m_floatingWidget)
|
||||
updateFloatingWidgetFocusStyle(m_floatingWidget, true);
|
||||
#endif
|
||||
|
||||
if (old != dockWidget)
|
||||
emit m_dockManager->focusedDockWidgetChanged(old, dockWidget);
|
||||
}
|
||||
|
||||
DockFocusController::DockFocusController(DockManager *dockManager)
|
||||
: QObject(dockManager)
|
||||
, d(new DockFocusControllerPrivate(this))
|
||||
{
|
||||
d->m_dockManager = dockManager;
|
||||
connect(qApp, &QApplication::focusChanged,
|
||||
this, &DockFocusController::onApplicationFocusChanged);
|
||||
connect(d->m_dockManager, &DockManager::stateRestored,
|
||||
this, &DockFocusController::onStateRestored);
|
||||
}
|
||||
|
||||
DockFocusController::~DockFocusController()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void DockFocusController::onApplicationFocusChanged(QWidget *focusedOld, QWidget *focusedNow)
|
||||
{
|
||||
if (d->m_dockManager->isRestoringState())
|
||||
return;
|
||||
|
||||
if (!focusedNow)
|
||||
return;
|
||||
|
||||
DockWidget *dockWidget = nullptr;
|
||||
auto dockWidgetTab = qobject_cast<DockWidgetTab *>(focusedNow);
|
||||
if (dockWidgetTab)
|
||||
dockWidget = dockWidgetTab->dockWidget();
|
||||
|
||||
if (!dockWidget)
|
||||
dockWidget = qobject_cast<DockWidget *>(focusedNow);
|
||||
|
||||
if (!dockWidget)
|
||||
dockWidget = internal::findParent<DockWidget *>(focusedNow);
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
if (!dockWidget)
|
||||
return;
|
||||
#else
|
||||
if (!dockWidget || dockWidget->tabWidget()->isHidden())
|
||||
return;
|
||||
#endif
|
||||
|
||||
d->updateDockWidgetFocus(dockWidget);
|
||||
}
|
||||
|
||||
void DockFocusController::setDockWidgetFocused(DockWidget *focusedNow)
|
||||
{
|
||||
d->updateDockWidgetFocus(focusedNow);
|
||||
}
|
||||
|
||||
void DockFocusController::onFocusedDockAreaViewToggled(bool open)
|
||||
{
|
||||
if (d->m_dockManager->isRestoringState())
|
||||
return;
|
||||
|
||||
DockAreaWidget* dockArea = qobject_cast<DockAreaWidget *>(sender());
|
||||
if (!dockArea || open)
|
||||
return;
|
||||
|
||||
auto container = dockArea->dockContainer();
|
||||
auto openedDockAreas = container->openedDockAreas();
|
||||
if (openedDockAreas.isEmpty())
|
||||
return;
|
||||
|
||||
DockManager::setWidgetFocus(openedDockAreas[0]->currentDockWidget()->tabWidget());
|
||||
}
|
||||
|
||||
void DockFocusController::notifyWidgetOrAreaRelocation(QWidget *droppedWidget)
|
||||
{
|
||||
if (d->m_dockManager->isRestoringState())
|
||||
return;
|
||||
|
||||
DockWidget *dockWidget = qobject_cast<DockWidget *>(droppedWidget);
|
||||
if (dockWidget)
|
||||
{
|
||||
DockManager::setWidgetFocus(dockWidget->tabWidget());
|
||||
return;
|
||||
}
|
||||
|
||||
DockAreaWidget* dockArea = qobject_cast<DockAreaWidget*>(droppedWidget);
|
||||
if (!dockArea)
|
||||
return;
|
||||
|
||||
dockWidget = dockArea->currentDockWidget();
|
||||
DockManager::setWidgetFocus(dockWidget->tabWidget());
|
||||
}
|
||||
|
||||
void DockFocusController::notifyFloatingWidgetDrop(FloatingDockContainer *floatingWidget)
|
||||
{
|
||||
if (!floatingWidget || d->m_dockManager->isRestoringState())
|
||||
return;
|
||||
|
||||
auto vDockWidget = floatingWidget->property("FocusedDockWidget");
|
||||
if (!vDockWidget.isValid())
|
||||
return;
|
||||
|
||||
auto dockWidget = vDockWidget.value<DockWidget *>();
|
||||
if (dockWidget) {
|
||||
dockWidget->dockAreaWidget()->setCurrentDockWidget(dockWidget);
|
||||
DockManager::setWidgetFocus(dockWidget->tabWidget());
|
||||
}
|
||||
}
|
||||
|
||||
void DockFocusController::onStateRestored()
|
||||
{
|
||||
if (d->m_focusedDockWidget)
|
||||
updateDockWidgetFocusStyle(d->m_focusedDockWidget, false);
|
||||
}
|
||||
|
||||
} // namespace ADS
|
109
src/libs/advanceddockingsystem/dockfocuscontroller.h
Normal file
109
src/libs/advanceddockingsystem/dockfocuscontroller.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Uwe Kindler
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or (at your option) any later version.
|
||||
** The licenses are as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.LGPLv21 included in the packaging
|
||||
** of this file. Please review the following information to ensure
|
||||
** the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 or (at your option) any later version
|
||||
** approved by the KDE Free Qt Foundation. The licenses are as published by
|
||||
** the Free Software Foundation and appearing in the file LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ads_globals.h"
|
||||
#include "dockmanager.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace ADS {
|
||||
|
||||
class DockFocusControllerPrivate;
|
||||
class DockManager;
|
||||
class FloatingDockContainer;
|
||||
|
||||
/**
|
||||
* Manages focus styling of dock widgets and handling of focus changes
|
||||
*/
|
||||
class ADS_EXPORT DockFocusController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
DockFocusControllerPrivate* d; ///< private data (pimpl)
|
||||
friend class DockFocusControllerPrivate;
|
||||
|
||||
private:
|
||||
void onApplicationFocusChanged(QWidget *old, QWidget *now);
|
||||
void onFocusedDockAreaViewToggled(bool open);
|
||||
void onStateRestored();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default Constructor
|
||||
*/
|
||||
DockFocusController(DockManager *dockManager);
|
||||
|
||||
/**
|
||||
* Virtual Destructor
|
||||
*/
|
||||
~DockFocusController() override;
|
||||
|
||||
/**
|
||||
* Helper function to set focus depending on the configuration of the
|
||||
* FocusStyling flag
|
||||
*/
|
||||
template <class QWidgetPtr>
|
||||
static void setWidgetFocus(QWidgetPtr widget)
|
||||
{
|
||||
if (!DockManager::testConfigFlag(DockManager::FocusHighlighting))
|
||||
return;
|
||||
|
||||
widget->setFocus(Qt::OtherFocusReason);
|
||||
}
|
||||
|
||||
/**
|
||||
* A container needs to call this function if a widget has been dropped
|
||||
* into it
|
||||
*/
|
||||
void notifyWidgetOrAreaRelocation(QWidget *relocatedWidget);
|
||||
|
||||
/**
|
||||
* This function is called, if a floating widget has been dropped into
|
||||
* an new position.
|
||||
* When this function is called, all dock widgets of the FloatingWidget
|
||||
* are already inserted into its new position
|
||||
*/
|
||||
void notifyFloatingWidgetDrop(FloatingDockContainer *floatingWidget);
|
||||
|
||||
/**
|
||||
* Request a focus change to the given dock widget
|
||||
*/
|
||||
void setDockWidgetFocused(DockWidget *focusedNow);
|
||||
}; // class DockFocusController
|
||||
|
||||
} // namespace ADS
|
@@ -36,7 +36,9 @@
|
||||
#include "dockmanager.h"
|
||||
|
||||
#include "ads_globals.h"
|
||||
#include "dockareatitlebar.h"
|
||||
#include "dockareawidget.h"
|
||||
#include "dockfocuscontroller.h"
|
||||
#include "dockingstatereader.h"
|
||||
#include "dockoverlay.h"
|
||||
#include "dockwidget.h"
|
||||
@@ -72,6 +74,15 @@ static Q_LOGGING_CATEGORY(adsLog, "qtc.qmldesigner.advanceddockingsystem", QtWar
|
||||
|
||||
namespace ADS
|
||||
{
|
||||
/**
|
||||
* Internal file version in case the structure changes internally
|
||||
*/
|
||||
enum eStateFileVersion {
|
||||
InitialVersion = 0, //!< InitialVersion
|
||||
Version1 = 1, //!< Version1
|
||||
CurrentVersion = Version1 //!< CurrentVersion
|
||||
};
|
||||
|
||||
static DockManager::ConfigFlags g_staticConfigFlags = DockManager::DefaultNonOpaqueConfig;
|
||||
|
||||
/**
|
||||
@@ -88,6 +99,7 @@ namespace ADS
|
||||
QMap<QString, DockWidget *> m_dockWidgetsMap;
|
||||
bool m_restoringState = false;
|
||||
QVector<FloatingDockContainer *> m_uninitializedFloatingWidgets;
|
||||
DockFocusController *m_focusController = nullptr;
|
||||
|
||||
QString m_workspaceName;
|
||||
bool m_workspaceListDirty = true;
|
||||
@@ -159,12 +171,11 @@ namespace ADS
|
||||
} else {
|
||||
qCInfo(adsLog) << "d->m_containers[i]->restoreState ";
|
||||
auto container = m_containers[index];
|
||||
if (container->isFloating()) {
|
||||
if (container->isFloating())
|
||||
result = container->floatingWidget()->restoreState(stream, testing);
|
||||
} else {
|
||||
else
|
||||
result = container->restoreState(stream, testing);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -190,6 +201,17 @@ namespace ADS
|
||||
return false;
|
||||
|
||||
stateReader.setFileVersion(v);
|
||||
|
||||
qCInfo(adsLog) << stateReader.attributes().value("userVersion");
|
||||
// Older files do not support UserVersion but we still want to load them so
|
||||
// we first test if the attribute exists
|
||||
if (!stateReader.attributes().value("userVersion").isEmpty())
|
||||
{
|
||||
v = stateReader.attributes().value("userVersion").toInt(&ok);
|
||||
if (!ok || v != version)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
#ifdef ADS_DEBUG_PRINT
|
||||
int dockContainers = stateReader.attributes().value("containers").toInt();
|
||||
@@ -248,9 +270,8 @@ namespace ADS
|
||||
DockAreaWidget *dockArea = dockContainer->dockArea(i);
|
||||
QString dockWidgetName = dockArea->property("currentDockWidget").toString();
|
||||
DockWidget *dockWidget = nullptr;
|
||||
if (!dockWidgetName.isEmpty()) {
|
||||
if (!dockWidgetName.isEmpty())
|
||||
dockWidget = q->findDockWidget(dockWidgetName);
|
||||
}
|
||||
|
||||
if (!dockWidget || dockWidget->isClosed()) {
|
||||
int index = dockArea->indexOfFirstOpenDockWidget();
|
||||
@@ -276,13 +297,12 @@ namespace ADS
|
||||
} else {
|
||||
for (int i = 0; i < dockContainer->dockAreaCount(); ++i) {
|
||||
auto dockArea = dockContainer->dockArea(i);
|
||||
for (auto dockWidget : dockArea->dockWidgets()) {
|
||||
for (auto dockWidget : dockArea->dockWidgets())
|
||||
dockWidget->emitTopLevelChanged(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DockManagerPrivate::restoreState(const QByteArray &state, int version)
|
||||
{
|
||||
@@ -326,6 +346,9 @@ namespace ADS
|
||||
d->m_dockAreaOverlay = new DockOverlay(this, DockOverlay::ModeDockAreaOverlay);
|
||||
d->m_containerOverlay = new DockOverlay(this, DockOverlay::ModeContainerOverlay);
|
||||
d->m_containers.append(this);
|
||||
|
||||
if (DockManager::configFlags().testFlag(DockManager::FocusHighlighting))
|
||||
d->m_focusController = new DockFocusController(this);
|
||||
}
|
||||
|
||||
DockManager::~DockManager()
|
||||
@@ -398,14 +421,13 @@ namespace ADS
|
||||
DockAreaWidget *DockManager::addDockWidgetTab(DockWidgetArea area, DockWidget *dockWidget)
|
||||
{
|
||||
DockAreaWidget *areaWidget = lastAddedDockAreaWidget(area);
|
||||
if (areaWidget) {
|
||||
if (areaWidget)
|
||||
return addDockWidget(ADS::CenterDockWidgetArea, dockWidget, areaWidget);
|
||||
} else if (!openedDockAreas().isEmpty()) {
|
||||
else if (!openedDockAreas().isEmpty())
|
||||
return addDockWidget(area, dockWidget, openedDockAreas().last());
|
||||
} else {
|
||||
else
|
||||
return addDockWidget(area, dockWidget, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
DockAreaWidget *DockManager::addDockWidgetTabToArea(DockWidget *dockWidget,
|
||||
DockAreaWidget *dockAreaWidget)
|
||||
@@ -423,11 +445,11 @@ namespace ADS
|
||||
dockWidget->setDockManager(this);
|
||||
FloatingDockContainer *floatingWidget = new FloatingDockContainer(dockWidget);
|
||||
floatingWidget->resize(dockWidget->size());
|
||||
if (isVisible()) {
|
||||
if (isVisible())
|
||||
floatingWidget->show();
|
||||
} else {
|
||||
else
|
||||
d->m_uninitializedFloatingWidgets.append(floatingWidget);
|
||||
}
|
||||
|
||||
return floatingWidget;
|
||||
}
|
||||
|
||||
@@ -450,10 +472,9 @@ namespace ADS
|
||||
|
||||
void DockManager::removeDockContainer(DockContainerWidget *dockContainer)
|
||||
{
|
||||
if (this != dockContainer) {
|
||||
if (this != dockContainer)
|
||||
d->m_containers.removeAll(dockContainer);
|
||||
}
|
||||
}
|
||||
|
||||
DockOverlay *DockManager::containerOverlay() const { return d->m_containerOverlay; }
|
||||
|
||||
@@ -479,7 +500,8 @@ namespace ADS
|
||||
stream.setAutoFormatting(configFlags.testFlag(XmlAutoFormattingEnabled));
|
||||
stream.writeStartDocument();
|
||||
stream.writeStartElement("QtAdvancedDockingSystem");
|
||||
stream.writeAttribute("version", QString::number(version));
|
||||
stream.writeAttribute("version", QString::number(CurrentVersion));
|
||||
stream.writeAttribute("userVersion", QString::number(version));
|
||||
stream.writeAttribute("containers", QString::number(d->m_containers.count()));
|
||||
for (auto container : d->m_containers)
|
||||
container->saveState(stream);
|
||||
@@ -512,10 +534,10 @@ namespace ADS
|
||||
emit restoringState();
|
||||
bool result = d->restoreState(state, version);
|
||||
d->m_restoringState = false;
|
||||
emit stateRestored();
|
||||
if (!isHidden)
|
||||
show();
|
||||
|
||||
emit stateRestored();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -574,15 +596,14 @@ namespace ADS
|
||||
emit aboutToSaveWorkspace();
|
||||
|
||||
bool result = write(activeWorkspace(), saveState(), parentWidget());
|
||||
if (result) {
|
||||
if (result)
|
||||
d->m_workspaceDateTimes.insert(activeWorkspace(), QDateTime::currentDateTime());
|
||||
} else {
|
||||
else
|
||||
QMessageBox::warning(parentWidget(),
|
||||
tr("Cannot Save Workspace"),
|
||||
tr("Could not save workspace to file %1")
|
||||
.arg(workspaceNameToFilePath(d->m_workspaceName)
|
||||
.toUserOutput()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -638,10 +659,9 @@ namespace ADS
|
||||
= workspacePresetsDir.entryInfoList(QStringList() << QLatin1Char('*') + m_fileExt,
|
||||
QDir::NoFilter,
|
||||
QDir::Time);
|
||||
for (const QFileInfo &fileInfo : workspacePresetsFiles) {
|
||||
for (const QFileInfo &fileInfo : workspacePresetsFiles)
|
||||
d->m_workspacePresets.insert(fileNameToWorkspaceName(fileInfo.completeBaseName()));
|
||||
}
|
||||
}
|
||||
return d->m_workspacePresets;
|
||||
}
|
||||
|
||||
@@ -819,8 +839,10 @@ namespace ADS
|
||||
{
|
||||
if (!cloneWorkspace(original, newName))
|
||||
return false;
|
||||
|
||||
if (original == activeWorkspace())
|
||||
openWorkspace(newName);
|
||||
|
||||
return deleteWorkspace(original);
|
||||
}
|
||||
|
||||
@@ -1002,10 +1024,10 @@ namespace ADS
|
||||
QFile file(filePath);
|
||||
|
||||
if (file.exists()) {
|
||||
if (!file.copy(workspaceDir.filePath(fileName))) {
|
||||
if (!file.copy(workspaceDir.filePath(fileName)))
|
||||
qCInfo(adsLog) << QString("Could not copy '%1' to '%2' error: %3").arg(
|
||||
filePath, workspaceDir.filePath(fileName), file.errorString());
|
||||
}
|
||||
|
||||
d->m_workspaceListDirty = true;
|
||||
}
|
||||
}
|
||||
@@ -1020,4 +1042,22 @@ namespace ADS
|
||||
d->m_settings->setValue(Constants::STARTUP_WORKSPACE_SETTINGS_KEY, activeWorkspace());
|
||||
}
|
||||
|
||||
void DockManager::notifyWidgetOrAreaRelocation(QWidget *droppedWidget)
|
||||
{
|
||||
if (d->m_focusController)
|
||||
d->m_focusController->notifyWidgetOrAreaRelocation(droppedWidget);
|
||||
}
|
||||
|
||||
void DockManager::notifyFloatingWidgetDrop(FloatingDockContainer *floatingWidget)
|
||||
{
|
||||
if (d->m_focusController)
|
||||
d->m_focusController->notifyFloatingWidgetDrop(floatingWidget);
|
||||
}
|
||||
|
||||
void DockManager::setDockWidgetFocused(DockWidget *dockWidget)
|
||||
{
|
||||
if (d->m_focusController)
|
||||
d->m_focusController->setDockWidgetFocused(dockWidget);
|
||||
}
|
||||
|
||||
} // namespace ADS
|
||||
|
@@ -142,6 +142,32 @@ protected:
|
||||
*/
|
||||
DockOverlay *dockAreaOverlay() const;
|
||||
|
||||
/**
|
||||
* A container needs to call this function if a widget has been dropped
|
||||
* into it
|
||||
*/
|
||||
void notifyWidgetOrAreaRelocation(QWidget *droppedWidget);
|
||||
|
||||
/**
|
||||
* This function is called, if a floating widget has been dropped into
|
||||
* an new position.
|
||||
* When this function is called, all dock widgets of the FloatingWidget
|
||||
* are already inserted into its new position
|
||||
*/
|
||||
void notifyFloatingWidgetDrop(FloatingDockContainer *floatingWidget);
|
||||
|
||||
/**
|
||||
* This function is called, if the given DockWidget has been relocated from
|
||||
* the old container ContainerOld to the new container DockWidget->dockContainer()
|
||||
*/
|
||||
void notifyDockWidgetRelocation(DockWidget *dockWidget, DockContainerWidget *containerOld);
|
||||
|
||||
/**
|
||||
* This function is called, if the given DockAreahas been relocated from
|
||||
* the old container ContainerOld to the new container DockArea->dockContainer()
|
||||
*/
|
||||
void notifyDockAreaRelocation(DockAreaWidget *dockArea, DockContainerWidget *containerOld);
|
||||
|
||||
/**
|
||||
* Show the floating widgets that has been created floating
|
||||
*/
|
||||
@@ -190,11 +216,18 @@ public:
|
||||
DockAreaHideDisabledButtons
|
||||
= 0x10000, //!< If the flag is set disabled dock area buttons will not appear on the tollbar at all (enabling them will bring them back)
|
||||
DockAreaDynamicTabsMenuButtonVisibility
|
||||
= 0x20000, //!< If the flag is set dock area will disable a tabs menu button when there is only one tab in the area
|
||||
= 0x20000, //!< If the flag is set, the tabs menu button will be shown only when it is required - that means, if the tabs are elided. If the tabs are not elided, it is hidden
|
||||
FloatingContainerHasWidgetTitle
|
||||
= 0x40000,
|
||||
= 0x40000, //!< If set, the Floating Widget window title reflects the title of the current dock widget otherwise it displays application name as window title
|
||||
FloatingContainerHasWidgetIcon
|
||||
= 0x80000,
|
||||
= 0x80000, //!< If set, the Floating Widget icon reflects the icon of the current dock widget otherwise it displays application icon
|
||||
HideSingleCentralWidgetTitleBar
|
||||
= 0x100000, //!< If there is only one single visible dock widget in the main dock container (the dock manager) and if this flag is set, then the titlebar of this dock widget will be hidden
|
||||
//!< this only makes sense for non draggable and non floatable widgets and enables the creation of some kind of "central" widget
|
||||
FocusHighlighting
|
||||
= 0x200000, //!< enables styling of focused dock widget tabs or floating widget titlebar
|
||||
EqualSplitOnInsertion
|
||||
= 0x400000, ///!< if enabled, the space is equally distributed to all widgets in a splitter
|
||||
|
||||
DefaultDockAreaButtons = DockAreaHasCloseButton
|
||||
| DockAreaHasUndockButton
|
||||
@@ -267,6 +300,19 @@ public:
|
||||
*/
|
||||
static int startDragDistance();
|
||||
|
||||
/**
|
||||
* Helper function to set focus depending on the configuration of the
|
||||
* FocusStyling flag
|
||||
*/
|
||||
template <class QWidgetPtr>
|
||||
static void setWidgetFocus(QWidgetPtr widget)
|
||||
{
|
||||
if (!DockManager::testConfigFlag(DockManager::FocusHighlighting))
|
||||
return;
|
||||
|
||||
widget->setFocus(Qt::OtherFocusReason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the QtCreator settings.
|
||||
*/
|
||||
@@ -358,8 +404,12 @@ public:
|
||||
* If auto formatting is enabled, the output is intended and line wrapped.
|
||||
* The XmlMode XmlAutoFormattingDisabled is better if you would like to have
|
||||
* a more compact XML output - i.e. for storage in ini files.
|
||||
* The version number is stored as part of the data.
|
||||
* To restore the saved state, pass the return value and version number
|
||||
* to restoreState().
|
||||
* \see restoreState()
|
||||
*/
|
||||
QByteArray saveState(int version = Version1) const;
|
||||
QByteArray saveState(int version = 0) const;
|
||||
|
||||
/**
|
||||
* Restores the state of this dockmanagers dockwidgets.
|
||||
@@ -367,8 +417,9 @@ public:
|
||||
* not match, the dockmanager's state is left unchanged, and this function
|
||||
* returns false; otherwise, the state is restored, and this function
|
||||
* returns true.
|
||||
* \see saveState()
|
||||
*/
|
||||
bool restoreState(const QByteArray &state, int version = Version1);
|
||||
bool restoreState(const QByteArray &state, int version = 0);
|
||||
|
||||
/**
|
||||
* This function returns true between the restoringState() and
|
||||
@@ -376,6 +427,13 @@ public:
|
||||
*/
|
||||
bool isRestoringState() const;
|
||||
|
||||
/**
|
||||
* Request a focus change to the given dock widget.
|
||||
* This function only has an effect, if the flag CDockManager::FocusStyling
|
||||
* is enabled
|
||||
*/
|
||||
void setDockWidgetFocused(DockWidget *dockWidget);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* This signal is emitted if the list of workspaces changed.
|
||||
@@ -444,6 +502,13 @@ signals:
|
||||
*/
|
||||
void dockWidgetRemoved(DockWidget *dockWidget);
|
||||
|
||||
/**
|
||||
* This signal is emitted if the focused dock widget changed.
|
||||
* Both old and now can be nullptr.
|
||||
* The focused dock widget is the one that is highlighted in the GUI
|
||||
*/
|
||||
void focusedDockWidgetChanged(DockWidget *old, DockWidget *now);
|
||||
|
||||
public:
|
||||
void showWorkspaceMananger();
|
||||
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#include "dockoverlay.h"
|
||||
|
||||
#include "dockareawidget.h"
|
||||
#include "dockareatitlebar.h"
|
||||
|
||||
#include <utils/hostosinfo.h>
|
||||
|
||||
@@ -151,12 +152,10 @@ namespace ADS {
|
||||
*/
|
||||
qreal dropIndicatiorWidth(QLabel *label) const
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
Q_UNUSED(label)
|
||||
if (Utils::HostOsInfo::isLinuxHost())
|
||||
return 40;
|
||||
#else
|
||||
else
|
||||
return static_cast<qreal>(label->fontMetrics().height()) * 3.f;
|
||||
#endif
|
||||
}
|
||||
|
||||
QWidget *createDropIndicatorWidget(DockWidgetArea dockWidgetArea, DockOverlay::eMode mode)
|
||||
@@ -190,10 +189,10 @@ namespace ADS {
|
||||
DockWidgetArea dockWidgetArea,
|
||||
DockOverlay::eMode mode)
|
||||
{
|
||||
QColor borderColor = iconColor(DockOverlayCross::FrameColor);
|
||||
QColor backgroundColor = iconColor(DockOverlayCross::WindowBackgroundColor);
|
||||
double devicePixelRatio = q->window()->devicePixelRatioF();
|
||||
QSizeF pixmapSize = size * devicePixelRatio;
|
||||
const QColor borderColor = iconColor(DockOverlayCross::FrameColor);
|
||||
const QColor backgroundColor = iconColor(DockOverlayCross::WindowBackgroundColor);
|
||||
const double devicePixelRatio = q->window()->devicePixelRatioF();
|
||||
const QSizeF pixmapSize = size * devicePixelRatio;
|
||||
QPixmap pixmap(pixmapSize.toSize());
|
||||
pixmap.fill(QColor(0, 0, 0, 0));
|
||||
|
||||
@@ -259,7 +258,7 @@ namespace ADS {
|
||||
break;
|
||||
}
|
||||
|
||||
QSizeF baseSize = baseRect.size();
|
||||
const QSizeF baseSize = baseRect.size();
|
||||
if (DockOverlay::ModeContainerOverlay == mode && dockWidgetArea != CenterDockWidgetArea) {
|
||||
baseRect = areaRect;
|
||||
}
|
||||
@@ -296,7 +295,7 @@ namespace ADS {
|
||||
|
||||
// draw window title bar
|
||||
painter.setBrush(borderColor);
|
||||
QRectF frameRect(baseRect.topLeft(), QSizeF(baseRect.width(), baseSize.height() / 10));
|
||||
const QRectF frameRect(baseRect.topLeft(), QSizeF(baseRect.width(), baseSize.height() / 10));
|
||||
painter.drawRect(frameRect);
|
||||
painter.restore();
|
||||
|
||||
@@ -370,6 +369,7 @@ namespace ADS {
|
||||
{
|
||||
if (areas == d->m_allowedAreas)
|
||||
return;
|
||||
|
||||
d->m_allowedAreas = areas;
|
||||
d->m_cross->reset();
|
||||
}
|
||||
@@ -382,19 +382,17 @@ namespace ADS {
|
||||
DockWidgetArea DockOverlay::dropAreaUnderCursor() const
|
||||
{
|
||||
DockWidgetArea result = d->m_cross->cursorLocation();
|
||||
if (result != InvalidDockWidgetArea) {
|
||||
if (result != InvalidDockWidgetArea)
|
||||
return result;
|
||||
}
|
||||
|
||||
DockAreaWidget *dockArea = qobject_cast<DockAreaWidget *>(d->m_targetWidget.data());
|
||||
if (!dockArea) {
|
||||
if (!dockArea)
|
||||
return result;
|
||||
}
|
||||
|
||||
if (dockArea->allowedAreas().testFlag(CenterDockWidgetArea)
|
||||
&& dockArea->titleBarGeometry().contains(dockArea->mapFromGlobal(QCursor::pos()))) {
|
||||
&& !dockArea->titleBar()->isHidden()
|
||||
&& dockArea->titleBarGeometry().contains(dockArea->mapFromGlobal(QCursor::pos())))
|
||||
return CenterDockWidgetArea;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -518,9 +516,9 @@ namespace ADS {
|
||||
bool DockOverlay::event(QEvent *event)
|
||||
{
|
||||
bool result = Super::event(event);
|
||||
if (event->type() == QEvent::Polish) {
|
||||
if (event->type() == QEvent::Polish)
|
||||
d->m_cross->setupOverlayCross(d->m_mode);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -622,13 +620,12 @@ namespace ADS {
|
||||
|
||||
void DockOverlayCross::updateOverlayIcons()
|
||||
{
|
||||
if (windowHandle()->devicePixelRatio() == d->m_lastDevicePixelRatio) { // TODO
|
||||
if (windowHandle()->devicePixelRatio() == d->m_lastDevicePixelRatio) // TODO
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto Widget : d->m_dropIndicatorWidgets) {
|
||||
d->updateDropIndicatorIcon(Widget);
|
||||
}
|
||||
for (auto widget : d->m_dropIndicatorWidgets)
|
||||
d->updateDropIndicatorIcon(widget);
|
||||
|
||||
d->m_lastDevicePixelRatio = devicePixelRatioF();
|
||||
}
|
||||
|
||||
@@ -661,7 +658,7 @@ namespace ADS {
|
||||
for (constIt = areas.begin(); constIt != areas.end(); ++constIt) {
|
||||
const DockWidgetArea area = constIt.key();
|
||||
QWidget *widget = constIt.value();
|
||||
QPoint position = d->areaGridPosition(area);
|
||||
const QPoint position = d->areaGridPosition(area);
|
||||
d->m_gridLayout->addWidget(widget,
|
||||
position.x(),
|
||||
position.y(),
|
||||
@@ -717,9 +714,9 @@ namespace ADS {
|
||||
|
||||
void DockOverlayCross::showEvent(QShowEvent *)
|
||||
{
|
||||
if (d->m_updateRequired) {
|
||||
if (d->m_updateRequired)
|
||||
setupOverlayCross(d->m_mode);
|
||||
}
|
||||
|
||||
this->updatePosition();
|
||||
}
|
||||
|
||||
@@ -744,14 +741,13 @@ namespace ADS {
|
||||
|
||||
// Update visibility of area widgets based on allowedAreas.
|
||||
for (auto area : allAreas) {
|
||||
QPoint position = d->areaGridPosition(area);
|
||||
const QPoint position = d->areaGridPosition(area);
|
||||
QLayoutItem *item = d->m_gridLayout->itemAtPosition(position.x(), position.y());
|
||||
QWidget *widget = nullptr;
|
||||
if (item && (widget = item->widget()) != nullptr) {
|
||||
if (item && (widget = item->widget()) != nullptr)
|
||||
widget->setVisible(allowedAreas.testFlag(area));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DockOverlayCross::setIconColors(const QString &colors)
|
||||
{
|
||||
@@ -766,9 +762,9 @@ namespace ADS {
|
||||
for (const auto &colorListEntry : colorList) {
|
||||
auto componentColor = colorListEntry.split('=', QString::SkipEmptyParts);
|
||||
int component = colorCompenentStringMap.value(componentColor[0], -1);
|
||||
if (component < 0) {
|
||||
if (component < 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
d->m_iconColors[component] = QColor(componentColor[1]);
|
||||
}
|
||||
|
||||
|
@@ -55,6 +55,7 @@
|
||||
#include <QTextStream>
|
||||
#include <QToolBar>
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QWindow>
|
||||
|
||||
static Q_LOGGING_CATEGORY(adsLog, "qtc.qmldesigner.advanceddockingsystem", QtWarningMsg)
|
||||
|
||||
@@ -127,6 +128,7 @@ namespace ADS
|
||||
if (!m_dockArea) {
|
||||
FloatingDockContainer *floatingWidget = new FloatingDockContainer(q);
|
||||
floatingWidget->resize(q->size());
|
||||
m_tabWidget->show();
|
||||
floatingWidget->show();
|
||||
} else {
|
||||
m_dockArea->setCurrentDockWidget(q);
|
||||
@@ -204,6 +206,9 @@ namespace ADS
|
||||
d->m_toggleViewAction->setCheckable(true);
|
||||
connect(d->m_toggleViewAction, &QAction::triggered, this, &DockWidget::toggleView);
|
||||
setToolbarFloatingStyle(false);
|
||||
|
||||
if (DockManager::testConfigFlag(DockManager::FocusHighlighting))
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
}
|
||||
|
||||
DockWidget::~DockWidget()
|
||||
@@ -222,7 +227,10 @@ namespace ADS
|
||||
|
||||
void DockWidget::setWidget(QWidget *widget, eInsertMode insertMode)
|
||||
{
|
||||
QScrollArea *scrollAreaWidget = qobject_cast<QScrollArea *>(widget);
|
||||
if (d->m_widget)
|
||||
takeWidget();
|
||||
|
||||
auto scrollAreaWidget = qobject_cast<QAbstractScrollArea *>(widget);
|
||||
if (scrollAreaWidget || ForceNoScrollArea == insertMode) {
|
||||
d->m_layout->addWidget(widget);
|
||||
if (scrollAreaWidget && scrollAreaWidget->viewport())
|
||||
@@ -238,11 +246,23 @@ namespace ADS
|
||||
|
||||
QWidget *DockWidget::takeWidget()
|
||||
{
|
||||
// TODO Shouldn't m_widget being set to nullptr?!
|
||||
d->m_scrollArea->takeWidget();
|
||||
QWidget *w = nullptr;
|
||||
if (d->m_scrollArea) {
|
||||
d->m_layout->removeWidget(d->m_scrollArea);
|
||||
w = d->m_scrollArea->takeWidget();
|
||||
delete d->m_scrollArea;
|
||||
d->m_scrollArea = nullptr;
|
||||
d->m_widget = nullptr;
|
||||
} else if (d->m_widget) {
|
||||
d->m_layout->removeWidget(d->m_widget);
|
||||
d->m_widget->setParent(nullptr);
|
||||
return d->m_widget;
|
||||
w = d->m_widget;
|
||||
d->m_widget = nullptr;
|
||||
}
|
||||
|
||||
if (w)
|
||||
w->setParent(nullptr);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
QWidget *DockWidget::widget() const { return d->m_widget; }
|
||||
@@ -251,9 +271,9 @@ namespace ADS
|
||||
|
||||
void DockWidget::setFeatures(DockWidgetFeatures features)
|
||||
{
|
||||
if (d->m_features == features) {
|
||||
if (d->m_features == features)
|
||||
return;
|
||||
}
|
||||
|
||||
d->m_features = features;
|
||||
emit featuresChanged(d->m_features);
|
||||
d->m_tabWidget->onDockWidgetFeaturesChanged();
|
||||
@@ -274,12 +294,11 @@ namespace ADS
|
||||
|
||||
DockContainerWidget *DockWidget::dockContainer() const
|
||||
{
|
||||
if (d->m_dockArea) {
|
||||
if (d->m_dockArea)
|
||||
return d->m_dockArea->dockContainer();
|
||||
} else {
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
DockAreaWidget *DockWidget::dockAreaWidget() const { return d->m_dockArea; }
|
||||
|
||||
@@ -347,11 +366,11 @@ namespace ADS
|
||||
? beforeDockContainerWidget->topLevelDockWidget()
|
||||
: nullptr;
|
||||
|
||||
if (open) {
|
||||
if (open)
|
||||
d->showDockWidget();
|
||||
} else {
|
||||
else
|
||||
d->hideDockWidget();
|
||||
}
|
||||
|
||||
d->m_closed = !open;
|
||||
//d->m_toggleViewAction->blockSignals(true);
|
||||
d->m_toggleViewAction->setChecked(open);
|
||||
@@ -449,7 +468,7 @@ namespace ADS
|
||||
d->m_toggleViewAction->setToolTip(text);
|
||||
|
||||
if (d->m_dockArea)
|
||||
d->m_dockArea->markTitleBarMenuOutdated(); //update tabs menu
|
||||
d->m_dockArea->markTitleBarMenuOutdated(); // update tabs menu
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -617,4 +636,58 @@ namespace ADS
|
||||
return d->m_titleBarActions;
|
||||
}
|
||||
|
||||
void DockWidget::showFullScreen()
|
||||
{
|
||||
if (isFloating())
|
||||
dockContainer()->floatingWidget()->showFullScreen();
|
||||
else
|
||||
Super::showFullScreen();
|
||||
}
|
||||
|
||||
void DockWidget::showNormal()
|
||||
{
|
||||
if (isFloating())
|
||||
dockContainer()->floatingWidget()->showNormal();
|
||||
else
|
||||
Super::showNormal();
|
||||
}
|
||||
|
||||
bool DockWidget::isFullScreen() const
|
||||
{
|
||||
if (isFloating())
|
||||
return dockContainer()->floatingWidget()->isFullScreen();
|
||||
else
|
||||
return Super::isFullScreen();
|
||||
}
|
||||
|
||||
void DockWidget::setAsCurrentTab()
|
||||
{
|
||||
if (d->m_dockArea && !isClosed())
|
||||
d->m_dockArea->setCurrentDockWidget(this);
|
||||
}
|
||||
|
||||
bool DockWidget::isTabbed() const
|
||||
{
|
||||
return d->m_dockArea && (d->m_dockArea->openDockWidgetsCount() > 1);
|
||||
}
|
||||
|
||||
bool DockWidget::isCurrentTab() const
|
||||
{
|
||||
return d->m_dockArea && (d->m_dockArea->currentDockWidget() == this);
|
||||
}
|
||||
|
||||
void DockWidget::raise()
|
||||
{
|
||||
if (isClosed())
|
||||
return;
|
||||
|
||||
setAsCurrentTab();
|
||||
if (isInFloatingContainer())
|
||||
{
|
||||
auto floatingWindow = window();
|
||||
floatingWindow->raise();
|
||||
floatingWindow->activateWindow();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ADS
|
||||
|
@@ -152,8 +152,8 @@ public:
|
||||
using Super = QFrame;
|
||||
|
||||
enum DockWidgetFeature {
|
||||
DockWidgetClosable = 0x01,
|
||||
DockWidgetMovable = 0x02,///< this feature is not properly implemented yet and is ignored
|
||||
DockWidgetClosable = 0x01,///< dock widget has a close button
|
||||
DockWidgetMovable = 0x02,///< dock widget is movable and can be moved to a new position in the current dock container
|
||||
DockWidgetFloatable = 0x04,
|
||||
DockWidgetDeleteOnClose = 0x08, ///< deletes the dock widget when it is closed
|
||||
CustomCloseHandling = 0x10,
|
||||
@@ -435,6 +435,26 @@ public:
|
||||
void setTabToolTip(const QString &text);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns true if the dock widget is floating and if the floating dock
|
||||
* container is full screen
|
||||
*/
|
||||
bool isFullScreen() const;
|
||||
|
||||
/**
|
||||
* Returns true if this dock widget is in a dock area, that contains at
|
||||
* least 2 opened dock widgets
|
||||
*/
|
||||
bool isTabbed() const;
|
||||
|
||||
/**
|
||||
* Returns true if this dock widget is the current one in the dock
|
||||
* area widget that contains it.
|
||||
* If the dock widget is the only opened dock widget in a dock area,
|
||||
* the true is returned
|
||||
*/
|
||||
bool isCurrentTab() const;
|
||||
|
||||
public: // reimplements QFrame
|
||||
/**
|
||||
* Emits titleChanged signal if title change event occurs
|
||||
@@ -447,6 +467,23 @@ public: // reimplements QFrame
|
||||
*/
|
||||
void toggleView(bool open = true);
|
||||
|
||||
/**
|
||||
* Makes this dock widget the current tab in its dock area.
|
||||
* The function only has an effect, if the dock widget is open. A call
|
||||
* to this function will not toggle the view, so if it is closed,
|
||||
* nothing will happen
|
||||
*/
|
||||
void setAsCurrentTab();
|
||||
|
||||
/**
|
||||
* Brings the dock widget to the front
|
||||
* This means:
|
||||
* - If the dock widget is tabbed with other dock widgets but its tab is not current, it's made current.
|
||||
* - If the dock widget is floating, QWindow::raise() is called.
|
||||
* This only applies if the dock widget is already open. If closed, does nothing.
|
||||
*/
|
||||
void raise();
|
||||
|
||||
/**
|
||||
* This function will make a docked widget floating
|
||||
*/
|
||||
@@ -463,6 +500,26 @@ public: // reimplements QFrame
|
||||
*/
|
||||
void closeDockWidget();
|
||||
|
||||
/**
|
||||
* Shows the widget in full-screen mode.
|
||||
* Normally this function only affects windows. To make the interface
|
||||
* compatible to QDockWidget, this function also maximizes a floating
|
||||
* dock widget.
|
||||
*
|
||||
* \note Full-screen mode works fine under Windows, but has certain
|
||||
* problems (doe not work) under X (Linux). These problems are due to
|
||||
* limitations of the ICCCM protocol that specifies the communication
|
||||
* between X11 clients and the window manager. ICCCM simply does not
|
||||
* understand the concept of non-decorated full-screen windows.
|
||||
*/
|
||||
void showFullScreen();
|
||||
|
||||
/**
|
||||
* This function complements showFullScreen() to restore the widget
|
||||
* after it has been in full screen mode.
|
||||
*/
|
||||
void showNormal();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* This signal is emitted if the dock widget is opened or closed
|
||||
|
@@ -116,7 +116,7 @@ namespace ADS
|
||||
*/
|
||||
bool testConfigFlag(DockManager::eConfigFlag flag) const
|
||||
{
|
||||
return DockManager::configFlags().testFlag(flag);
|
||||
return DockManager::testConfigFlag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,18 +232,20 @@ namespace ADS
|
||||
|
||||
qCInfo(adsLog) << "startFloating";
|
||||
m_dragState = draggingState;
|
||||
QSize size = m_dockArea->size();
|
||||
AbstractFloatingWidget *floatingWidget = nullptr;
|
||||
bool opaqueUndocking = DockManager::configFlags().testFlag(DockManager::OpaqueUndocking)
|
||||
bool opaqueUndocking = DockManager::testConfigFlag(DockManager::OpaqueUndocking)
|
||||
|| (DraggingFloatingWidget != draggingState);
|
||||
|
||||
// If section widget has multiple tabs, we take only one tab
|
||||
// If it has only one single tab, we can move the complete
|
||||
// dock area into floating widget
|
||||
QSize size;
|
||||
if (m_dockArea->dockWidgetsCount() > 1) {
|
||||
floatingWidget = createFloatingWidget(m_dockWidget, opaqueUndocking);
|
||||
size = m_dockWidget->size();
|
||||
} else {
|
||||
floatingWidget = createFloatingWidget(m_dockArea, opaqueUndocking);
|
||||
size = m_dockArea->size();
|
||||
}
|
||||
|
||||
if (DraggingFloatingWidget == draggingState) {
|
||||
@@ -265,6 +267,8 @@ namespace ADS
|
||||
setAttribute(Qt::WA_NoMousePropagation, true);
|
||||
d->m_dockWidget = dockWidget;
|
||||
d->createLayout();
|
||||
if (DockManager::testConfigFlag(DockManager::FocusHighlighting))
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
}
|
||||
|
||||
DockWidgetTab::~DockWidgetTab()
|
||||
@@ -358,9 +362,9 @@ namespace ADS
|
||||
// If we undock, we need to restore the initial position of this
|
||||
// tab because it looks strange if it remains on its dragged position
|
||||
if (d->isDraggingState(DraggingTab)
|
||||
&& !DockManager::configFlags().testFlag(DockManager::OpaqueUndocking)) {
|
||||
&& !DockManager::testConfigFlag(DockManager::OpaqueUndocking))
|
||||
parentWidget()->layout()->update();
|
||||
}
|
||||
|
||||
d->startFloating();
|
||||
}
|
||||
return;
|
||||
@@ -370,9 +374,9 @@ namespace ADS
|
||||
{
|
||||
// If we start dragging the tab, we save its initial position to
|
||||
// restore it later
|
||||
if (DraggingTab != d->m_dragState) {
|
||||
if (DraggingTab != d->m_dragState)
|
||||
d->m_tabDragStartPosition = this->pos();
|
||||
}
|
||||
|
||||
d->m_dragState = DraggingTab;
|
||||
return;
|
||||
}
|
||||
@@ -383,9 +387,8 @@ namespace ADS
|
||||
void DockWidgetTab::contextMenuEvent(QContextMenuEvent *event)
|
||||
{
|
||||
event->accept();
|
||||
if (d->isDraggingState(DraggingFloatingWidget)) {
|
||||
if (d->isDraggingState(DraggingFloatingWidget))
|
||||
return;
|
||||
}
|
||||
|
||||
d->saveDragStartMousePosition(event->globalPos());
|
||||
QMenu menu(this);
|
||||
@@ -413,16 +416,27 @@ namespace ADS
|
||||
bool allTabsHaveCloseButton = d->testConfigFlag(DockManager::AllTabsHaveCloseButton);
|
||||
bool tabHasCloseButton = (activeTabHasCloseButton && active) | allTabsHaveCloseButton;
|
||||
d->m_closeButton->setVisible(dockWidgetClosable && tabHasCloseButton);
|
||||
|
||||
// Focus related stuff
|
||||
if (DockManager::testConfigFlag(DockManager::FocusHighlighting)
|
||||
&& !d->m_dockWidget->dockManager()->isRestoringState()) {
|
||||
bool updateFocusStyle = false;
|
||||
if (active && !hasFocus()) {
|
||||
setFocus(Qt::OtherFocusReason);
|
||||
updateFocusStyle = true;
|
||||
}
|
||||
|
||||
if (d->m_isActiveTab == active) {
|
||||
if (updateFocusStyle)
|
||||
updateStyle();
|
||||
return;
|
||||
}
|
||||
} else if (d->m_isActiveTab == active) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->m_isActiveTab = active;
|
||||
|
||||
style()->unpolish(this);
|
||||
style()->polish(this);
|
||||
d->m_titleLabel->style()->unpolish(d->m_titleLabel);
|
||||
d->m_titleLabel->style()->polish(d->m_titleLabel);
|
||||
updateStyle();
|
||||
update();
|
||||
updateGeometry();
|
||||
|
||||
@@ -438,9 +452,8 @@ namespace ADS
|
||||
void DockWidgetTab::setIcon(const QIcon &icon)
|
||||
{
|
||||
QBoxLayout *boxLayout = qobject_cast<QBoxLayout *>(layout());
|
||||
if (!d->m_iconLabel && icon.isNull()) {
|
||||
if (!d->m_iconLabel && icon.isNull())
|
||||
return;
|
||||
}
|
||||
|
||||
if (!d->m_iconLabel) {
|
||||
d->m_iconLabel = new QLabel();
|
||||
@@ -499,9 +512,9 @@ namespace ADS
|
||||
|
||||
void DockWidgetTab::detachDockWidget()
|
||||
{
|
||||
if (!d->m_dockWidget->features().testFlag(DockWidget::DockWidgetFloatable)) {
|
||||
if (!d->m_dockWidget->features().testFlag(DockWidget::DockWidgetFloatable))
|
||||
return;
|
||||
}
|
||||
|
||||
d->saveDragStartMousePosition(QCursor::pos());
|
||||
d->startFloating(DraggingInactive);
|
||||
}
|
||||
@@ -527,4 +540,14 @@ namespace ADS
|
||||
d->m_closeButton->setSizePolicy(sizePolicy);
|
||||
}
|
||||
|
||||
void DockWidgetTab::setElideMode(Qt::TextElideMode mode)
|
||||
{
|
||||
d->m_titleLabel->setElideMode(mode);
|
||||
}
|
||||
|
||||
void DockWidgetTab::updateStyle()
|
||||
{
|
||||
internal::repolishStyle(this, internal::RepolishDirectChildren);
|
||||
}
|
||||
|
||||
} // namespace ADS
|
||||
|
@@ -59,6 +59,7 @@ private:
|
||||
DockWidgetTabPrivate *d; ///< private data (pimpl)
|
||||
friend class DockWidgetTabPrivate;
|
||||
friend class DockWidget;
|
||||
friend class DockManager;
|
||||
void onDockWidgetFeaturesChanged();
|
||||
void detachDockWidget();
|
||||
|
||||
@@ -150,6 +151,16 @@ public:
|
||||
*/
|
||||
bool event(QEvent *event) override;
|
||||
|
||||
/**
|
||||
* Sets the text elide mode
|
||||
*/
|
||||
void setElideMode(Qt::TextElideMode mode);
|
||||
|
||||
/**
|
||||
* Update stylesheet style if a property changes
|
||||
*/
|
||||
void updateStyle();
|
||||
|
||||
void setVisible(bool visible) override;
|
||||
|
||||
signals:
|
||||
|
@@ -115,9 +115,8 @@ namespace ADS {
|
||||
void ElidingLabel::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
Super::mouseReleaseEvent(event);
|
||||
if (event->button() != Qt::LeftButton) {
|
||||
if (event->button() != Qt::LeftButton)
|
||||
return;
|
||||
}
|
||||
|
||||
emit clicked();
|
||||
}
|
||||
@@ -131,17 +130,17 @@ namespace ADS {
|
||||
|
||||
void ElidingLabel::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
if (!d->isModeElideNone()) {
|
||||
if (!d->isModeElideNone())
|
||||
d->elideText(event->size().width());
|
||||
}
|
||||
|
||||
Super::resizeEvent(event);
|
||||
}
|
||||
|
||||
QSize ElidingLabel::minimumSizeHint() const
|
||||
{
|
||||
if (pixmap() != nullptr || d->isModeElideNone()) {
|
||||
if (pixmap() != nullptr || d->isModeElideNone())
|
||||
return QLabel::minimumSizeHint();
|
||||
}
|
||||
|
||||
const QFontMetrics &fm = fontMetrics();
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
|
||||
QSize size(fm.horizontalAdvance(d->m_text.left(2) + "…"), fm.height());
|
||||
@@ -153,9 +152,9 @@ namespace ADS {
|
||||
|
||||
QSize ElidingLabel::sizeHint() const
|
||||
{
|
||||
if (pixmap() != nullptr || d->isModeElideNone()) {
|
||||
if (pixmap() != nullptr || d->isModeElideNone())
|
||||
return QLabel::sizeHint();
|
||||
}
|
||||
|
||||
const QFontMetrics &fm = fontMetrics();
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
|
||||
QSize size(fm.horizontalAdvance(d->m_text), QLabel::sizeHint().height());
|
||||
@@ -167,10 +166,10 @@ namespace ADS {
|
||||
|
||||
void ElidingLabel::setText(const QString &text)
|
||||
{
|
||||
d->m_text = text;
|
||||
if (d->isModeElideNone()) {
|
||||
Super::setText(text);
|
||||
} else {
|
||||
d->m_text = text;
|
||||
internal::setToolTip(this, text);
|
||||
d->elideText(this->size().width());
|
||||
}
|
||||
|
@@ -41,6 +41,12 @@
|
||||
#include "dockoverlay.h"
|
||||
#include "dockwidget.h"
|
||||
#include "linux/floatingwidgettitlebar.h"
|
||||
#ifdef Q_OS_WIN
|
||||
#include <windows.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "User32.lib")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <QAbstractButton>
|
||||
#include <QAction>
|
||||
@@ -56,6 +62,303 @@ static Q_LOGGING_CATEGORY(adsLog, "qtc.qmldesigner.advanceddockingsystem", QtWar
|
||||
|
||||
namespace ADS
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
#if 0 // set to 1 if you need this function for debugging
|
||||
/**
|
||||
* Just for debugging to convert windows message identifiers to strings
|
||||
*/
|
||||
static const char* windowsMessageString(int messageId)
|
||||
{
|
||||
switch (messageId)
|
||||
{
|
||||
case 0: return "WM_NULL";
|
||||
case 1: return "WM_CREATE";
|
||||
case 2: return "WM_DESTROY";
|
||||
case 3: return "WM_MOVE";
|
||||
case 5: return "WM_SIZE";
|
||||
case 6: return "WM_ACTIVATE";
|
||||
case 7: return "WM_SETFOCUS";
|
||||
case 8: return "WM_KILLFOCUS";
|
||||
case 10: return "WM_ENABLE";
|
||||
case 11: return "WM_SETREDRAW";
|
||||
case 12: return "WM_SETTEXT";
|
||||
case 13: return "WM_GETTEXT";
|
||||
case 14: return "WM_GETTEXTLENGTH";
|
||||
case 15: return "WM_PAINT";
|
||||
case 16: return "WM_CLOSE";
|
||||
case 17: return "WM_QUERYENDSESSION";
|
||||
case 18: return "WM_QUIT";
|
||||
case 19: return "WM_QUERYOPEN";
|
||||
case 20: return "WM_ERASEBKGND";
|
||||
case 21: return "WM_SYSCOLORCHANGE";
|
||||
case 22: return "WM_ENDSESSION";
|
||||
case 24: return "WM_SHOWWINDOW";
|
||||
case 25: return "WM_CTLCOLOR";
|
||||
case 26: return "WM_WININICHANGE";
|
||||
case 27: return "WM_DEVMODECHANGE";
|
||||
case 28: return "WM_ACTIVATEAPP";
|
||||
case 29: return "WM_FONTCHANGE";
|
||||
case 30: return "WM_TIMECHANGE";
|
||||
case 31: return "WM_CANCELMODE";
|
||||
case 32: return "WM_SETCURSOR";
|
||||
case 33: return "WM_MOUSEACTIVATE";
|
||||
case 34: return "WM_CHILDACTIVATE";
|
||||
case 35: return "WM_QUEUESYNC";
|
||||
case 36: return "WM_GETMINMAXINFO";
|
||||
case 38: return "WM_PAINTICON";
|
||||
case 39: return "WM_ICONERASEBKGND";
|
||||
case 40: return "WM_NEXTDLGCTL";
|
||||
case 42: return "WM_SPOOLERSTATUS";
|
||||
case 43: return "WM_DRAWITEM";
|
||||
case 44: return "WM_MEASUREITEM";
|
||||
case 45: return "WM_DELETEITEM";
|
||||
case 46: return "WM_VKEYTOITEM";
|
||||
case 47: return "WM_CHARTOITEM";
|
||||
case 48: return "WM_SETFONT";
|
||||
case 49: return "WM_GETFONT";
|
||||
case 50: return "WM_SETHOTKEY";
|
||||
case 51: return "WM_GETHOTKEY";
|
||||
case 55: return "WM_QUERYDRAGICON";
|
||||
case 57: return "WM_COMPAREITEM";
|
||||
case 61: return "WM_GETOBJECT";
|
||||
case 65: return "WM_COMPACTING";
|
||||
case 68: return "WM_COMMNOTIFY";
|
||||
case 70: return "WM_WINDOWPOSCHANGING";
|
||||
case 71: return "WM_WINDOWPOSCHANGED";
|
||||
case 72: return "WM_POWER";
|
||||
case 73: return "WM_COPYGLOBALDATA";
|
||||
case 74: return "WM_COPYDATA";
|
||||
case 75: return "WM_CANCELJOURNAL";
|
||||
case 78: return "WM_NOTIFY";
|
||||
case 80: return "WM_INPUTLANGCHANGEREQUEST";
|
||||
case 81: return "WM_INPUTLANGCHANGE";
|
||||
case 82: return "WM_TCARD";
|
||||
case 83: return "WM_HELP";
|
||||
case 84: return "WM_USERCHANGED";
|
||||
case 85: return "WM_NOTIFYFORMAT";
|
||||
case 123: return "WM_CONTEXTMENU";
|
||||
case 124: return "WM_STYLECHANGING";
|
||||
case 125: return "WM_STYLECHANGED";
|
||||
case 126: return "WM_DISPLAYCHANGE";
|
||||
case 127: return "WM_GETICON";
|
||||
case 128: return "WM_SETICON";
|
||||
case 129: return "WM_NCCREATE";
|
||||
case 130: return "WM_NCDESTROY";
|
||||
case 131: return "WM_NCCALCSIZE";
|
||||
case 132: return "WM_NCHITTEST";
|
||||
case 133: return "WM_NCPAINT";
|
||||
case 134: return "WM_NCACTIVATE";
|
||||
case 135: return "WM_GETDLGCODE";
|
||||
case 136: return "WM_SYNCPAINT";
|
||||
case 160: return "WM_NCMOUSEMOVE";
|
||||
case 161: return "WM_NCLBUTTONDOWN";
|
||||
case 162: return "WM_NCLBUTTONUP";
|
||||
case 163: return "WM_NCLBUTTONDBLCLK";
|
||||
case 164: return "WM_NCRBUTTONDOWN";
|
||||
case 165: return "WM_NCRBUTTONUP";
|
||||
case 166: return "WM_NCRBUTTONDBLCLK";
|
||||
case 167: return "WM_NCMBUTTONDOWN";
|
||||
case 168: return "WM_NCMBUTTONUP";
|
||||
case 169: return "WM_NCMBUTTONDBLCLK";
|
||||
case 171: return "WM_NCXBUTTONDOWN";
|
||||
case 172: return "WM_NCXBUTTONUP";
|
||||
case 173: return "WM_NCXBUTTONDBLCLK";
|
||||
case 176: return "EM_GETSEL";
|
||||
case 177: return "EM_SETSEL";
|
||||
case 178: return "EM_GETRECT";
|
||||
case 179: return "EM_SETRECT";
|
||||
case 180: return "EM_SETRECTNP";
|
||||
case 181: return "EM_SCROLL";
|
||||
case 182: return "EM_LINESCROLL";
|
||||
case 183: return "EM_SCROLLCARET";
|
||||
case 185: return "EM_GETMODIFY";
|
||||
case 187: return "EM_SETMODIFY";
|
||||
case 188: return "EM_GETLINECOUNT";
|
||||
case 189: return "EM_LINEINDEX";
|
||||
case 190: return "EM_SETHANDLE";
|
||||
case 191: return "EM_GETHANDLE";
|
||||
case 192: return "EM_GETTHUMB";
|
||||
case 193: return "EM_LINELENGTH";
|
||||
case 194: return "EM_REPLACESEL";
|
||||
case 195: return "EM_SETFONT";
|
||||
case 196: return "EM_GETLINE";
|
||||
case 197: return "EM_LIMITTEXT / EM_SETLIMITTEXT";
|
||||
case 198: return "EM_CANUNDO";
|
||||
case 199: return "EM_UNDO";
|
||||
case 200: return "EM_FMTLINES";
|
||||
case 201: return "EM_LINEFROMCHAR";
|
||||
case 202: return "EM_SETWORDBREAK";
|
||||
case 203: return "EM_SETTABSTOPS";
|
||||
case 204: return "EM_SETPASSWORDCHAR";
|
||||
case 205: return "EM_EMPTYUNDOBUFFER";
|
||||
case 206: return "EM_GETFIRSTVISIBLELINE";
|
||||
case 207: return "EM_SETREADONLY";
|
||||
case 209: return "EM_SETWORDBREAKPROC / EM_GETWORDBREAKPROC";
|
||||
case 210: return "EM_GETPASSWORDCHAR";
|
||||
case 211: return "EM_SETMARGINS";
|
||||
case 212: return "EM_GETMARGINS";
|
||||
case 213: return "EM_GETLIMITTEXT";
|
||||
case 214: return "EM_POSFROMCHAR";
|
||||
case 215: return "EM_CHARFROMPOS";
|
||||
case 216: return "EM_SETIMESTATUS";
|
||||
case 217: return "EM_GETIMESTATUS";
|
||||
case 224: return "SBM_SETPOS";
|
||||
case 225: return "SBM_GETPOS";
|
||||
case 226: return "SBM_SETRANGE";
|
||||
case 227: return "SBM_GETRANGE";
|
||||
case 228: return "SBM_ENABLE_ARROWS";
|
||||
case 230: return "SBM_SETRANGEREDRAW";
|
||||
case 233: return "SBM_SETSCROLLINFO";
|
||||
case 234: return "SBM_GETSCROLLINFO";
|
||||
case 235: return "SBM_GETSCROLLBARINFO";
|
||||
case 240: return "BM_GETCHECK";
|
||||
case 241: return "BM_SETCHECK";
|
||||
case 242: return "BM_GETSTATE";
|
||||
case 243: return "BM_SETSTATE";
|
||||
case 244: return "BM_SETSTYLE";
|
||||
case 245: return "BM_CLICK";
|
||||
case 246: return "BM_GETIMAGE";
|
||||
case 247: return "BM_SETIMAGE";
|
||||
case 248: return "BM_SETDONTCLICK";
|
||||
case 255: return "WM_INPUT";
|
||||
case 256: return "WM_KEYDOWN";
|
||||
case 257: return "WM_KEYUP";
|
||||
case 258: return "WM_CHAR";
|
||||
case 259: return "WM_DEADCHAR";
|
||||
case 260: return "WM_SYSKEYDOWN";
|
||||
case 261: return "WM_SYSKEYUP";
|
||||
case 262: return "WM_SYSCHAR";
|
||||
case 263: return "WM_SYSDEADCHAR";
|
||||
case 265: return "WM_UNICHAR / WM_WNT_CONVERTREQUESTEX";
|
||||
case 266: return "WM_CONVERTREQUEST";
|
||||
case 267: return "WM_CONVERTRESULT";
|
||||
case 268: return "WM_INTERIM";
|
||||
case 269: return "WM_IME_STARTCOMPOSITION";
|
||||
case 270: return "WM_IME_ENDCOMPOSITION";
|
||||
case 272: return "WM_INITDIALOG";
|
||||
case 273: return "WM_COMMAND";
|
||||
case 274: return "WM_SYSCOMMAND";
|
||||
case 275: return "WM_TIMER";
|
||||
case 276: return "WM_HSCROLL";
|
||||
case 277: return "WM_VSCROLL";
|
||||
case 278: return "WM_INITMENU";
|
||||
case 279: return "WM_INITMENUPOPUP";
|
||||
case 280: return "WM_SYSTIMER";
|
||||
case 287: return "WM_MENUSELECT";
|
||||
case 288: return "WM_MENUCHAR";
|
||||
case 289: return "WM_ENTERIDLE";
|
||||
case 290: return "WM_MENURBUTTONUP";
|
||||
case 291: return "WM_MENUDRAG";
|
||||
case 292: return "WM_MENUGETOBJECT";
|
||||
case 293: return "WM_UNINITMENUPOPUP";
|
||||
case 294: return "WM_MENUCOMMAND";
|
||||
case 295: return "WM_CHANGEUISTATE";
|
||||
case 296: return "WM_UPDATEUISTATE";
|
||||
case 297: return "WM_QUERYUISTATE";
|
||||
case 306: return "WM_CTLCOLORMSGBOX";
|
||||
case 307: return "WM_CTLCOLOREDIT";
|
||||
case 308: return "WM_CTLCOLORLISTBOX";
|
||||
case 309: return "WM_CTLCOLORBTN";
|
||||
case 310: return "WM_CTLCOLORDLG";
|
||||
case 311: return "WM_CTLCOLORSCROLLBAR";
|
||||
case 312: return "WM_CTLCOLORSTATIC";
|
||||
case 512: return "WM_MOUSEMOVE";
|
||||
case 513: return "WM_LBUTTONDOWN";
|
||||
case 514: return "WM_LBUTTONUP";
|
||||
case 515: return "WM_LBUTTONDBLCLK";
|
||||
case 516: return "WM_RBUTTONDOWN";
|
||||
case 517: return "WM_RBUTTONUP";
|
||||
case 518: return "WM_RBUTTONDBLCLK";
|
||||
case 519: return "WM_MBUTTONDOWN";
|
||||
case 520: return "WM_MBUTTONUP";
|
||||
case 521: return "WM_MBUTTONDBLCLK";
|
||||
case 522: return "WM_MOUSEWHEEL";
|
||||
case 523: return "WM_XBUTTONDOWN";
|
||||
case 524: return "WM_XBUTTONUP";
|
||||
case 525: return "WM_XBUTTONDBLCLK";
|
||||
case 528: return "WM_PARENTNOTIFY";
|
||||
case 529: return "WM_ENTERMENULOOP";
|
||||
case 530: return "WM_EXITMENULOOP";
|
||||
case 531: return "WM_NEXTMENU";
|
||||
case 532: return "WM_SIZING";
|
||||
case 533: return "WM_CAPTURECHANGED";
|
||||
case 534: return "WM_MOVING";
|
||||
case 536: return "WM_POWERBROADCAST";
|
||||
case 537: return "WM_DEVICECHANGE";
|
||||
case 544: return "WM_MDICREATE";
|
||||
case 545: return "WM_MDIDESTROY";
|
||||
case 546: return "WM_MDIACTIVATE";
|
||||
case 547: return "WM_MDIRESTORE";
|
||||
case 548: return "WM_MDINEXT";
|
||||
case 549: return "WM_MDIMAXIMIZE";
|
||||
case 550: return "WM_MDITILE";
|
||||
case 551: return "WM_MDICASCADE";
|
||||
case 552: return "WM_MDIICONARRANGE";
|
||||
case 553: return "WM_MDIGETACTIVE";
|
||||
case 560: return "WM_MDISETMENU";
|
||||
case 561: return "WM_ENTERSIZEMOVE";
|
||||
case 562: return "WM_EXITSIZEMOVE";
|
||||
case 563: return "WM_DROPFILES";
|
||||
case 564: return "WM_MDIREFRESHMENU";
|
||||
case 640: return "WM_IME_REPORT";
|
||||
case 641: return "WM_IME_SETCONTEXT";
|
||||
case 642: return "WM_IME_NOTIFY";
|
||||
case 643: return "WM_IME_CONTROL";
|
||||
case 644: return "WM_IME_COMPOSITIONFULL";
|
||||
case 645: return "WM_IME_SELECT";
|
||||
case 646: return "WM_IME_CHAR";
|
||||
case 648: return "WM_IME_REQUEST";
|
||||
case 656: return "WM_IME_KEYDOWN";
|
||||
case 657: return "WM_IME_KEYUP";
|
||||
case 672: return "WM_NCMOUSEHOVER";
|
||||
case 673: return "WM_MOUSEHOVER";
|
||||
case 674: return "WM_NCMOUSELEAVE";
|
||||
case 675: return "WM_MOUSELEAVE";
|
||||
case 768: return "WM_CUT";
|
||||
case 769: return "WM_COPY";
|
||||
case 770: return "WM_PASTE";
|
||||
case 771: return "WM_CLEAR";
|
||||
case 772: return "WM_UNDO";
|
||||
case 773: return "WM_RENDERFORMAT";
|
||||
case 774: return "WM_RENDERALLFORMATS";
|
||||
case 775: return "WM_DESTROYCLIPBOARD";
|
||||
case 776: return "WM_DRAWCLIPBOARD";
|
||||
case 777: return "WM_PAINTCLIPBOARD";
|
||||
case 778: return "WM_VSCROLLCLIPBOARD";
|
||||
case 779: return "WM_SIZECLIPBOARD";
|
||||
case 780: return "WM_ASKCBFORMATNAME";
|
||||
case 781: return "WM_CHANGECBCHAIN";
|
||||
case 782: return "WM_HSCROLLCLIPBOARD";
|
||||
case 783: return "WM_QUERYNEWPALETTE";
|
||||
case 784: return "WM_PALETTEISCHANGING";
|
||||
case 785: return "WM_PALETTECHANGED";
|
||||
case 786: return "WM_HOTKEY";
|
||||
case 791: return "WM_PRINT";
|
||||
case 792: return "WM_PRINTCLIENT";
|
||||
case 793: return "WM_APPCOMMAND";
|
||||
case 856: return "WM_HANDHELDFIRST";
|
||||
case 863: return "WM_HANDHELDLAST";
|
||||
case 864: return "WM_AFXFIRST";
|
||||
case 895: return "WM_AFXLAST";
|
||||
case 896: return "WM_PENWINFIRST";
|
||||
case 897: return "WM_RCRESULT";
|
||||
case 898: return "WM_HOOKRCRESULT";
|
||||
case 899: return "WM_GLOBALRCCHANGE / WM_PENMISCINFO";
|
||||
case 900: return "WM_SKB";
|
||||
case 901: return "WM_HEDITCTL / WM_PENCTL";
|
||||
case 902: return "WM_PENMISC";
|
||||
case 903: return "WM_CTLINIT";
|
||||
case 904: return "WM_PENEVENT";
|
||||
case 911: return "WM_PENWINLAST";
|
||||
default:
|
||||
return "unknown WM_ message";
|
||||
}
|
||||
|
||||
return "unknown WM_ message";
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
AbstractFloatingWidget::~AbstractFloatingWidget() = default;
|
||||
|
||||
static unsigned int zOrderCounter = 0;
|
||||
@@ -74,8 +377,9 @@ namespace ADS
|
||||
DockContainerWidget *m_dropContainer = nullptr;
|
||||
DockAreaWidget *m_singleDockArea = nullptr;
|
||||
QPoint m_dragStartPos;
|
||||
QWidget *m_mouseEventHandler = nullptr;
|
||||
FloatingWidgetTitleBar *m_titleBar = nullptr;
|
||||
bool m_hiding = false;
|
||||
QWidget *m_mouseEventHandler = nullptr; // linux only
|
||||
FloatingWidgetTitleBar *m_titleBar = nullptr; // linux only
|
||||
|
||||
/**
|
||||
* Private data constructor
|
||||
@@ -90,7 +394,7 @@ namespace ADS
|
||||
*/
|
||||
static bool testConfigFlag(DockManager::eConfigFlag flag)
|
||||
{
|
||||
return DockManager::configFlags().testFlag(flag);
|
||||
return DockManager::testConfigFlag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,11 +450,11 @@ namespace ADS
|
||||
|
||||
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())
|
||||
overlay = m_dockManager->dockAreaOverlay();
|
||||
|
||||
// Resize the floating widget to the size of the highlighted drop area rectangle
|
||||
QRect rect = overlay->dropOverlayRect();
|
||||
int frameWidth = (q->frameSize().width() - q->rect().width()) / 2;
|
||||
int titleBarHeight = q->frameSize().height() - q->rect().height() - frameWidth;
|
||||
@@ -246,7 +550,7 @@ namespace ADS
|
||||
this,
|
||||
&FloatingDockContainer::onDockAreasAddedOrRemoved);
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#ifdef Q_OS_LINUX
|
||||
d->m_titleBar = new FloatingWidgetTitleBar(this);
|
||||
setWindowFlags(windowFlags() | Qt::Tool);
|
||||
QDockWidget::setWidget(d->m_dockContainer);
|
||||
@@ -257,14 +561,14 @@ namespace ADS
|
||||
&FloatingWidgetTitleBar::closeRequested,
|
||||
this,
|
||||
&FloatingDockContainer::close);
|
||||
#else
|
||||
#else
|
||||
setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
|
||||
QBoxLayout *boxLayout = new QBoxLayout(QBoxLayout::TopToBottom);
|
||||
boxLayout->setContentsMargins(0, 0, 0, 0);
|
||||
boxLayout->setSpacing(0);
|
||||
setLayout(boxLayout);
|
||||
boxLayout->addWidget(d->m_dockContainer);
|
||||
#endif
|
||||
#endif
|
||||
dockManager->registerFloatingWidget(this);
|
||||
}
|
||||
|
||||
@@ -272,24 +576,26 @@ namespace ADS
|
||||
: FloatingDockContainer(dockArea->dockManager())
|
||||
{
|
||||
d->m_dockContainer->addDockArea(dockArea);
|
||||
if (Utils::HostOsInfo::isLinuxHost())
|
||||
#ifdef Q_OS_LINUX
|
||||
d->m_titleBar->enableCloseButton(isClosable());
|
||||
|
||||
auto dw = topLevelDockWidget();
|
||||
if (dw)
|
||||
#endif
|
||||
if (auto dw = topLevelDockWidget())
|
||||
dw->emitTopLevelChanged(true);
|
||||
|
||||
d->m_dockManager->notifyWidgetOrAreaRelocation(dockArea);
|
||||
}
|
||||
|
||||
FloatingDockContainer::FloatingDockContainer(DockWidget *dockWidget)
|
||||
: FloatingDockContainer(dockWidget->dockManager())
|
||||
{
|
||||
d->m_dockContainer->addDockWidget(CenterDockWidgetArea, dockWidget);
|
||||
if (Utils::HostOsInfo::isLinuxHost())
|
||||
#ifdef Q_OS_LINUX
|
||||
d->m_titleBar->enableCloseButton(isClosable());
|
||||
|
||||
auto dw = topLevelDockWidget();
|
||||
if (dw)
|
||||
#endif
|
||||
if (auto dw = topLevelDockWidget())
|
||||
dw->emitTopLevelChanged(true);
|
||||
|
||||
d->m_dockManager->notifyWidgetOrAreaRelocation(dockWidget);
|
||||
}
|
||||
|
||||
FloatingDockContainer::~FloatingDockContainer()
|
||||
@@ -313,33 +619,56 @@ namespace ADS
|
||||
}
|
||||
}
|
||||
|
||||
void FloatingDockContainer::moveEvent(QMoveEvent *event)
|
||||
#ifdef Q_OS_WIN
|
||||
bool FloatingDockContainer::nativeEvent(const QByteArray &eventType, void *message, long *result)
|
||||
{
|
||||
QWidget::nativeEvent(eventType, message, result);
|
||||
MSG *msg = static_cast<MSG *>(message);
|
||||
switch (msg->message)
|
||||
{
|
||||
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);
|
||||
case WM_MOVING:
|
||||
{
|
||||
if (d->isState(DraggingFloatingWidget))
|
||||
d->updateDropOverlays(QCursor::pos());
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_NCLBUTTONDOWN:
|
||||
if (msg->wParam == HTCAPTION && d->isState(DraggingInactive))
|
||||
{
|
||||
qCInfo(adsLog) << Q_FUNC_INFO << "WM_NCLBUTTONDOWN" << eventType;
|
||||
d->m_dragStartPos = pos();
|
||||
d->setState(DraggingMousePressed);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_NCLBUTTONDBLCLK:
|
||||
d->setState(DraggingInactive);
|
||||
break;
|
||||
|
||||
case WM_ENTERSIZEMOVE:
|
||||
if (d->isState(DraggingMousePressed))
|
||||
{
|
||||
qCInfo(adsLog) << Q_FUNC_INFO << "WM_ENTERSIZEMOVE" << eventType;
|
||||
d->setState(DraggingFloatingWidget);
|
||||
d->updateDropOverlays(QCursor::pos());
|
||||
}
|
||||
break;
|
||||
|
||||
case DraggingFloatingWidget:
|
||||
d->updateDropOverlays(QCursor::pos());
|
||||
if (Utils::HostOsInfo::isMacHost()) {
|
||||
// In macOS when hiding the DockAreaOverlay the application would set
|
||||
// the main window as the active window for some reason. This fixes
|
||||
// that by resetting the active window to the floating widget after
|
||||
// updating the overlays.
|
||||
QApplication::setActiveWindow(this);
|
||||
case WM_EXITSIZEMOVE:
|
||||
if (d->isState(DraggingFloatingWidget))
|
||||
{
|
||||
qCInfo(adsLog) << Q_FUNC_INFO << "WM_EXITSIZEMOVE" << eventType;
|
||||
if (GetAsyncKeyState(VK_ESCAPE) & 0x8000)
|
||||
d->handleEscapeKey();
|
||||
else
|
||||
d->titleMouseReleaseEvent();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void FloatingDockContainer::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
@@ -368,112 +697,21 @@ namespace ADS
|
||||
if (d->m_dockManager->isRestoringState())
|
||||
return;
|
||||
|
||||
d->m_hiding = true;
|
||||
for (auto dockArea : d->m_dockContainer->openedDockAreas()) {
|
||||
for (auto dockWidget : dockArea->openedDockWidgets())
|
||||
dockWidget->toggleView(false);
|
||||
}
|
||||
d->m_hiding = false;
|
||||
}
|
||||
|
||||
void FloatingDockContainer::showEvent(QShowEvent *event) { Super::showEvent(event); }
|
||||
|
||||
bool FloatingDockContainer::event(QEvent *event)
|
||||
void FloatingDockContainer::showEvent(QShowEvent *event)
|
||||
{
|
||||
switch (d->m_draggingState) {
|
||||
case DraggingInactive: {
|
||||
// Normally we would check here, if the left mouse button is pressed.
|
||||
// But from QT version 5.12.2 on the mouse events from
|
||||
// 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)*/)
|
||||
#else
|
||||
if (event->type() == QEvent::NonClientAreaMouseButtonPress
|
||||
&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton))
|
||||
#endif
|
||||
{
|
||||
qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::NonClientAreaMouseButtonPress"
|
||||
<< event->type();
|
||||
d->m_dragStartPos = pos();
|
||||
d->setState(DraggingMousePressed);
|
||||
}
|
||||
} break;
|
||||
|
||||
case DraggingMousePressed:
|
||||
switch (event->type()) {
|
||||
case QEvent::NonClientAreaMouseButtonDblClick:
|
||||
qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::NonClientAreaMouseButtonDblClick";
|
||||
d->setState(DraggingInactive);
|
||||
break;
|
||||
|
||||
case QEvent::Resize:
|
||||
// If the first event after the mouse press is a resize event, then
|
||||
// the user resizes the window instead of dragging it around.
|
||||
// But there is one exception. If the window is maximized,
|
||||
// then dragging the window via title bar will cause the widget to
|
||||
// leave the maximized state. This in turn will trigger a resize event.
|
||||
// To know, if the resize event was triggered by user via moving a
|
||||
// corner of the window frame or if it was caused by a windows state
|
||||
// change, we check, if we are not in maximized state.
|
||||
if (!isMaximized()) {
|
||||
d->setState(DraggingInactive);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case DraggingFloatingWidget:
|
||||
if (event->type() == QEvent::NonClientAreaMouseButtonRelease) {
|
||||
qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::NonClientAreaMouseButtonRelease";
|
||||
d->titleMouseReleaseEvent();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if (ADS_DEBUG_LEVEL > 0)
|
||||
qDebug() << "FloatingDockContainer::event " << event->type();
|
||||
#endif
|
||||
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;
|
||||
Super::showEvent(event);
|
||||
#ifdef Q_OS_LINUX
|
||||
if (DockManager::testConfigFlag(DockManager::FocusHighlighting))
|
||||
window()->activateWindow();
|
||||
#endif
|
||||
}
|
||||
|
||||
void FloatingDockContainer::startFloating(const QPoint &dragStartMousePos,
|
||||
@@ -481,29 +719,52 @@ namespace ADS
|
||||
eDragState dragState,
|
||||
QWidget *mouseEventHandler)
|
||||
{
|
||||
#ifndef Q_OS_LINUX
|
||||
Q_UNUSED(mouseEventHandler)
|
||||
#endif
|
||||
resize(size);
|
||||
d->setState(dragState);
|
||||
d->m_dragStartMousePosition = dragStartMousePos;
|
||||
|
||||
if (Utils::HostOsInfo::isLinuxHost()) {
|
||||
#ifdef Q_OS_LINUX
|
||||
if (DraggingFloatingWidget == dragState) {
|
||||
setAttribute(Qt::WA_X11NetWmWindowTypeDock, true);
|
||||
d->m_mouseEventHandler = mouseEventHandler;
|
||||
if (d->m_mouseEventHandler) {
|
||||
if (d->m_mouseEventHandler)
|
||||
d->m_mouseEventHandler->grabMouse();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
moveFloating();
|
||||
show();
|
||||
}
|
||||
|
||||
void FloatingDockContainer::moveFloating()
|
||||
{
|
||||
int borderSize = (frameSize().width() - size().width()) / 2;
|
||||
const int borderSize = (frameSize().width() - size().width()) / 2;
|
||||
const QPoint moveToPos = QCursor::pos() - d->m_dragStartMousePosition
|
||||
- QPoint(borderSize, 0);
|
||||
move(moveToPos);
|
||||
|
||||
switch (d->m_draggingState)
|
||||
{
|
||||
case DraggingMousePressed:
|
||||
d->setState(DraggingFloatingWidget);
|
||||
d->updateDropOverlays(QCursor::pos());
|
||||
break;
|
||||
|
||||
case DraggingFloatingWidget:
|
||||
d->updateDropOverlays(QCursor::pos());
|
||||
// On macOS when hiding the DockAreaOverlay the application would set
|
||||
// the main window as the active window for some reason. This fixes
|
||||
// that by resetting the active window to the floating widget after
|
||||
// updating the overlays.
|
||||
if (Utils::HostOsInfo::isMacHost())
|
||||
QApplication::setActiveWindow(this);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool FloatingDockContainer::isClosable() const
|
||||
@@ -538,9 +799,13 @@ namespace ADS
|
||||
|
||||
void FloatingDockContainer::updateWindowTitle()
|
||||
{
|
||||
auto topLevelDockArea = d->m_dockContainer->topLevelDockArea();
|
||||
if (topLevelDockArea) {
|
||||
DockWidget *currentWidget = topLevelDockArea->currentDockWidget();
|
||||
// If this floating container will be hidden, then updating the window
|
||||
// title is not required anymore
|
||||
if (d->m_hiding)
|
||||
return;
|
||||
|
||||
if (auto topLevelDockArea = d->m_dockContainer->topLevelDockArea()) {
|
||||
if (DockWidget *currentWidget = topLevelDockArea->currentDockWidget())
|
||||
d->reflectCurrentWidget(currentWidget);
|
||||
} else {
|
||||
d->setWindowTitle(QApplication::applicationDisplayName());
|
||||
@@ -557,9 +822,8 @@ namespace ADS
|
||||
|
||||
bool FloatingDockContainer::restoreState(DockingStateReader &stream, bool testing)
|
||||
{
|
||||
if (!d->m_dockContainer->restoreState(stream, testing)) {
|
||||
if (!d->m_dockContainer->restoreState(stream, testing))
|
||||
return false;
|
||||
}
|
||||
|
||||
onDockAreasAddedOrRemoved();
|
||||
return true;
|
||||
@@ -584,7 +848,7 @@ namespace ADS
|
||||
{
|
||||
qCInfo(adsLog) << Q_FUNC_INFO;
|
||||
|
||||
if (Utils::HostOsInfo::isLinuxHost()) {
|
||||
#ifdef Q_OS_LINUX
|
||||
setAttribute(Qt::WA_X11NetWmWindowTypeDock, false);
|
||||
setWindowOpacity(1);
|
||||
activateWindow();
|
||||
@@ -592,8 +856,105 @@ namespace ADS
|
||||
d->m_mouseEventHandler->releaseMouse();
|
||||
d->m_mouseEventHandler = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
d->titleMouseReleaseEvent();
|
||||
}
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
bool FloatingDockContainer::event(QEvent *event)
|
||||
{
|
||||
switch (d->m_draggingState)
|
||||
{
|
||||
case DraggingInactive:
|
||||
{
|
||||
// Normally we would check here, if the left mouse button is pressed.
|
||||
// But from QT version 5.12.2 on the mouse events from
|
||||
// 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)*/)
|
||||
#else
|
||||
if (event->type() == QEvent::NonClientAreaMouseButtonPress
|
||||
&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton))
|
||||
#endif
|
||||
{
|
||||
qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::NonClientAreaMouseButtonPress"
|
||||
<< event->type();
|
||||
d->m_dragStartPos = pos();
|
||||
d->setState(DraggingMousePressed);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DraggingMousePressed:
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::NonClientAreaMouseButtonDblClick:
|
||||
qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::NonClientAreaMouseButtonDblClick";
|
||||
d->setState(DraggingInactive);
|
||||
break;
|
||||
|
||||
case QEvent::Resize:
|
||||
// If the first event after the mouse press is a resize event, then
|
||||
// the user resizes the window instead of dragging it around.
|
||||
// But there is one exception. If the window is maximized,
|
||||
// then dragging the window via title bar will cause the widget to
|
||||
// leave the maximized state. This in turn will trigger a resize event.
|
||||
// To know, if the resize event was triggered by user via moving a
|
||||
// corner of the window frame or if it was caused by a windows state
|
||||
// change, we check, if we are not in maximized state.
|
||||
if (!isMaximized())
|
||||
d->setState(DraggingInactive);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case DraggingFloatingWidget:
|
||||
if (event->type() == QEvent::NonClientAreaMouseButtonRelease)
|
||||
{
|
||||
qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::NonClientAreaMouseButtonRelease";
|
||||
d->titleMouseReleaseEvent();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if (ADS_DEBUG_LEVEL > 0)
|
||||
qDebug() << Q_FUNC_INFO << event->type();
|
||||
#endif
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
void FloatingDockContainer::moveEvent(QMoveEvent *event)
|
||||
{
|
||||
QWidget::moveEvent(event);
|
||||
switch (d->m_draggingState)
|
||||
{
|
||||
case DraggingMousePressed:
|
||||
d->setState(DraggingFloatingWidget);
|
||||
d->updateDropOverlays(QCursor::pos());
|
||||
break;
|
||||
|
||||
case DraggingFloatingWidget:
|
||||
d->updateDropOverlays(QCursor::pos());
|
||||
// On macOS when hiding the DockAreaOverlay the application would set
|
||||
// the main window as the active window for some reason. This fixes
|
||||
// that by resetting the active window to the floating widget after
|
||||
// updating the overlays.
|
||||
QApplication::setActiveWindow(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // namespace ADS
|
||||
|
@@ -183,12 +183,21 @@ protected:
|
||||
|
||||
protected: // reimplements QWidget
|
||||
void changeEvent(QEvent *event) override;
|
||||
void moveEvent(QMoveEvent *event) override;
|
||||
bool event(QEvent *event) override;
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
void hideEvent(QHideEvent *event) override;
|
||||
void showEvent(QShowEvent *event) override;
|
||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
virtual bool event(QEvent *event) override;
|
||||
virtual void moveEvent(QMoveEvent *event) override;
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
/**
|
||||
* Native event filter for handling WM_MOVING messages on Windows
|
||||
*/
|
||||
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
|
||||
#endif
|
||||
|
||||
public:
|
||||
using Super = QWidget;
|
||||
|
@@ -62,7 +62,6 @@ namespace ADS
|
||||
FloatingDragPreview *q;
|
||||
QWidget *m_content = nullptr;
|
||||
DockAreaWidget *m_contentSourceArea = nullptr;
|
||||
DockContainerWidget *m_contenSourceContainer = nullptr;
|
||||
QPoint m_dragStartMousePosition;
|
||||
DockManager *m_dockManager = nullptr;
|
||||
DockContainerWidget *m_dropContainer = nullptr;
|
||||
@@ -93,6 +92,12 @@ namespace ADS
|
||||
m_dockManager->dockAreaOverlay()->hideOverlay();
|
||||
q->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the real floating widget in case the mouse is released outside
|
||||
* outside of any drop area
|
||||
*/
|
||||
void createFloatingWidget();
|
||||
}; // class FloatingDragPreviewPrivate
|
||||
|
||||
void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &globalPosition)
|
||||
@@ -106,7 +111,7 @@ namespace ADS
|
||||
if (!containerWidget->isVisible())
|
||||
continue;
|
||||
|
||||
QPoint mappedPosition = containerWidget->mapFromGlobal(globalPosition);
|
||||
const QPoint mappedPosition = containerWidget->mapFromGlobal(globalPosition);
|
||||
if (containerWidget->rect().contains(mappedPosition)) {
|
||||
if (!topContainer || containerWidget->isInFrontOf(topContainer))
|
||||
topContainer = containerWidget;
|
||||
@@ -122,18 +127,16 @@ namespace ADS
|
||||
if (!topContainer) {
|
||||
containerOverlay->hideOverlay();
|
||||
dockAreaOverlay->hideOverlay();
|
||||
if (DockManager::configFlags().testFlag(DockManager::DragPreviewIsDynamic))
|
||||
if (DockManager::testConfigFlag(DockManager::DragPreviewIsDynamic))
|
||||
setHidden(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int visibleDockAreas = topContainer->visibleDockAreaCount();
|
||||
const int visibleDockAreas = topContainer->visibleDockAreaCount();
|
||||
containerOverlay->setAllowedAreas(visibleDockAreas > 1 ? OuterDockAreas : AllDockAreas);
|
||||
DockWidgetArea containerArea = containerOverlay->showOverlay(topContainer);
|
||||
containerOverlay->enableDropPreview(containerArea != InvalidDockWidgetArea);
|
||||
auto dockArea = topContainer->dockAreaAt(globalPosition);
|
||||
if (dockArea && dockArea->isVisible() && visibleDockAreas > 0
|
||||
if (dockArea && dockArea->isVisible() && visibleDockAreas >= 0
|
||||
&& dockArea != m_contentSourceArea) {
|
||||
dockAreaOverlay->enableDropPreview(true);
|
||||
dockAreaOverlay->setAllowedAreas((visibleDockAreas == 1) ? NoDockWidgetArea
|
||||
@@ -143,25 +146,28 @@ namespace ADS
|
||||
// A CenterDockWidgetArea for the dockAreaOverlay() indicates that the mouse is in the
|
||||
// title bar. If the ContainerArea is valid then we ignore the dock area of the
|
||||
// dockAreaOverlay() and disable the drop preview
|
||||
if ((area == CenterDockWidgetArea) && (containerArea != InvalidDockWidgetArea)) {
|
||||
if ((area == CenterDockWidgetArea) && (containerDropArea != InvalidDockWidgetArea)) {
|
||||
dockAreaOverlay->enableDropPreview(false);
|
||||
containerOverlay->enableDropPreview(true);
|
||||
} else {
|
||||
containerOverlay->enableDropPreview(InvalidDockWidgetArea == area);
|
||||
}
|
||||
containerOverlay->showOverlay(topContainer);
|
||||
} else {
|
||||
dockAreaOverlay->hideOverlay();
|
||||
// If there is only one single visible dock area in a container, then
|
||||
// it does not make sense to show a dock overlay because the dock area
|
||||
// would be removed and inserted at the same position
|
||||
if (visibleDockAreas <= 1)
|
||||
containerOverlay->hide();
|
||||
containerOverlay->hideOverlay();
|
||||
else
|
||||
containerOverlay->showOverlay(topContainer);
|
||||
|
||||
if (dockArea == m_contentSourceArea && InvalidDockWidgetArea == containerDropArea)
|
||||
m_dropContainer = nullptr;
|
||||
}
|
||||
|
||||
if (DockManager::configFlags().testFlag(DockManager::DragPreviewIsDynamic)) {
|
||||
if (DockManager::testConfigFlag(DockManager::DragPreviewIsDynamic)) {
|
||||
setHidden(dockDropArea != InvalidDockWidgetArea
|
||||
|| containerDropArea != InvalidDockWidgetArea);
|
||||
}
|
||||
@@ -171,13 +177,38 @@ namespace ADS
|
||||
: q(parent)
|
||||
{}
|
||||
|
||||
void FloatingDragPreviewPrivate::createFloatingWidget()
|
||||
{
|
||||
DockWidget *dockWidget = qobject_cast<DockWidget *>(m_content);
|
||||
DockAreaWidget *dockArea = qobject_cast<DockAreaWidget *>(m_content);
|
||||
|
||||
FloatingDockContainer *floatingWidget = nullptr;
|
||||
|
||||
if (dockWidget && dockWidget->features().testFlag(DockWidget::DockWidgetFloatable))
|
||||
floatingWidget = new FloatingDockContainer(dockWidget);
|
||||
else if (dockArea && dockArea->features().testFlag(DockWidget::DockWidgetFloatable))
|
||||
floatingWidget = new FloatingDockContainer(dockArea);
|
||||
|
||||
if (floatingWidget) {
|
||||
floatingWidget->setGeometry(q->geometry());
|
||||
floatingWidget->show();
|
||||
if (!DockManager::testConfigFlag(DockManager::DragPreviewHasWindowFrame)) {
|
||||
QApplication::processEvents();
|
||||
int frameHeight = floatingWidget->frameGeometry().height() - floatingWidget->geometry().height();
|
||||
QRect fixedGeometry = q->geometry();
|
||||
fixedGeometry.adjust(0, frameHeight, 0, 0);
|
||||
floatingWidget->setGeometry(fixedGeometry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FloatingDragPreview::FloatingDragPreview(QWidget *content, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, d(new FloatingDragPreviewPrivate(this))
|
||||
{
|
||||
d->m_content = content;
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
if (DockManager::configFlags().testFlag(DockManager::DragPreviewHasWindowFrame)) {
|
||||
if (DockManager::testConfigFlag(DockManager::DragPreviewHasWindowFrame)) {
|
||||
setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
|
||||
} else {
|
||||
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
|
||||
@@ -195,7 +226,7 @@ namespace ADS
|
||||
|
||||
// Create a static image of the widget that should get undocked
|
||||
// This is like some kind preview image like it is uses in drag and drop operations
|
||||
if (DockManager::configFlags().testFlag(DockManager::DragPreviewShowsContentPixmap)) {
|
||||
if (DockManager::testConfigFlag(DockManager::DragPreviewShowsContentPixmap)) {
|
||||
d->m_contentPreviewPixmap = QPixmap(content->size());
|
||||
content->render(&d->m_contentPreviewPixmap);
|
||||
}
|
||||
@@ -213,10 +244,9 @@ namespace ADS
|
||||
content->dockManager()) // TODO static_cast?
|
||||
{
|
||||
d->m_dockManager = content->dockManager();
|
||||
if (content->dockAreaWidget()->openDockWidgetsCount() == 1) {
|
||||
if (content->dockAreaWidget()->openDockWidgetsCount() == 1)
|
||||
d->m_contentSourceArea = content->dockAreaWidget();
|
||||
d->m_contenSourceContainer = content->dockContainer();
|
||||
}
|
||||
|
||||
setWindowTitle(content->windowTitle());
|
||||
}
|
||||
|
||||
@@ -226,7 +256,6 @@ namespace ADS
|
||||
{
|
||||
d->m_dockManager = content->dockManager();
|
||||
d->m_contentSourceArea = content;
|
||||
d->m_contenSourceContainer = content->dockContainer();
|
||||
setWindowTitle(content->currentDockWidget()->windowTitle());
|
||||
}
|
||||
|
||||
@@ -234,10 +263,11 @@ namespace ADS
|
||||
|
||||
void FloatingDragPreview::moveFloating()
|
||||
{
|
||||
int borderSize = (frameSize().width() - size().width()) / 2;
|
||||
const int borderSize = (frameSize().width() - size().width()) / 2;
|
||||
const QPoint moveToPos = QCursor::pos() - d->m_dragStartMousePosition
|
||||
- QPoint(borderSize, 0);
|
||||
move(moveToPos);
|
||||
d->updateDropOverlays(QCursor::pos());
|
||||
}
|
||||
|
||||
void FloatingDragPreview::startFloating(const QPoint &dragStartMousePos,
|
||||
@@ -253,46 +283,24 @@ namespace ADS
|
||||
show();
|
||||
}
|
||||
|
||||
void FloatingDragPreview::moveEvent(QMoveEvent *event)
|
||||
{
|
||||
QWidget::moveEvent(event);
|
||||
d->updateDropOverlays(QCursor::pos());
|
||||
}
|
||||
|
||||
void FloatingDragPreview::finishDragging()
|
||||
{
|
||||
qCInfo(adsLog) << Q_FUNC_INFO;
|
||||
auto dockDropArea = d->m_dockManager->dockAreaOverlay()->visibleDropAreaUnderCursor();
|
||||
auto containerDropArea = d->m_dockManager->containerOverlay()->visibleDropAreaUnderCursor();
|
||||
if (d->m_dropContainer && (dockDropArea != InvalidDockWidgetArea)) {
|
||||
d->m_dropContainer->dropWidget(d->m_content,
|
||||
dockDropArea,
|
||||
d->m_dropContainer->dockAreaAt(QCursor::pos()));
|
||||
} else if (d->m_dropContainer && (containerDropArea != InvalidDockWidgetArea)) {
|
||||
if (!d->m_dropContainer) {
|
||||
d->createFloatingWidget();
|
||||
} else if (dockDropArea != InvalidDockWidgetArea) {
|
||||
d->m_dropContainer->dropWidget(d->m_content, dockDropArea, d->m_dropContainer->dockAreaAt(QCursor::pos()));
|
||||
} else if (containerDropArea != InvalidDockWidgetArea) {
|
||||
// If there is only one single dock area, and we drop into the center
|
||||
// then we tabify the dropped widget into the only visible dock area
|
||||
if (d->m_dropContainer->visibleDockAreaCount() <= 1 && CenterDockWidgetArea == containerDropArea)
|
||||
d->m_dropContainer->dropWidget(d->m_content, containerDropArea, d->m_dropContainer->dockAreaAt(QCursor::pos()));
|
||||
else
|
||||
d->m_dropContainer->dropWidget(d->m_content, containerDropArea, nullptr);
|
||||
} else {
|
||||
DockWidget *dockWidget = qobject_cast<DockWidget *>(d->m_content);
|
||||
FloatingDockContainer *floatingWidget = nullptr;
|
||||
|
||||
if (dockWidget && dockWidget->features().testFlag(DockWidget::DockWidgetFloatable)) {
|
||||
floatingWidget = new FloatingDockContainer(dockWidget);
|
||||
} else {
|
||||
DockAreaWidget *dockArea = qobject_cast<DockAreaWidget *>(d->m_content);
|
||||
if (dockArea->features().testFlag(DockWidget::DockWidgetFloatable))
|
||||
floatingWidget = new FloatingDockContainer(dockArea);
|
||||
}
|
||||
|
||||
if (floatingWidget) {
|
||||
floatingWidget->setGeometry(this->geometry());
|
||||
floatingWidget->show();
|
||||
if (!DockManager::configFlags().testFlag(DockManager::DragPreviewHasWindowFrame)) {
|
||||
QApplication::processEvents();
|
||||
int frameHeight = floatingWidget->frameGeometry().height() - floatingWidget->geometry().height();
|
||||
QRect fixedGeometry = this->geometry();
|
||||
fixedGeometry.adjust(0, frameHeight, 0, 0);
|
||||
floatingWidget->setGeometry(fixedGeometry);
|
||||
}
|
||||
}
|
||||
d->createFloatingWidget();
|
||||
}
|
||||
|
||||
this->close();
|
||||
@@ -307,11 +315,11 @@ namespace ADS
|
||||
return;
|
||||
|
||||
QPainter painter(this);
|
||||
if (DockManager::configFlags().testFlag(DockManager::DragPreviewShowsContentPixmap))
|
||||
if (DockManager::testConfigFlag(DockManager::DragPreviewShowsContentPixmap))
|
||||
painter.drawPixmap(QPoint(0, 0), d->m_contentPreviewPixmap);
|
||||
|
||||
// If we do not have a window frame then we paint a QRubberBand like frameless window
|
||||
if (!DockManager::configFlags().testFlag(DockManager::DragPreviewHasWindowFrame)) {
|
||||
if (!DockManager::testConfigFlag(DockManager::DragPreviewHasWindowFrame)) {
|
||||
QColor color = palette().color(QPalette::Active, QPalette::Highlight);
|
||||
QPen pen = painter.pen();
|
||||
pen.setColor(color.darker(120));
|
||||
|
@@ -64,11 +64,6 @@ private:
|
||||
void onApplicationStateChanged(Qt::ApplicationState state);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Updates the drop overlays
|
||||
*/
|
||||
void moveEvent(QMoveEvent *event) override;
|
||||
|
||||
/**
|
||||
* Cares about painting the
|
||||
*/
|
||||
|
@@ -1,122 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 512 512"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="close-button-disabled.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"><metadata
|
||||
id="metadata897"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs895" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
id="namedview893"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="0.85862966"
|
||||
inkscape:cx="345.29142"
|
||||
inkscape:cy="32.731258"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Capa_1" />
|
||||
<g
|
||||
id="g860"
|
||||
transform="matrix(0.71708683,0,0,0.71708683,128,128)"
|
||||
style="stroke:none;stroke-opacity:1;fill:#000000;fill-opacity:0.50196081">
|
||||
<g
|
||||
id="close"
|
||||
style="stroke:none;stroke-opacity:1;fill:#000000;fill-opacity:0.50196081">
|
||||
<polygon
|
||||
points="357,321.3 214.2,178.5 357,35.7 321.3,0 178.5,142.8 35.7,0 0,35.7 142.8,178.5 0,321.3 35.7,357 178.5,214.2 321.3,357 "
|
||||
id="polygon857"
|
||||
style="stroke:none;stroke-opacity:1;fill:#000000;fill-opacity:0.50196081" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g862"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g864"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g866"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g868"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g870"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g872"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g874"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g876"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g878"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g880"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g882"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g884"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g886"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g888"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g890"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.9 KiB |
@@ -1,119 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 512 512"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="close-button.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"><metadata
|
||||
id="metadata897"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs895" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
id="namedview893"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="0.85862966"
|
||||
inkscape:cx="345.29142"
|
||||
inkscape:cy="32.731258"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Capa_1" />
|
||||
<g
|
||||
id="g860"
|
||||
transform="matrix(0.71708683,0,0,0.71708683,128,128)">
|
||||
<g
|
||||
id="close">
|
||||
<polygon
|
||||
points="357,321.3 214.2,178.5 357,35.7 321.3,0 178.5,142.8 35.7,0 0,35.7 142.8,178.5 0,321.3 35.7,357 178.5,214.2 321.3,357 "
|
||||
id="polygon857" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g862"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g864"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g866"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g868"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g870"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g872"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g874"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g876"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g878"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g880"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g882"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g884"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g886"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g888"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
<g
|
||||
id="g890"
|
||||
transform="translate(0,155)">
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.7 KiB |
@@ -41,7 +41,7 @@
|
||||
namespace ADS {
|
||||
|
||||
using TabLabelType = ElidingLabel;
|
||||
using CloseButtonType = QPushButton;
|
||||
using CloseButtonType = QToolButton;
|
||||
|
||||
/**
|
||||
* @brief Private data class of public interface CFloatingWidgetTitleBar
|
||||
@@ -76,7 +76,7 @@ void FloatingWidgetTitleBarPrivate::createLayout()
|
||||
|
||||
m_closeButton = new CloseButtonType();
|
||||
m_closeButton->setObjectName("floatingTitleCloseButton");
|
||||
m_closeButton->setFlat(true);
|
||||
m_closeButton->setAutoRaise(true);
|
||||
internal::setButtonIcon(m_closeButton,
|
||||
QStyle::SP_TitleBarCloseButton,
|
||||
ADS::FloatingWidgetCloseIcon);
|
||||
@@ -106,7 +106,7 @@ void FloatingWidgetTitleBarPrivate::createLayout()
|
||||
}
|
||||
|
||||
FloatingWidgetTitleBar::FloatingWidgetTitleBar(FloatingDockContainer *parent)
|
||||
: QWidget(parent)
|
||||
: QFrame(parent)
|
||||
, d(new FloatingWidgetTitleBarPrivate(this))
|
||||
{
|
||||
d->m_floatingWidget = parent;
|
||||
@@ -131,9 +131,9 @@ void FloatingWidgetTitleBar::mousePressEvent(QMouseEvent *event)
|
||||
void FloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
d->m_dragState = DraggingInactive;
|
||||
if (d->m_floatingWidget) {
|
||||
if (d->m_floatingWidget)
|
||||
d->m_floatingWidget->finishDragging();
|
||||
}
|
||||
|
||||
Super::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
@@ -164,4 +164,9 @@ void FloatingWidgetTitleBar::setTitle(const QString &text)
|
||||
d->m_titleLabel->setText(text);
|
||||
}
|
||||
|
||||
void FloatingWidgetTitleBar::updateStyle()
|
||||
{
|
||||
internal::repolishStyle(this, internal::RepolishDirectChildren);
|
||||
}
|
||||
|
||||
} // namespace ADS
|
||||
|
@@ -25,7 +25,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QFrame>
|
||||
|
||||
namespace ADS {
|
||||
|
||||
@@ -34,12 +34,12 @@ class FloatingWidgetTitleBarPrivate;
|
||||
|
||||
/**
|
||||
* Titlebar for floating widgets to capture non client are mouse events.
|
||||
* Linux does not support NonClieantArea mouse events like
|
||||
* Linux does not support NonClientArea mouse events like
|
||||
* QEvent::NonClientAreaMouseButtonPress. Because these events are required
|
||||
* for the docking system to work properly, we use our own titlebar here to
|
||||
* capture the required mouse events.
|
||||
*/
|
||||
class FloatingWidgetTitleBar : public QWidget
|
||||
class FloatingWidgetTitleBar : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
@@ -69,6 +69,11 @@ public:
|
||||
*/
|
||||
void setTitle(const QString &text);
|
||||
|
||||
/**
|
||||
* Update stylesheet style if a property changes
|
||||
*/
|
||||
void updateStyle();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* This signal is emitted, if the close button is clicked.
|
||||
|
@@ -1,6 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="/ads">
|
||||
<file>images/close-button.svg</file>
|
||||
<file>images/close-button-disabled.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
@@ -59,9 +59,15 @@ ADS--DockWidget
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
ADS--DockAreaTitleBar{ background-color: creatorTheme.BackgroundColorDark; }
|
||||
ADS--DockAreaTitleBar
|
||||
{
|
||||
background-color: creatorTheme.BackgroundColorDark;
|
||||
}
|
||||
|
||||
QWidget#tabsContainerWidget { background-color: creatorTheme.BackgroundColorDark; }
|
||||
QWidget#tabsContainerWidget
|
||||
{
|
||||
background-color: creatorTheme.BackgroundColorDark;
|
||||
}
|
||||
|
||||
ADS--TitleBarButton
|
||||
{
|
||||
@@ -126,3 +132,33 @@ QScrollBar::sub-page {
|
||||
height: 0px;
|
||||
width: 0px;
|
||||
}
|
||||
|
||||
/* Focus related styling */
|
||||
ADS--DockWidgetTab[focused="true"] {
|
||||
background: creatorTheme.DSinteraction;
|
||||
border-color: creatorTheme.DSinteraction;
|
||||
}
|
||||
|
||||
ADS--DockWidgetTab[focused="true"] > #tabCloseButton:hover {
|
||||
background: rgba(255, 255, 255, 48);
|
||||
}
|
||||
|
||||
ADS--DockWidgetTab[focused="true"] > #tabCloseButton:pressed {
|
||||
background: rgba(255, 255, 255, 92);
|
||||
}
|
||||
|
||||
ADS--DockWidgetTab[focused="true"] QLabel {
|
||||
color: palette(creatorTheme.QmlDesigner_TabDark);
|
||||
}
|
||||
|
||||
ADS--DockAreaTitleBar {
|
||||
background: transparent;
|
||||
border-bottom: 2px solid creatorTheme.QmlDesigner_TabLight;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
ADS--DockAreaWidget[focused="true"] ADS--DockAreaTitleBar {
|
||||
background: transparent;
|
||||
border-bottom: 2px solid creatorTheme.DSinteraction;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
@@ -228,8 +228,9 @@ void DesignModeWidget::setup()
|
||||
|
||||
auto settings = Core::ICore::settings(QSettings::UserScope);
|
||||
|
||||
ADS::DockManager::setConfigFlags(ADS::DockManager::DefaultNonOpaqueConfig);
|
||||
ADS::DockManager::setConfigFlag(ADS::DockManager::FocusHighlighting, true);
|
||||
m_dockManager = new ADS::DockManager(this);
|
||||
m_dockManager->setConfigFlags(ADS::DockManager::DefaultNonOpaqueConfig);
|
||||
m_dockManager->setSettings(settings);
|
||||
m_dockManager->setWorkspacePresetsPath(Core::ICore::resourcePath() + QLatin1String("/qmldesigner/workspacePresets/"));
|
||||
|
||||
|
Reference in New Issue
Block a user