diff --git a/doc/dyt修改.txt b/doc/dyt修改.txt index bbf75301..3780a144 100644 --- a/doc/dyt修改.txt +++ b/doc/dyt修改.txt @@ -24,7 +24,7 @@ 5.关联文件时候更改文件的按键不太明显。 解决方案 a、属性控件文件选择按钮不明显 (解决) - b、属性控件中间的分割线能左右移动 + b、属性控件中间的分割线能左右移动 (解决) 6.提供的轨迹文件是如何输入到dyt界面的,我们需要知道。 解决方案 diff --git a/src/translations/Dyt_zh_CN.ts b/src/translations/Dyt_zh_CN.ts index 8176b284..5450fc9e 100644 --- a/src/translations/Dyt_zh_CN.ts +++ b/src/translations/Dyt_zh_CN.ts @@ -857,31 +857,6 @@ the appliaction is crash - - - List all tabs - - - - - Detach Group - - - - - Close Active Tab - - - - - Close Group - - - - - Close Tab - - longitude: @@ -1816,50 +1791,6 @@ 保存空间目录 - - ads::CDockAreaTitleBar - - - Detach Area - - - - - Close Area - - - - - Close Other Areas - - - - - ads::CDockManager - - - Show View - - - - - ads::CDockWidgetTab - - - Detach - - - - - Close - - - - - Close Others - - - osgQOpenGLWidget diff --git a/src/ui/AdvDock/DockAreaTabBar.cpp b/src/ui/AdvDock/DockAreaTabBar.cpp deleted file mode 100644 index c2097aab..00000000 --- a/src/ui/AdvDock/DockAreaTabBar.cpp +++ /dev/null @@ -1,647 +0,0 @@ -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockAreaTabBar.cpp -/// \author Uwe Kindler -/// \date 24.08.2018 -/// \brief Implementation of CDockAreaTabBar class -//============================================================================ - -//============================================================================ -// INCLUDES -//============================================================================ -#include "FloatingDragPreview.h" -#include "DockAreaTabBar.h" - -#include -#include -#include -#include -#include - -#include "FloatingDockContainer.h" -#include "DockAreaWidget.h" -#include "DockOverlay.h" -#include "DockManager.h" -#include "DockWidget.h" -#include "DockWidgetTab.h" - -#include - - -namespace ads -{ -/** - * Private data class of CDockAreaTabBar class (pimpl) - */ -struct DockAreaTabBarPrivate -{ - CDockAreaTabBar* _this; - QPoint DragStartMousePos; - CDockAreaWidget* DockArea; - IFloatingWidget* FloatingWidget = nullptr; - QWidget* TabsContainerWidget; - QBoxLayout* TabsLayout; - int CurrentIndex = -1; - eDragState DragState = DraggingInactive; - - /** - * Private data constructor - */ - DockAreaTabBarPrivate(CDockAreaTabBar* _public); - - /** - * Update tabs after current index changed or when tabs are removed. - * The function reassigns the stylesheet to update the tabs - */ - void updateTabs(); - - /** - * Test function for current drag state - */ - bool isDraggingState(eDragState dragState) const - { - return this->DragState == dragState; - } -}; -// struct DockAreaTabBarPrivate - -//============================================================================ -DockAreaTabBarPrivate::DockAreaTabBarPrivate(CDockAreaTabBar* _public) : - _this(_public) -{ - -} - - -//============================================================================ -void DockAreaTabBarPrivate::updateTabs() -{ - // Set active TAB and update all other tabs to be inactive - for (int i = 0; i < _this->count(); ++i) - { - auto TabWidget = _this->tab(i); - if (!TabWidget) - { - continue; - } - - if (i == CurrentIndex) - { - TabWidget->show(); - TabWidget->setActiveTab(true); - _this->ensureWidgetVisible(TabWidget); - } - else - { - TabWidget->setActiveTab(false); - } - } -} - - -//============================================================================ -CDockAreaTabBar::CDockAreaTabBar(CDockAreaWidget* parent) : - QScrollArea(parent), - d(new DockAreaTabBarPrivate(this)) -{ - d->DockArea = parent; - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - setFrameStyle(QFrame::NoFrame); - setWidgetResizable(true); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - d->TabsContainerWidget = new QWidget(); - d->TabsContainerWidget->setObjectName("tabsContainerWidget"); - setWidget(d->TabsContainerWidget); - - d->TabsLayout = new QBoxLayout(QBoxLayout::LeftToRight); - d->TabsLayout->setContentsMargins(0, 0, 0, 0); - d->TabsLayout->setSpacing(0); - d->TabsLayout->addStretch(1); - d->TabsContainerWidget->setLayout(d->TabsLayout); -} - -//============================================================================ -CDockAreaTabBar::~CDockAreaTabBar() -{ - delete d; -} - - -//============================================================================ -void CDockAreaTabBar::wheelEvent(QWheelEvent* Event) -{ - Event->accept(); - const int direction = Event->angleDelta().y(); - if (direction < 0) - { - horizontalScrollBar()->setValue(horizontalScrollBar()->value() + 20); - } - else - { - horizontalScrollBar()->setValue(horizontalScrollBar()->value() - 20); - } -} - - -//============================================================================ -void CDockAreaTabBar::mousePressEvent(QMouseEvent* ev) -{ - if (ev->button() == Qt::LeftButton) - { - ev->accept(); - d->DragStartMousePos = ev->pos(); - d->DragState = DraggingMousePressed; - return; - } - Super::mousePressEvent(ev); -} - - -//============================================================================ -void CDockAreaTabBar::mouseReleaseEvent(QMouseEvent* ev) -{ - if (ev->button() == Qt::LeftButton) - { - ADS_PRINT("CDockAreaTabBar::mouseReleaseEvent"); - ev->accept(); - auto CurrentDragState = d->DragState; - d->DragStartMousePos = QPoint(); - d->DragState = DraggingInactive; - if (DraggingFloatingWidget == CurrentDragState) - { - d->FloatingWidget->finishDragging(); - } - return; - } - Super::mouseReleaseEvent(ev); -} - - -//============================================================================ -void CDockAreaTabBar::mouseMoveEvent(QMouseEvent* ev) -{ - Super::mouseMoveEvent(ev); - if (!(ev->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive)) - { - d->DragState = DraggingInactive; - return; - } - - // move floating window - if (d->isDraggingState(DraggingFloatingWidget)) - { - d->FloatingWidget->moveFloating(); - return; - } - - // If this is the last dock area in a dock container it does not make - // sense to move it to a new floating widget and leave this one - // empty - if (d->DockArea->dockContainer()->isFloating() - && d->DockArea->dockContainer()->visibleDockAreaCount() == 1) - { - return; - } - - // If one single dock widget in this area is not floatable then the whole - // area is not floatable - if (!d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable)) - { - return; - } - - int DragDistance = (d->DragStartMousePos - ev->pos()).manhattanLength(); - if (DragDistance >= CDockManager::startDragDistance()) - { - ADS_PRINT("CTabsScrollArea::startFloating"); - startFloating(d->DragStartMousePos); - auto Overlay = d->DockArea->dockManager()->containerOverlay(); - Overlay->setAllowedAreas(OuterDockAreas); - } - - return; -} - - -//============================================================================ -void CDockAreaTabBar::mouseDoubleClickEvent(QMouseEvent *event) -{ - // If this is the last dock area in a dock container it does not make - // sense to move it to a new floating widget and leave this one - // empty - if (d->DockArea->dockContainer()->isFloating() && d->DockArea->dockContainer()->dockAreaCount() == 1) - { - return; - } - - if (!d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable)) - { - return; - } - makeAreaFloating(event->pos(), DraggingInactive); -} - - -//============================================================================ -IFloatingWidget* CDockAreaTabBar::makeAreaFloating(const QPoint& Offset, eDragState DragState) -{ - QSize Size = d->DockArea->size(); - d->DragState = DragState; - bool OpaqueUndocking = CDockManager::configFlags().testFlag(CDockManager::OpaqueUndocking) || - (DraggingFloatingWidget != DragState); - CFloatingDockContainer* FloatingDockContainer = nullptr; - IFloatingWidget* FloatingWidget; - if (OpaqueUndocking) - { - FloatingWidget = FloatingDockContainer = new CFloatingDockContainer(d->DockArea); - } - else - { - auto w = new CFloatingDragPreview(d->DockArea); - connect(w, &CFloatingDragPreview::draggingCanceled, [=]() - { - d->DragState = DraggingInactive; - }); - FloatingWidget = w; - } - - FloatingWidget->startFloating(Offset, Size, DragState, nullptr); - if (FloatingDockContainer) - { - auto TopLevelDockWidget = FloatingDockContainer->topLevelDockWidget(); - if (TopLevelDockWidget) - { - TopLevelDockWidget->emitTopLevelChanged(true); - } - } - - return FloatingWidget; -} - - -//============================================================================ -void CDockAreaTabBar::startFloating(const QPoint& Offset) -{ - d->FloatingWidget = makeAreaFloating(Offset, DraggingFloatingWidget); -} - - -//============================================================================ -void CDockAreaTabBar::setCurrentIndex(int index) -{ - if (index == d->CurrentIndex) - { - return; - } - - if (index < -1 || index > (count() - 1)) - { - qWarning() << Q_FUNC_INFO << "Invalid index" << index; - return; - } - - emit currentChanging(index); - d->CurrentIndex = index; - d->updateTabs(); - emit currentChanged(index); -} - - -//============================================================================ -int CDockAreaTabBar::count() const -{ - // The tab bar contains a stretch item as last item - return d->TabsLayout->count() - 1; -} - - -//=========================================================================== -void CDockAreaTabBar::insertTab(int Index, CDockWidgetTab* Tab) -{ - d->TabsLayout->insertWidget(Index, Tab); - connect(Tab, SIGNAL(clicked()), this, SLOT(onTabClicked())); - connect(Tab, SIGNAL(closeRequested()), this, SLOT(onTabCloseRequested())); - connect(Tab, SIGNAL(closeOtherTabsRequested()), this, SLOT(onCloseOtherTabsRequested())); - connect(Tab, SIGNAL(moved(const QPoint&)), this, SLOT(onTabWidgetMoved(const QPoint&))); - Tab->installEventFilter(this); - emit tabInserted(Index); - if (Index <= d->CurrentIndex) - { - setCurrentIndex(d->CurrentIndex + 1); - } -} - - -//=========================================================================== -void CDockAreaTabBar::removeTab(CDockWidgetTab* Tab) -{ - if (!count()) - { - return; - } - ADS_PRINT("CDockAreaTabBar::removeTab "); - int NewCurrentIndex = currentIndex(); - int RemoveIndex = d->TabsLayout->indexOf(Tab); - if (count() == 1) - { - NewCurrentIndex = -1; - } - if (NewCurrentIndex > RemoveIndex) - { - NewCurrentIndex--; - } - else if (NewCurrentIndex == RemoveIndex) - { - NewCurrentIndex = -1; - // First we walk to the right to search for the next visible tab - for (int i = (RemoveIndex + 1); i < count(); ++i) - { - if (tab(i)->isVisibleTo(this)) - { - NewCurrentIndex = i - 1; - break; - } - } - - // If there is no visible tab right to this tab then we walk to - // the left to find a visible tab - if (NewCurrentIndex < 0) - { - for (int i = (RemoveIndex - 1); i >= 0; --i) - { - if (tab(i)->isVisibleTo(this)) - { - NewCurrentIndex = i; - break; - } - } - } - } - - emit removingTab(RemoveIndex); - d->TabsLayout->removeWidget(Tab); - Tab->disconnect(this); - Tab->removeEventFilter(this); - ADS_PRINT("NewCurrentIndex " << NewCurrentIndex); - if (NewCurrentIndex != d->CurrentIndex) - { - setCurrentIndex(NewCurrentIndex); - } - else - { - d->updateTabs(); - } -} - - -//=========================================================================== -int CDockAreaTabBar::currentIndex() const -{ - return d->CurrentIndex; -} - - -//=========================================================================== -CDockWidgetTab* CDockAreaTabBar::currentTab() const -{ - if (d->CurrentIndex < 0) - { - return nullptr; - } - else - { - return qobject_cast(d->TabsLayout->itemAt(d->CurrentIndex)->widget()); - } -} - - -//=========================================================================== -void CDockAreaTabBar::onTabClicked() -{ - CDockWidgetTab* Tab = qobject_cast(sender()); - if (!Tab) - { - return; - } - - int index = d->TabsLayout->indexOf(Tab); - if (index < 0) - { - return; - } - setCurrentIndex(index); - emit tabBarClicked(index); -} - - -//=========================================================================== -void CDockAreaTabBar::onTabCloseRequested() -{ - CDockWidgetTab* Tab = qobject_cast(sender()); - int Index = d->TabsLayout->indexOf(Tab); - closeTab(Index); -} - - -//=========================================================================== -void CDockAreaTabBar::onCloseOtherTabsRequested() -{ - auto Sender = qobject_cast(sender()); - for (int i = 0; i < count(); ++i) - { - auto Tab = tab(i); - if (Tab->isClosable() && !Tab->isHidden() && Tab != Sender) - { - // If the dock widget is deleted with the closeTab() call, its tab - // it will no longer be in the layout, and thus the index needs to - // be updated to not skip any tabs - int Offset = Tab->dockWidget()->features().testFlag( - CDockWidget::DockWidgetDeleteOnClose) ? 1 : 0; - closeTab(i); - - // 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 (Tab->dockWidget()->isClosed()) - { - i -= Offset; - } - } - } -} - - -//=========================================================================== -CDockWidgetTab* CDockAreaTabBar::tab(int Index) const -{ - if (Index >= count() || Index < 0) - { - return nullptr; - } - return qobject_cast(d->TabsLayout->itemAt(Index)->widget()); -} - - -//=========================================================================== -void CDockAreaTabBar::onTabWidgetMoved(const QPoint& GlobalPos) -{ - CDockWidgetTab* MovingTab = qobject_cast(sender()); - if (!MovingTab) - { - return; - } - - int fromIndex = d->TabsLayout->indexOf(MovingTab); - auto MousePos = mapFromGlobal(GlobalPos); - int toIndex = -1; - // Find tab under mouse - for (int i = 0; i < count(); ++i) - { - CDockWidgetTab* DropTab = tab(i); - if (DropTab == MovingTab || !DropTab->isVisibleTo(this) - || !DropTab->geometry().contains(MousePos)) - { - continue; - } - - toIndex = d->TabsLayout->indexOf(DropTab); - if (toIndex == fromIndex) - { - toIndex = -1; - continue; - } - - if (toIndex < 0) - { - toIndex = 0; - } - break; - } - - // Now check if the mouse is behind the last tab - if (toIndex < 0) - { - if (MousePos.x() > tab(count() - 1)->geometry().right()) - { - ADS_PRINT("after all tabs"); - toIndex = count() - 1; - } - else - { - toIndex = fromIndex; - } - } - - d->TabsLayout->removeWidget(MovingTab); - d->TabsLayout->insertWidget(toIndex, MovingTab); - if (toIndex >= 0) - { - ADS_PRINT("tabMoved from " << fromIndex << " to " << toIndex); - emit tabMoved(fromIndex, toIndex); - setCurrentIndex(toIndex); - } -} - - -//=========================================================================== -void CDockAreaTabBar::closeTab(int Index) -{ - if (Index < 0 || Index >= count()) - { - return; - } - - auto Tab = tab(Index); - if (Tab->isHidden()) - { - return; - } - //Tab->hide(); - emit tabCloseRequested(Index); -} - - -//=========================================================================== -bool CDockAreaTabBar::eventFilter(QObject *watched, QEvent *event) -{ - bool Result = Super::eventFilter(watched, event); - CDockWidgetTab* Tab = qobject_cast(watched); - if (!Tab) - { - return Result; - } - - switch (event->type()) - { - case QEvent::Hide: - emit tabClosed(d->TabsLayout->indexOf(Tab)); break; - case QEvent::Show: - emit tabOpened(d->TabsLayout->indexOf(Tab)); break; - default: - break; - } - - return Result; -} - - -//=========================================================================== -bool CDockAreaTabBar::isTabOpen(int Index) const -{ - if (Index < 0 || Index >= count()) - { - return false; - } - - return !tab(Index)->isHidden(); -} - - -//=========================================================================== -QSize CDockAreaTabBar::minimumSizeHint() const -{ - QSize Size = sizeHint(); - Size.setWidth(Super::minimumSizeHint().width());// this defines the minimum width of a dock area - return Size; -} - - -//=========================================================================== -QSize CDockAreaTabBar::sizeHint() const -{ - QSize Size = Super::sizeHint(); - Size.setHeight(d->TabsContainerWidget->sizeHint().height()); - return Size; -} - - -//=========================================================================== -eDragState CDockAreaTabBar::dragState() const -{ - return d->DragState; -} - -} // namespace ads - -//--------------------------------------------------------------------------- -// EOF DockAreaTabBar.cpp diff --git a/src/ui/AdvDock/DockAreaTabBar.h b/src/ui/AdvDock/DockAreaTabBar.h deleted file mode 100644 index 730b8c76..00000000 --- a/src/ui/AdvDock/DockAreaTabBar.h +++ /dev/null @@ -1,247 +0,0 @@ -#ifndef DockAreaTabBarH -#define DockAreaTabBarH -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockAreaTabBar.h -/// \author Uwe Kindler -/// \date 24.08.2018 -/// \brief Declaration of CDockAreaTabBar class -//============================================================================ - -//============================================================================ -// INCLUDES -//============================================================================ -#include - -#include "ads_globals.h" - -namespace ads -{ -class CDockAreaWidget; -class CDockWidgetTab; -struct DockAreaTabBarPrivate; -class CDockAreaTitleBar; -class CFloatingDockContainer; -class IFloatingWidget; - -/** - * Custom tabbar implementation for tab area that is shown on top of a - * dock area widget. - * The tabbar displays the tab widgets of the contained dock widgets. - * We cannot use QTabBar here because it does a lot of fancy animations - * that will crash the application if a tab is removed while the animation - * has not finished. And we need to remove a tab, if the user drags a - * a dock widget out of a group of tabbed widgets - */ -class CDockAreaTabBar : public QScrollArea -{ - Q_OBJECT -private: - DockAreaTabBarPrivate* d; ///< private data (pimpl) - friend struct DockAreaTabBarPrivate; - friend class CDockAreaTitleBar; - -private slots: - void onTabClicked(); - void onTabCloseRequested(); - void onCloseOtherTabsRequested(); - void onTabWidgetMoved(const QPoint& GlobalPos); - -protected: - virtual void wheelEvent(QWheelEvent* Event) override; - - /** - * Stores mouse position to detect dragging - */ - virtual void mousePressEvent(QMouseEvent* ev) override; - - /** - * Stores mouse position to detect dragging - */ - virtual void mouseReleaseEvent(QMouseEvent* ev) override; - - /** - * Starts floating the complete docking area including all dock widgets, - * if it is not the last dock area in a floating widget - */ - virtual void mouseMoveEvent(QMouseEvent* ev) override; - - /** - * Double clicking the title bar also starts floating of the complete area - */ - virtual void mouseDoubleClickEvent(QMouseEvent *event) override; - - /** - * Starts floating - */ - void startFloating(const QPoint& Offset); - - /** - * Makes the dock area floating - */ - IFloatingWidget* makeAreaFloating(const QPoint& Offset, eDragState DragState); - - /** - * Returns the current drag state - */ - eDragState dragState() const; - - -public: - using Super = QScrollArea; - - /** - * Default Constructor - */ - CDockAreaTabBar(CDockAreaWidget* parent); - - /** - * Virtual Destructor - */ - virtual ~CDockAreaTabBar(); - - /** - * Inserts the given dock widget tab at the given position. - * Inserting a new tab at an index less than or equal to the current index - * will increment the current index, but keep the current tab. - */ - void insertTab(int Index, CDockWidgetTab* Tab); - - /** - * Removes the given DockWidgetTab from the tabbar - */ - void removeTab(CDockWidgetTab* Tab); - - /** - * Returns the number of tabs in this tabbar - */ - int count() const; - - /** - * Returns the current index or -1 if no tab is selected - */ - int currentIndex() const; - - /** - * Returns the current tab or a nullptr if no tab is selected. - */ - CDockWidgetTab* currentTab() const; - - /** - * Returns the tab with the given index - */ - CDockWidgetTab* tab(int Index) const; - - /** - * Filters the tab widget events - */ - virtual bool eventFilter(QObject *watched, QEvent *event) override; - - /** - * This function returns true if the tab is open, that means if it is - * visible to the user. If the function returns false, the tab is - * closed - */ - bool isTabOpen(int Index) const; - - /** - * Overrides the minimumSizeHint() function of QScrollArea - * The minimumSizeHint() is bigger than the sizeHint () for the scroll - * area because even if the scrollbars are invisible, the required speace - * is reserved in the minimumSizeHint(). This override simply returns - * sizeHint(); - */ - virtual QSize minimumSizeHint() const override; - - /** - * The function provides a sizeHint that matches the height of the - * internal viewport. - */ - virtual QSize sizeHint() const override; - -public slots: - /** - * This property sets the index of the tab bar's visible tab - */ - void setCurrentIndex(int Index); - - /** - * This function will close the tab given in Index param. - * Closing a tab means, the tab will be hidden, it will not be removed - */ - void closeTab(int Index); - -signals: - /** - * This signal is emitted when the tab bar's current tab is about to be changed. The new - * current has the given index, or -1 if there isn't a new one. - */ - void currentChanging(int Index); - - /** - * This signal is emitted when the tab bar's current tab changes. The new - * current has the given index, or -1 if there isn't a new one - */ - void currentChanged(int Index); - - /** - * This signal is emitted when user clicks on a tab - */ - void tabBarClicked(int index); - - /** - * This signal is emitted when the close button on a tab is clicked. - * The index is the index that should be closed. - */ - void tabCloseRequested(int index); - - /** - * This signal is emitted if a tab has been closed - */ - void tabClosed(int index); - - /** - * This signal is emitted if a tab has been opened. - * A tab is opened if it has been made visible - */ - void tabOpened(int index); - - /** - * This signal is emitted when the tab has moved the tab at index position - * from to index position to. - */ - void tabMoved(int from, int to); - - /** - * This signal is emitted, just before the tab with the given index is - * removed - */ - void removingTab(int index); - - /** - * This signal is emitted if a tab has been inserted - */ - void tabInserted(int index); -}; // class CDockAreaTabBar -} // namespace ads -//----------------------------------------------------------------------------- -#endif // DockAreaTabBarH - diff --git a/src/ui/AdvDock/DockAreaTitleBar.cpp b/src/ui/AdvDock/DockAreaTitleBar.cpp deleted file mode 100644 index b662b16c..00000000 --- a/src/ui/AdvDock/DockAreaTitleBar.cpp +++ /dev/null @@ -1,386 +0,0 @@ -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockAreaTitleBar.cpp -/// \author Uwe Kindler -/// \date 12.10.2018 -/// \brief Implementation of CDockAreaTitleBar class -//============================================================================ - -//============================================================================ -// INCLUDES -//============================================================================ -#include "DockAreaTitleBar.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ads_globals.h" -#include "FloatingDockContainer.h" -#include "DockAreaWidget.h" -#include "DockOverlay.h" -#include "DockManager.h" -#include "DockWidget.h" -#include "DockWidgetTab.h" -#include "DockAreaTabBar.h" -#include "IconProvider.h" - -#include - -namespace ads -{ -using tTileBarButton = QToolButton; -/** - * Private data class of CDockAreaTitleBar class (pimpl) - */ -struct DockAreaTitleBarPrivate -{ - CDockAreaTitleBar* _this; - tTileBarButton* TabsMenuButton; - tTileBarButton* UndockButton; - tTileBarButton* CloseButton; - QBoxLayout* TopLayout; - CDockAreaWidget* DockArea; - CDockAreaTabBar* TabBar; - bool MenuOutdated = true; - QMenu* TabsMenu; - - /** - * Private data constructor - */ - DockAreaTitleBarPrivate(CDockAreaTitleBar* _public); - - /** - * Creates the title bar close and menu buttons - */ - void createButtons(); - - /** - * Creates the internal TabBar - */ - void createTabBar(); - - /** - * Convenience function for DockManager access - */ - CDockManager* dockManager() const - { - return DockArea->dockManager(); - } - - /** - * Returns true if the given config flag is set - */ - bool testConfigFlag(CDockManager::eConfigFlag Flag) const - { - return CDockManager::configFlags().testFlag(Flag); - } - - /** - * Helper function to set title bar button icons depending on operating - * system and to avoid duplicated code. On windows the standard icons - * are blurry since Qt 5.11 so we need to do some additional steps. - * If the global IconPovider of the dockmanager provides a custom - * Icon for the given CustomIconId, the this icon will be used. - */ - void setTitleBarButtonIcon(tTileBarButton* Button, QStyle::StandardPixmap StandarPixmap, - ads::eIcon CustomIconId) - { - // First we try to use custom icons if available - QIcon Icon = CDockManager::iconProvider().customIcon(CustomIconId); - if (!Icon.isNull()) - { - Button->setIcon(Icon); - return; - } - - #ifdef Q_OS_LINUX - Button->setIcon(_this->style()->standardIcon(StandarPixmap)); - #else - QPixmap normalPixmap = _this->style()->standardPixmap(StandarPixmap, 0, Button); - Icon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled); - Icon.addPixmap(normalPixmap, QIcon::Normal); - Button->setIcon(Icon); - #endif - } -};// struct DockAreaTitleBarPrivate - - - -//============================================================================ -DockAreaTitleBarPrivate::DockAreaTitleBarPrivate(CDockAreaTitleBar* _public) : - _this(_public) -{ - -} - - -//============================================================================ -void DockAreaTitleBarPrivate::createButtons() -{ - QSizePolicy ButtonSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); - // Tabs menu button - TabsMenuButton = new tTileBarButton(); - TabsMenuButton->setObjectName("tabsMenuButton"); - TabsMenuButton->setAutoRaise(true); - TabsMenuButton->setPopupMode(QToolButton::InstantPopup); - setTitleBarButtonIcon(TabsMenuButton, QStyle::SP_TitleBarUnshadeButton, ads::DockAreaMenuIcon); - QMenu* TabsMenu = new QMenu(TabsMenuButton); -#ifndef QT_NO_TOOLTIP - TabsMenu->setToolTipsVisible(true); -#endif - _this->connect(TabsMenu, SIGNAL(aboutToShow()), SLOT(onTabsMenuAboutToShow())); - TabsMenuButton->setMenu(TabsMenu); -#ifndef QT_NO_TOOLTIP - TabsMenuButton->setToolTip(QObject::tr("List all tabs")); -#endif - TabsMenuButton->setSizePolicy(ButtonSizePolicy); - TopLayout->addWidget(TabsMenuButton, 0); - _this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)), - SLOT(onTabsMenuActionTriggered(QAction*))); - - - // Undock button - UndockButton = new tTileBarButton(); - UndockButton->setObjectName("undockButton"); - UndockButton->setAutoRaise(true); -#ifndef QT_NO_TOOLTIP - UndockButton->setToolTip(QObject::tr("Detach Group")); -#endif - setTitleBarButtonIcon(UndockButton, QStyle::SP_TitleBarNormalButton, ads::DockAreaUndockIcon); - UndockButton->setSizePolicy(ButtonSizePolicy); - TopLayout->addWidget(UndockButton, 0); - _this->connect(UndockButton, SIGNAL(clicked()), SLOT(onUndockButtonClicked())); - - - // Close button - CloseButton = new tTileBarButton(); - CloseButton->setObjectName("closeButton"); - CloseButton->setAutoRaise(true); - setTitleBarButtonIcon(CloseButton, QStyle::SP_TitleBarCloseButton, ads::DockAreaCloseIcon); -#ifndef QT_NO_TOOLTIP - if (testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab)) - { - CloseButton->setToolTip(QObject::tr("Close Active Tab")); - } - else - { - CloseButton->setToolTip(QObject::tr("Close Group")); - } -#endif - CloseButton->setSizePolicy(ButtonSizePolicy); - CloseButton->setIconSize(QSize(16, 16)); - if (testConfigFlag(CDockManager::DockAreaHasCloseButton)) - { - TopLayout->addWidget(CloseButton, 0); - } - _this->connect(CloseButton, SIGNAL(clicked()), SLOT(onCloseButtonClicked())); -} - - -//============================================================================ -void DockAreaTitleBarPrivate::createTabBar() -{ - TabBar = new CDockAreaTabBar(DockArea); - TopLayout->addWidget(TabBar); - _this->connect(TabBar, SIGNAL(tabClosed(int)), SLOT(markTabsMenuOutdated())); - _this->connect(TabBar, SIGNAL(tabOpened(int)), SLOT(markTabsMenuOutdated())); - _this->connect(TabBar, SIGNAL(tabInserted(int)), SLOT(markTabsMenuOutdated())); - _this->connect(TabBar, SIGNAL(removingTab(int)), SLOT(markTabsMenuOutdated())); - _this->connect(TabBar, SIGNAL(tabMoved(int, int)), SLOT(markTabsMenuOutdated())); - _this->connect(TabBar, SIGNAL(currentChanged(int)), SLOT(onCurrentTabChanged(int))); - _this->connect(TabBar, SIGNAL(tabBarClicked(int)), SIGNAL(tabBarClicked(int))); - - TabBar->setContextMenuPolicy(Qt::CustomContextMenu); - _this->connect(TabBar, SIGNAL(customContextMenuRequested(const QPoint&)), - SLOT(showContextMenu(const QPoint&))); -} - - -//============================================================================ -CDockAreaTitleBar::CDockAreaTitleBar(CDockAreaWidget* parent) : - QFrame(parent), - d(new DockAreaTitleBarPrivate(this)) -{ - d->DockArea = parent; - - setObjectName("dockAreaTitleBar"); - d->TopLayout = new QBoxLayout(QBoxLayout::LeftToRight); - d->TopLayout->setContentsMargins(0, 0, 0, 0); - d->TopLayout->setSpacing(0); - setLayout(d->TopLayout); - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - - d->createTabBar(); - d->createButtons(); - -} - - -//============================================================================ -CDockAreaTitleBar::~CDockAreaTitleBar() -{ - delete d; -} - - -//============================================================================ -CDockAreaTabBar* CDockAreaTitleBar::tabBar() const -{ - return d->TabBar; -} - - -//============================================================================ -void CDockAreaTitleBar::markTabsMenuOutdated() -{ - d->MenuOutdated = true; -} - - -//============================================================================ -void CDockAreaTitleBar::onTabsMenuAboutToShow() -{ - if (!d->MenuOutdated) - { - return; - } - - QMenu* menu = d->TabsMenuButton->menu(); - menu->clear(); - for (int i = 0; i < d->TabBar->count(); ++i) - { - if (!d->TabBar->isTabOpen(i)) - { - continue; - } - auto Tab = d->TabBar->tab(i); - QAction* Action = menu->addAction(Tab->icon(), Tab->text()); - #ifndef QT_NO_TOOLTIP - Action->setToolTip(Tab->toolTip()); - #endif - Action->setData(i); - } - - d->MenuOutdated = false; -} - - -//============================================================================ -void CDockAreaTitleBar::onCloseButtonClicked() -{ - ADS_PRINT("CDockAreaTitleBar::onCloseButtonClicked"); - if (d->testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab)) - { - d->TabBar->closeTab(d->TabBar->currentIndex()); - } - else - { - d->DockArea->closeArea(); - } -} - - -//============================================================================ -void CDockAreaTitleBar::onUndockButtonClicked() -{ - if (d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable)) - { - d->TabBar->makeAreaFloating(mapFromGlobal(QCursor::pos()), DraggingInactive); - } -} - - -//============================================================================ -void CDockAreaTitleBar::onTabsMenuActionTriggered(QAction* Action) -{ - int Index = Action->data().toInt(); - d->TabBar->setCurrentIndex(Index); - emit tabBarClicked(Index); -} - - -//============================================================================ -void CDockAreaTitleBar::onCurrentTabChanged(int Index) -{ - if (Index < 0) - { - return; - } - - if (d->testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab)) - { - CDockWidget* DockWidget = d->TabBar->tab(Index)->dockWidget(); - d->CloseButton->setEnabled(DockWidget->features().testFlag(CDockWidget::DockWidgetClosable)); - } -} - - -//============================================================================ -QAbstractButton* CDockAreaTitleBar::button(TitleBarButton which) const -{ - switch (which) - { - case TitleBarButtonTabsMenu: return d->TabsMenuButton; - case TitleBarButtonUndock: return d->UndockButton; - case TitleBarButtonClose: return d->CloseButton; - default: - return nullptr; - } -} - - -//============================================================================ -void CDockAreaTitleBar::setVisible(bool Visible) -{ - Super::setVisible(Visible); - markTabsMenuOutdated(); -} - - -//============================================================================ -void CDockAreaTitleBar::showContextMenu(const QPoint& pos) -{ - if (d->TabBar->dragState() == DraggingFloatingWidget) - { - return; - } - - QMenu Menu(this); - auto Action = Menu.addAction(tr("Detach Area"), this, SLOT(onUndockButtonClicked())); - Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable)); - Menu.addSeparator(); - Action = Menu.addAction(tr("Close Area"), this, SLOT(onCloseButtonClicked())); - Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetClosable)); - Menu.addAction(tr("Close Other Areas"), d->DockArea, SLOT(closeOtherAreas())); - Menu.exec(mapToGlobal(pos)); -} - - -} // namespace ads - -//--------------------------------------------------------------------------- -// EOF DockAreaTitleBar.cpp diff --git a/src/ui/AdvDock/DockAreaTitleBar.h b/src/ui/AdvDock/DockAreaTitleBar.h deleted file mode 100644 index 8b07d7b4..00000000 --- a/src/ui/AdvDock/DockAreaTitleBar.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef DockAreaTitleBarH -#define DockAreaTitleBarH -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockAreaTitleBar.h -/// \author Uwe Kindler -/// \date 12.10.2018 -/// \brief Declaration of CDockAreaTitleBar class -//============================================================================ - - -//============================================================================ -// INCLUDES -//============================================================================ -#include - -#include "ads_globals.h" - -class QAbstractButton; - -namespace ads -{ -class CDockAreaTabBar; -class CDockAreaWidget; -struct DockAreaTitleBarPrivate; - -/** - * Title bar of a dock area. - * The title bar contains a tabbar with all tabs for a dock widget group and - * with a tabs menu button, a undock button and a close button. - */ -class CDockAreaTitleBar : public QFrame -{ - Q_OBJECT -private: - DockAreaTitleBarPrivate* d; ///< private data (pimpl) - friend struct DockAreaTitleBarPrivate; - -private slots: - void onTabsMenuAboutToShow(); - void onCloseButtonClicked(); - void onUndockButtonClicked(); - void onTabsMenuActionTriggered(QAction* Action); - void onCurrentTabChanged(int Index); - void showContextMenu(const QPoint& pos); - -public slots: - /** - * Call this slot to tell the title bar that it should update the tabs menu - * the next time it is shown. - */ - void markTabsMenuOutdated(); - - -public: - using Super = QFrame; - /** - * Default Constructor - */ - CDockAreaTitleBar(CDockAreaWidget* parent); - - /** - * Virtual Destructor - */ - virtual ~CDockAreaTitleBar(); - - /** - * Returns the pointer to the tabBar() - */ - CDockAreaTabBar* tabBar() const; - - /** - * Returns the button corresponding to the given title bar button identifier - */ - QAbstractButton* button(TitleBarButton which) const; - - /** - * Marks the tabs menu outdated before it calls its base class - * implementation - */ - virtual void setVisible(bool Visible) override; - - -signals: - /** - * This signal is emitted if a tab in the tab bar is clicked by the user - * or if the user clicks on a tab item in the title bar tab menu. - */ - void tabBarClicked(int index); -}; // class name -} - // namespace ads -//----------------------------------------------------------------------------- -#endif // DockAreaTitleBarH diff --git a/src/ui/AdvDock/DockAreaWidget.cpp b/src/ui/AdvDock/DockAreaWidget.cpp deleted file mode 100644 index 2d0ca485..00000000 --- a/src/ui/AdvDock/DockAreaWidget.cpp +++ /dev/null @@ -1,846 +0,0 @@ -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockAreaWidget.cpp -/// \author Uwe Kindler -/// \date 24.02.2017 -/// \brief Implementation of CDockAreaWidget class -//============================================================================ - - -//============================================================================ -// INCLUDES -//============================================================================ -#include "DockWidgetTab.h" -#include "DockAreaWidget.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "DockContainerWidget.h" -#include "DockWidget.h" -#include "FloatingDockContainer.h" -#include "DockManager.h" -#include "DockOverlay.h" -#include "DockAreaTabBar.h" -#include "DockSplitter.h" -#include "DockAreaTitleBar.h" - -#include - - -namespace ads -{ -static const char* const INDEX_PROPERTY = "index"; -static const char* const ACTION_PROPERTY = "action"; - -/** - * Internal dock area layout mimics stack layout but only inserts the current - * widget into the internal QLayout object. - * \warning Only the current widget has a parent. All other widgets - * do not have a parent. That means, a widget that is in this layout may - * return nullptr for its parent() function if it is not the current widget. - */ -class CDockAreaLayout -{ -private: - QBoxLayout* m_ParentLayout; - QList m_Widgets; - int m_CurrentIndex = -1; - QWidget* m_CurrentWidget = nullptr; - -public: - /** - * Creates an instance with the given parent layout - */ - CDockAreaLayout(QBoxLayout* ParentLayout) - : m_ParentLayout(ParentLayout) - { - - } - - /** - * Returns the number of widgets in this layout - */ - int count() const - { - return m_Widgets.count(); - } - - /** - * Inserts the widget at the given index position into the internal widget - * list - */ - void insertWidget(int index, QWidget* Widget) - { - Widget->setParent(nullptr); - if (index < 0) - { - index = m_Widgets.count(); - } - m_Widgets.insert(index, Widget); - if (m_CurrentIndex < 0) - { - setCurrentIndex(index); - } - else - { - if (index <= m_CurrentIndex ) - { - ++m_CurrentIndex; - } - } - } - - /** - * Removes the given widget from the layout - */ - void removeWidget(QWidget* Widget) - { - if (currentWidget() == Widget) - { - auto LayoutItem = m_ParentLayout->takeAt(1); - if (LayoutItem) - { - LayoutItem->widget()->setParent(nullptr); - } - m_CurrentWidget = nullptr; - m_CurrentIndex = -1; - } - m_Widgets.removeOne(Widget); - } - - /** - * Returns the current selected widget - */ - QWidget* currentWidget() const - { - return m_CurrentWidget; - } - - /** - * Activates the widget with the give index. - */ - void setCurrentIndex(int index) - { - QWidget *prev = currentWidget(); - QWidget *next = widget(index); - if (!next || (next == prev && !m_CurrentWidget)) - { - return; - } - - bool reenableUpdates = false; - QWidget *parent = m_ParentLayout->parentWidget(); - - if (parent && parent->updatesEnabled()) - { - reenableUpdates = true; - parent->setUpdatesEnabled(false); - } - - auto LayoutItem = m_ParentLayout->takeAt(1); - if (LayoutItem) - { - LayoutItem->widget()->setParent(nullptr); - } - - m_ParentLayout->addWidget(next); - if (prev) - { - prev->hide(); - } - m_CurrentIndex = index; - m_CurrentWidget = next; - - - if (reenableUpdates) - { - parent->setUpdatesEnabled(true); - } - } - - /** - * Returns the index of the current active widget - */ - int currentIndex() const - { - return m_CurrentIndex; - } - - /** - * Returns true if there are no widgets in the layout - */ - bool isEmpty() const - { - return m_Widgets.empty(); - } - - /** - * Returns the index of the given widget - */ - int indexOf(QWidget* w) const - { - return m_Widgets.indexOf(w); - } - - /** - * Returns the widget for the given index - */ - QWidget* widget(int index) const - { - return (index < m_Widgets.size()) ? m_Widgets.at(index) : nullptr; - } - - /** - * Returns the geometry of the current active widget - */ - QRect geometry() const - { - return m_Widgets.empty() ? QRect() : currentWidget()->geometry(); - } -}; - - - -using DockAreaLayout = CDockAreaLayout; - - -/** - * Private data class of CDockAreaWidget class (pimpl) - */ -struct DockAreaWidgetPrivate -{ - CDockAreaWidget* _this = nullptr; - QBoxLayout* Layout = nullptr; - DockAreaLayout* ContentsLayout = nullptr; - CDockAreaTitleBar* TitleBar = nullptr; - CDockManager* DockManager = nullptr; - bool UpdateTitleBarButtons = false; - - /** - * Private data constructor - */ - DockAreaWidgetPrivate(CDockAreaWidget* _public); - - /** - * Creates the layout for top area with tabs and close button - */ - void createTitleBar(); - - /** - * Returns the dock widget with the given index - */ - CDockWidget* dockWidgetAt(int index) - { - return dynamic_cast(ContentsLayout->widget(index)); - } - - /** - * Convenience function to ease title widget access by index - */ - CDockWidgetTab* tabWidgetAt(int index) - { - return dockWidgetAt(index)->tabWidget(); - } - - - /** - * Returns the tab action of the given dock widget - */ - QAction* dockWidgetTabAction(CDockWidget* DockWidget) const - { - return qvariant_cast(DockWidget->property(ACTION_PROPERTY)); - } - - /** - * Returns the index of the given dock widget - */ - int dockWidgetIndex(CDockWidget* DockWidget) const - { - return DockWidget->property(INDEX_PROPERTY).toInt(); - } - - /** - * Convenience function for tabbar access - */ - CDockAreaTabBar* tabBar() const - { - return TitleBar->tabBar(); - } - - /** - * Udpates the enable state of the close and detach button - */ - void updateTitleBarButtonStates(); -}; -// struct DockAreaWidgetPrivate - - -//============================================================================ -DockAreaWidgetPrivate::DockAreaWidgetPrivate(CDockAreaWidget* _public) : - _this(_public) -{ - -} - - -//============================================================================ -void DockAreaWidgetPrivate::createTitleBar() -{ - TitleBar = new CDockAreaTitleBar(_this); - Layout->addWidget(TitleBar); - QObject::connect(tabBar(), &CDockAreaTabBar::tabCloseRequested, _this, &CDockAreaWidget::onTabCloseRequested); - QObject::connect(TitleBar, &CDockAreaTitleBar::tabBarClicked, _this, &CDockAreaWidget::setCurrentIndex); - QObject::connect(tabBar(), &CDockAreaTabBar::tabMoved, _this, &CDockAreaWidget::reorderDockWidget); -} - - -//============================================================================ -void DockAreaWidgetPrivate::updateTitleBarButtonStates() -{ - if (_this->isHidden()) - { - UpdateTitleBarButtons = true; - return; - } - - TitleBar->button(TitleBarButtonClose)->setEnabled( - _this->features().testFlag(CDockWidget::DockWidgetClosable)); - TitleBar->button(TitleBarButtonUndock)->setEnabled( - _this->features().testFlag(CDockWidget::DockWidgetFloatable)); - UpdateTitleBarButtons = false; -} - - -//============================================================================ -CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent) : - QFrame(parent), - d(new DockAreaWidgetPrivate(this)) -{ - d->DockManager = DockManager; - d->Layout = new QBoxLayout(QBoxLayout::TopToBottom); - d->Layout->setContentsMargins(0, 0, 0, 0); - d->Layout->setSpacing(0); - setLayout(d->Layout); - - d->createTitleBar(); - d->ContentsLayout = new DockAreaLayout(d->Layout); - if (d->DockManager) - { - emit d->DockManager->dockAreaCreated(this); - } -} - -//============================================================================ -CDockAreaWidget::~CDockAreaWidget() -{ - ADS_PRINT("~CDockAreaWidget()"); - delete d->ContentsLayout; - delete d; -} - - -//============================================================================ -CDockManager* CDockAreaWidget::dockManager() const -{ - return d->DockManager; -} - - -//============================================================================ -CDockContainerWidget* CDockAreaWidget::dockContainer() const -{ - return internal::findParent(this); -} - - -//============================================================================ -void CDockAreaWidget::addDockWidget(CDockWidget* DockWidget) -{ - insertDockWidget(d->ContentsLayout->count(), DockWidget); -} - - -//============================================================================ -void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget, - bool Activate) -{ - d->ContentsLayout->insertWidget(index, DockWidget); - DockWidget->tabWidget()->setDockAreaWidget(this); - auto TabWidget = DockWidget->tabWidget(); - // Inserting the tab will change the current index which in turn will - // make the tab widget visible in the slot - d->tabBar()->blockSignals(true); - d->tabBar()->insertTab(index, TabWidget); - d->tabBar()->blockSignals(false); - TabWidget->setVisible(!DockWidget->isClosed()); - DockWidget->setProperty(INDEX_PROPERTY, index); - if (Activate) - { - setCurrentIndex(index); - } - DockWidget->setDockArea(this); - d->updateTitleBarButtonStates(); -} - - -//============================================================================ -void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget) -{ - ADS_PRINT("CDockAreaWidget::removeDockWidget"); - auto NextOpenDockWidget = nextOpenDockWidget(DockWidget); - - d->ContentsLayout->removeWidget(DockWidget); - auto TabWidget = DockWidget->tabWidget(); - TabWidget->hide(); - d->tabBar()->removeTab(TabWidget); - CDockContainerWidget* DockContainer = dockContainer(); - if (NextOpenDockWidget) - { - setCurrentDockWidget(NextOpenDockWidget); - } - else if (d->ContentsLayout->isEmpty() && DockContainer->dockAreaCount() > 1) - { - ADS_PRINT("Dock Area empty"); - DockContainer->removeDockArea(this); - this->deleteLater(); - } - else - { - // if contents layout is not empty but there are no more open dock - // widgets, then we need to hide the dock area because it does not - // contain any visible content - hideAreaWithNoVisibleContent(); - } - - d->updateTitleBarButtonStates(); - updateTitleBarVisibility(); - auto TopLevelDockWidget = DockContainer->topLevelDockWidget(); - if (TopLevelDockWidget) - { - TopLevelDockWidget->emitTopLevelChanged(true); - } - -#if (ADS_DEBUG_LEVEL > 0) - DockContainer->dumpLayout(); -#endif -} - - -//============================================================================ -void CDockAreaWidget::hideAreaWithNoVisibleContent() -{ - this->toggleView(false); - - // Hide empty parent splitters - auto Splitter = internal::findParent(this); - internal::hideEmptyParentSplitters(Splitter); - - //Hide empty floating widget - CDockContainerWidget* Container = this->dockContainer(); - if (!Container->isFloating()) - { - return; - } - - updateTitleBarVisibility(); - auto TopLevelWidget = Container->topLevelDockWidget(); - auto FloatingWidget = Container->floatingWidget(); - if (TopLevelWidget) - { - FloatingWidget->updateWindowTitle(); - CDockWidget::emitTopLevelEventForWidget(TopLevelWidget, true); - } - else if (Container->openedDockAreas().isEmpty()) - { - FloatingWidget->hide(); - } -} - - -//============================================================================ -void CDockAreaWidget::onTabCloseRequested(int Index) -{ - ADS_PRINT("CDockAreaWidget::onTabCloseRequested " << Index); - auto* DockWidget = dockWidget(Index); - if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose)) - { - //DockWidget->deleteDockWidget(); - DockWidget->closeDockWidgetInternal(); - } - else - { - DockWidget->toggleView(false); - } -} - - -//============================================================================ -CDockWidget* CDockAreaWidget::currentDockWidget() const -{ - int CurrentIndex = currentIndex(); - if (CurrentIndex < 0) - { - return nullptr; - } - - return dockWidget(CurrentIndex); -} - - -//============================================================================ -void CDockAreaWidget::setCurrentDockWidget(CDockWidget* DockWidget) -{ - if (dockManager()->isRestoringState()) - { - return; - } - - internalSetCurrentDockWidget(DockWidget); -} - - -//============================================================================ -void CDockAreaWidget::internalSetCurrentDockWidget(CDockWidget* DockWidget) -{ - int Index = index(DockWidget); - if (Index < 0) - { - return; - } - - setCurrentIndex(Index); -} - - -//============================================================================ -void CDockAreaWidget::setCurrentIndex(int index) -{ - auto TabBar = d->tabBar(); - if (index < 0 || index > (TabBar->count() - 1)) - { - qWarning() << Q_FUNC_INFO << "Invalid index" << index; - return; - } - - auto cw = d->ContentsLayout->currentWidget(); - auto nw = d->ContentsLayout->widget(index); - if (cw == nw && !nw->isHidden()) - { - return; - } - - emit currentChanging(index); - TabBar->setCurrentIndex(index); - d->ContentsLayout->setCurrentIndex(index); - d->ContentsLayout->currentWidget()->show(); - emit currentChanged(index); -} - - -//============================================================================ -int CDockAreaWidget::currentIndex() const -{ - return d->ContentsLayout->currentIndex(); -} - - -//============================================================================ -QRect CDockAreaWidget::titleBarGeometry() const -{ - return d->TitleBar->geometry(); -} - -//============================================================================ -QRect CDockAreaWidget::contentAreaGeometry() const -{ - return d->ContentsLayout->geometry(); -} - - -//============================================================================ -int CDockAreaWidget::index(CDockWidget* DockWidget) -{ - return d->ContentsLayout->indexOf(DockWidget); -} - - -//============================================================================ -QList CDockAreaWidget::dockWidgets() const -{ - QList DockWidgetList; - for (int i = 0; i < d->ContentsLayout->count(); ++i) - { - DockWidgetList.append(dockWidget(i)); - } - return DockWidgetList; -} - - -//============================================================================ -int CDockAreaWidget::openDockWidgetsCount() const -{ - int Count = 0; - for (int i = 0; i < d->ContentsLayout->count(); ++i) - { - if (!dockWidget(i)->isClosed()) - { - ++Count; - } - } - return Count; -} - - -//============================================================================ -QList CDockAreaWidget::openedDockWidgets() const -{ - QList DockWidgetList; - for (int i = 0; i < d->ContentsLayout->count(); ++i) - { - CDockWidget* DockWidget = dockWidget(i); - if (!DockWidget->isClosed()) - { - DockWidgetList.append(dockWidget(i)); - } - } - return DockWidgetList; -} - - -//============================================================================ -int CDockAreaWidget::indexOfFirstOpenDockWidget() const -{ - for (int i = 0; i < d->ContentsLayout->count(); ++i) - { - if (!dockWidget(i)->isClosed()) - { - return i; - } - } - - return -1; -} - - -//============================================================================ -int CDockAreaWidget::dockWidgetsCount() const -{ - return d->ContentsLayout->count(); -} - - -//============================================================================ -CDockWidget* CDockAreaWidget::dockWidget(int Index) const -{ - return qobject_cast(d->ContentsLayout->widget(Index)); -} - - -//============================================================================ -void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex) -{ - ADS_PRINT("CDockAreaWidget::reorderDockWidget"); - if (fromIndex >= d->ContentsLayout->count() || fromIndex < 0 - || toIndex >= d->ContentsLayout->count() || toIndex < 0 || fromIndex == toIndex) - { - ADS_PRINT("Invalid index for tab movement" << fromIndex << toIndex); - return; - } - - auto Widget = d->ContentsLayout->widget(fromIndex); - d->ContentsLayout->removeWidget(Widget); - d->ContentsLayout->insertWidget(toIndex, Widget); - setCurrentIndex(toIndex); -} - - -//============================================================================ -void CDockAreaWidget::toggleDockWidgetView(CDockWidget* DockWidget, bool Open) -{ - Q_UNUSED(DockWidget); - Q_UNUSED(Open); - updateTitleBarVisibility(); -} - - -//============================================================================ -void CDockAreaWidget::updateTitleBarVisibility() -{ - CDockContainerWidget* Container = dockContainer(); - if (!Container) - { - return; - } - - if (d->TitleBar) - { - d->TitleBar->setVisible(!Container->isFloating() || !Container->hasTopLevelDockWidget()); - } -} - - -//============================================================================ -void CDockAreaWidget::markTitleBarMenuOutdated() -{ - if (d->TitleBar) - { - d->TitleBar->markTabsMenuOutdated(); - } -} - - - -//============================================================================ -void CDockAreaWidget::saveState(QXmlStreamWriter& s) const -{ - s.writeStartElement("Area"); - s.writeAttribute("Tabs", QString::number(d->ContentsLayout->count())); - auto CurrentDockWidget = currentDockWidget(); - QString Name = CurrentDockWidget ? CurrentDockWidget->objectName() : ""; - s.writeAttribute("Current", Name); - ADS_PRINT("CDockAreaWidget::saveState TabCount: " << d->ContentsLayout->count() - << " Current: " << Name); - for (int i = 0; i < d->ContentsLayout->count(); ++i) - { - dockWidget(i)->saveState(s); - } - s.writeEndElement(); -} - - -//============================================================================ -CDockWidget* CDockAreaWidget::nextOpenDockWidget(CDockWidget* DockWidget) const -{ - auto OpenDockWidgets = openedDockWidgets(); - if (OpenDockWidgets.count() > 1 || (OpenDockWidgets.count() == 1 && OpenDockWidgets[0] != DockWidget)) - { - CDockWidget* NextDockWidget; - if (OpenDockWidgets.last() == DockWidget) - { - NextDockWidget = OpenDockWidgets[OpenDockWidgets.count() - 2]; - } - else - { - int NextIndex = OpenDockWidgets.indexOf(DockWidget) + 1; - NextDockWidget = OpenDockWidgets[NextIndex]; - } - - return NextDockWidget; - } - else - { - return nullptr; - } -} - - -//============================================================================ -CDockWidget::DockWidgetFeatures CDockAreaWidget::features(eBitwiseOperator Mode) const -{ - if (BitwiseAnd == Mode) - { - CDockWidget::DockWidgetFeatures Features(CDockWidget::AllDockWidgetFeatures); - for (const auto DockWidget : dockWidgets()) - { - Features &= DockWidget->features(); - } - return Features; - } - else - { - CDockWidget::DockWidgetFeatures Features(CDockWidget::NoDockWidgetFeatures); - for (const auto DockWidget : dockWidgets()) - { - Features |= DockWidget->features(); - } - return Features; - } -} - - -//============================================================================ -void CDockAreaWidget::toggleView(bool Open) -{ - setVisible(Open); - - emit viewToggled(Open); -} - - -//============================================================================ -void CDockAreaWidget::setVisible(bool Visible) -{ - Super::setVisible(Visible); - if (d->UpdateTitleBarButtons) - { - d->updateTitleBarButtonStates(); - } -} - - -//============================================================================ -QAbstractButton* CDockAreaWidget::titleBarButton(TitleBarButton which) const -{ - return d->TitleBar->button(which); -} - - -//============================================================================ -void CDockAreaWidget::closeArea() -{ - // If there is only one single dock widget and this widget has the - // DeleteOnClose feature, then we delete the dock widget now - auto OpenDockWidgets = openedDockWidgets(); - if (OpenDockWidgets.count() == 1 && OpenDockWidgets[0]->features().testFlag(CDockWidget::DockWidgetDeleteOnClose)) - { - OpenDockWidgets[0]->closeDockWidgetInternal(); - } - else - { - for (auto DockWidget : openedDockWidgets()) - { - DockWidget->toggleView(false); - } - } -} - - -//============================================================================ -void CDockAreaWidget::closeOtherAreas() -{ - dockContainer()->closeOtherAreas(this); -} -} // namespace ads - -//--------------------------------------------------------------------------- -// EOF DockAreaWidget.cpp diff --git a/src/ui/AdvDock/DockAreaWidget.h b/src/ui/AdvDock/DockAreaWidget.h deleted file mode 100644 index cfca256c..00000000 --- a/src/ui/AdvDock/DockAreaWidget.h +++ /dev/null @@ -1,303 +0,0 @@ -#ifndef DockAreaWidgetH -#define DockAreaWidgetH -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockAreaWidget.h -/// \author Uwe Kindler -/// \date 24.02.2017 -/// \brief Declaration of CDockAreaWidget class -//============================================================================ - - -//============================================================================ -// INCLUDES -//============================================================================ -#include - -#include "DockWidget.h" - -class QXmlStreamWriter; -class QAbstractButton; - -namespace ads -{ -struct DockAreaWidgetPrivate; -class CDockManager; -class CDockContainerWidget; -class DockContainerWidgetPrivate; - - -/** - * DockAreaWidget manages multiple instances of DockWidgets. - * It displays a title tab, which is clickable and will switch to - * the contents associated to the title when clicked. - */ -class CDockAreaWidget : public QFrame -{ - Q_OBJECT -private: - DockAreaWidgetPrivate* d; ///< private data (pimpl) - friend struct DockAreaWidgetPrivate; - friend class CDockContainerWidget; - friend class DockContainerWidgetPrivate; - friend class CDockWidgetTab; - friend struct DockWidgetPrivate; - friend class CDockWidget; - friend struct DockManagerPrivate; - friend class CDockManager; - -private slots: - void onTabCloseRequested(int Index); - - /** - * Reorder the index position of DockWidget at fromIndx to toIndex - * if a tab in the tabbar is dragged from one index to another one - */ - void reorderDockWidget(int fromIndex, int toIndex); - -protected: - /** - * Inserts a dock widget into dock area. - * All dockwidgets in the dock area tabified in a stacked layout with tabs. - * The index indicates the index of the new dockwidget in the tabbar and - * in the stacked layout. If the Activate parameter is true, the new - * DockWidget will be the active one in the stacked layout - */ - void insertDockWidget(int index, CDockWidget* DockWidget, bool Activate = true); - - /** - * Add a new dock widget to dock area. - * All dockwidgets in the dock area tabified in a stacked layout with tabs - */ - void addDockWidget(CDockWidget* DockWidget); - - /** - * Removes the given dock widget from the dock area - */ - void removeDockWidget(CDockWidget* DockWidget); - - /** - * Called from dock widget if it is opened or closed - */ - void toggleDockWidgetView(CDockWidget* DockWidget, bool Open); - - /** - * This is a helper function to get the next open dock widget to activate - * if the given DockWidget will be closed or removed. - * The function returns the next widget that should be activated or - * nullptr in case there are no more open widgets in this area. - */ - CDockWidget* nextOpenDockWidget(CDockWidget* DockWidget) const; - - /** - * Returns the index of the given DockWidget in the internal layout - */ - int index(CDockWidget* DockWidget); - - /** - * Call this function, if you already know, that the dock does not - * contain any visible content (any open dock widgets). - */ - void hideAreaWithNoVisibleContent(); - - /** - * Updates the dock area layout and components visibility - */ - void updateTitleBarVisibility(); - - /** - * This is the internal private function for setting the current widget. - * This function is called by the public setCurrentDockWidget() function - * and by the dock manager when restoring the state - */ - void internalSetCurrentDockWidget(CDockWidget* DockWidget); - - /** - * Marks tabs menu to update - */ - void markTitleBarMenuOutdated(); - -protected slots: - void toggleView(bool Open); - -public: - using Super = QFrame; - - /** - * Default Constructor - */ - CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent); - - /** - * Virtual Destructor - */ - virtual ~CDockAreaWidget(); - - /** - * Returns the dock manager object this dock area belongs to - */ - CDockManager* dockManager() const; - - /** - * Returns the dock container widget this dock area widget belongs to or 0 - * if there is no - */ - CDockContainerWidget* dockContainer() const; - - /** - * Returns the rectangle of the title area - */ - QRect titleBarGeometry() const; - - /** - * Returns the rectangle of the content - */ - QRect contentAreaGeometry() const; - - /** - * Returns the number of dock widgets in this area - */ - int dockWidgetsCount() const; - - /** - * Returns a list of all dock widgets in this dock area. - * This list contains open and closed dock widgets. - */ - QList dockWidgets() const; - - /** - * Returns the number of open dock widgets in this area - */ - int openDockWidgetsCount() const; - - /** - * Returns a list of dock widgets that are not closed. - */ - QList openedDockWidgets() const; - - /** - * Returns a dock widget by its index - */ - CDockWidget* dockWidget(int Index) const; - - /** - * Returns the index of the current active dock widget or -1 if there - * are is no active dock widget (ie.e if all dock widgets are closed) - */ - int currentIndex() const; - - /** - * Returns the index of the first open dock widgets in the list of - * dock widgets. - * This function is here for performance reasons. Normally it would - * be possible to take the first dock widget from the list returned by - * openedDockWidgets() function. But that function enumerates all - * dock widgets while this functions stops after the first open dock widget. - * If there are no open dock widgets, the function returns -1. - */ - int indexOfFirstOpenDockWidget() const; - - /** - * Returns the current active dock widget or a nullptr if there is no - * active dock widget (i.e. if all dock widgets are closed) - */ - CDockWidget* currentDockWidget() const; - - /** - * Shows the tab with the given dock widget - */ - void setCurrentDockWidget(CDockWidget* DockWidget); - - /** - * Saves the state into the given stream - */ - void saveState(QXmlStreamWriter& Stream) const; - - /** - * This functions returns the dock widget features of all dock widget in - * this area. - * A bitwise and is used to combine the flags of all dock widgets. That - * means, if only one single dock widget does not support a certain flag, - * the whole dock are does not support the flag. I.e. if one single - * dock widget in this area is not closable, the whole dock are is not - * closable. - */ - CDockWidget::DockWidgetFeatures features(eBitwiseOperator Mode = BitwiseAnd) const; - - /** - * Returns the title bar button corresponding to the given title bar - * button identifier - */ - QAbstractButton* titleBarButton(TitleBarButton which) const; - - /** - * Update the close button if visibility changed - */ - virtual void setVisible(bool Visible) override; - -public slots: - /** - * This activates the tab for the given tab index. - * If the dock widget for the given tab is not visible, the this function - * call will make it visible. - */ - void setCurrentIndex(int index); - - /** - * Closes the dock area and all dock widgets in this area - */ - void closeArea(); - - /** - * This function closes all other areas except of this area - */ - void closeOtherAreas(); - -signals: - /** - * This signal is emitted when user clicks on a tab at an index. - */ - void tabBarClicked(int index); - - /** - * This signal is emitted when the tab bar's current tab is about to be changed. The new - * current has the given index, or -1 if there isn't a new one. - * @param index - */ - void currentChanging(int index); - - /** - * This signal is emitted when the tab bar's current tab changes. The new - * current has the given index, or -1 if there isn't a new one - * @param index - */ - void currentChanged(int index); - - /** - * This signal is emitted if the visibility of this dock area is toggled - * via toggle view function - */ - void viewToggled(bool Open); -}; // class DockAreaWidget -} - // namespace ads -//----------------------------------------------------------------------------- -#endif // DockAreaWidgetH diff --git a/src/ui/AdvDock/DockContainerWidget.cpp b/src/ui/AdvDock/DockContainerWidget.cpp deleted file mode 100644 index 128a77ce..00000000 --- a/src/ui/AdvDock/DockContainerWidget.cpp +++ /dev/null @@ -1,1740 +0,0 @@ -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockContainerWidget.cpp -/// \author Uwe Kindler -/// \date 24.02.2017 -/// \brief Implementation of CDockContainerWidget class -//============================================================================ - - -//============================================================================ -// INCLUDES -//============================================================================ -#include "DockContainerWidget.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "DockManager.h" -#include "DockAreaWidget.h" -#include "DockWidget.h" -#include "DockingStateReader.h" -#include "FloatingDockContainer.h" -#include "DockOverlay.h" -#include "ads_globals.h" -#include "DockSplitter.h" - -#include -#include - -#if QT_VERSION < 0x050900 - -inline char toHexLower(uint value) -{ - return "0123456789abcdef"[value & 0xF]; -} - -QByteArray qByteArrayToHex(const QByteArray& src, char separator) -{ - if(src.size() == 0) - return QByteArray(); - - const int length = separator ? (src.size() * 3 - 1) : (src.size() * 2); - QByteArray hex(length, Qt::Uninitialized); - char *hexData = hex.data(); - const uchar *data = reinterpret_cast(src.data()); - for (int i = 0, o = 0; i < src.size(); ++i) { - hexData[o++] = toHexLower(data[i] >> 4); - hexData[o++] = toHexLower(data[i] & 0xf); - - if ((separator) && (o < length)) - hexData[o++] = separator; - } - return hex; -} -#endif - -namespace ads -{ -static unsigned int zOrderCounter = 0; - -enum eDropMode -{ - DropModeIntoArea,///< drop widget into a dock area - DropModeIntoContainer,///< drop into container - DropModeInvalid///< invalid mode - do not drop -}; - -/** - * Converts dock area ID to an index for array access - */ -static int areaIdToIndex(DockWidgetArea area) -{ - switch (area) - { - case LeftDockWidgetArea: return 0; - case RightDockWidgetArea: return 1; - case TopDockWidgetArea: return 2; - case BottomDockWidgetArea: return 3; - case CenterDockWidgetArea: return 4; - default: - return 4; - } -} - -/** - * Helper function to ease insertion of dock area into splitter - */ -static void insertWidgetIntoSplitter(QSplitter* Splitter, QWidget* widget, bool Append) -{ - if (Append) - { - Splitter->addWidget(widget); - } - else - { - Splitter->insertWidget(0, widget); - } -} - -/** - * Private data class of CDockContainerWidget class (pimpl) - */ -class DockContainerWidgetPrivate -{ -public: - CDockContainerWidget* _this; - QPointer DockManager; - unsigned int zOrderIndex = 0; - QList DockAreas; - QGridLayout* Layout = nullptr; - QSplitter* RootSplitter = nullptr; - bool isFloating = false; - CDockAreaWidget* LastAddedAreaCache[5]; - int VisibleDockAreaCount = -1; - CDockAreaWidget* TopLevelDockArea = nullptr; - - /** - * Private data constructor - */ - DockContainerWidgetPrivate(CDockContainerWidget* _public); - - /** - * Adds dock widget to container and returns the dock area that contains - * the inserted dock widget - */ - CDockAreaWidget* dockWidgetIntoContainer(DockWidgetArea area, CDockWidget* Dockwidget); - - /** - * Adds dock widget to a existing DockWidgetArea - */ - CDockAreaWidget* dockWidgetIntoDockArea(DockWidgetArea area, CDockWidget* Dockwidget, - CDockAreaWidget* TargetDockArea); - - /** - * Add dock area to this container - */ - void addDockArea(CDockAreaWidget* NewDockWidget, DockWidgetArea area = CenterDockWidgetArea); - - /** - * Drop floating widget into container - */ - void dropIntoContainer(CFloatingDockContainer* FloatingWidget, DockWidgetArea area); - - /** - * Drop floating widget into dock area - */ - void dropIntoSection(CFloatingDockContainer* FloatingWidget, - CDockAreaWidget* TargetArea, DockWidgetArea area); - - /** - * Moves the dock widget or dock area given in Widget parameter to a - * new dock widget area - */ - void moveToNewSection(QWidget* Widget, CDockAreaWidget* TargetArea, DockWidgetArea area); - - /** - * Moves the dock widget or dock area given in Widget parameter to a - * a dock area in container - */ - void moveToContainer(QWidget* Widgett, DockWidgetArea area); - - /** - * Creates a new tab for a widget dropped into the center of a section - */ - void dropIntoCenterOfSection(CFloatingDockContainer* FloatingWidget, - CDockAreaWidget* TargetArea); - - /** - * Creates a new tab for a widget dropped into the center of a section - */ - void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea); - - - /** - * Adds new dock areas to the internal dock area list - */ - void addDockAreasToList(const QList NewDockAreas); - - /** - * Wrapper function for DockAreas append, that ensures that dock area signals - * are properly connected to dock container slots - */ - void appendDockAreas(const QList NewDockAreas); - - /** - * Save state of child nodes - */ - void saveChildNodesState(QXmlStreamWriter& Stream, QWidget* Widget); - - /** - * Restore state of child nodes. - * \param[in] Stream The data stream that contains the serialized state - * \param[out] CreatedWidget The widget created from parsed data or 0 if - * the parsed widget was an empty splitter - * \param[in] Testing If Testing is true, only the stream data is - * parsed without modifiying anything. - */ - bool restoreChildNodes(CDockingStateReader& Stream, QWidget*& CreatedWidget, - bool Testing); - - /** - * Restores a splitter. - * \see restoreChildNodes() for details - */ - bool restoreSplitter(CDockingStateReader& Stream, QWidget*& CreatedWidget, - bool Testing); - - /** - * Restores a dock area. - * \see restoreChildNodes() for details - */ - bool restoreDockArea(CDockingStateReader& Stream, QWidget*& CreatedWidget, - bool Testing); - - /** - * Helper function for recursive dumping of layout - */ - void dumpRecursive(int level, QWidget* widget); - - /** - * Calculate the drop mode from the given target position - */ - eDropMode getDropMode(const QPoint& TargetPos); - - /** - * Initializes the visible dock area count variable if it is not initialized - * yet - */ - void initVisibleDockAreaCount() - { - if (VisibleDockAreaCount > -1) - { - return; - } - - VisibleDockAreaCount = 0; - for (auto DockArea : DockAreas) - { - VisibleDockAreaCount += DockArea->isHidden() ? 0 : 1; - } - } - - /** - * Access function for the visible dock area counter - */ - int& visibleDockAreaCount() - { - // Lazy initialisation - we initialize the VisibleDockAreaCount variable - // on first use - initVisibleDockAreaCount(); - return VisibleDockAreaCount; - } - - /** - * The visible dock area count changes, if dock areas are remove, added or - * when its view is toggled - */ - void onVisibleDockAreaCountChanged(); - - void emitDockAreasRemoved() - { - onVisibleDockAreaCountChanged(); - emit _this->dockAreasRemoved(); - } - - void emitDockAreasAdded() - { - onVisibleDockAreaCountChanged(); - emit _this->dockAreasAdded(); - } - - /** - * Helper function for creation of new splitter - */ - CDockSplitter* newSplitter(Qt::Orientation orientation, QWidget* parent = nullptr) - { - CDockSplitter* s = new CDockSplitter(orientation, parent); - s->setOpaqueResize(CDockManager::configFlags().testFlag(CDockManager::OpaqueSplitterResize)); - s->setChildrenCollapsible(false); - return s; - } - - -// private slots: ------------------------------------------------------------ - void onDockAreaViewToggled(bool Visible) - { - CDockAreaWidget* DockArea = qobject_cast(_this->sender()); - VisibleDockAreaCount += Visible ? 1 : -1; - onVisibleDockAreaCountChanged(); - emit _this->dockAreaViewToggled(DockArea, Visible); - } -}; // struct DockContainerWidgetPrivate - - -//============================================================================ -DockContainerWidgetPrivate::DockContainerWidgetPrivate(CDockContainerWidget* _public) : - _this(_public) -{ - std::fill(std::begin(LastAddedAreaCache),std::end(LastAddedAreaCache), nullptr); -} - - -//============================================================================ -eDropMode DockContainerWidgetPrivate::getDropMode(const QPoint& TargetPos) -{ - CDockAreaWidget* DockArea = _this->dockAreaAt(TargetPos); - auto dropArea = InvalidDockWidgetArea; - auto ContainerDropArea = DockManager->containerOverlay()->dropAreaUnderCursor(); - - if (DockArea) - { - auto dropOverlay = DockManager->dockAreaOverlay(); - dropOverlay->setAllowedAreas(AllDockAreas); - dropArea = dropOverlay->showOverlay(DockArea); - if (ContainerDropArea != InvalidDockWidgetArea && - ContainerDropArea != dropArea) - { - dropArea = InvalidDockWidgetArea; - } - - if (dropArea != InvalidDockWidgetArea) - { - ADS_PRINT("Dock Area Drop Content: " << dropArea); - return DropModeIntoArea; - } - } - - // mouse is over container - if (InvalidDockWidgetArea == dropArea) - { - dropArea = ContainerDropArea; - ADS_PRINT("Container Drop Content: " << dropArea); - if (dropArea != InvalidDockWidgetArea) - { - return DropModeIntoContainer; - } - } - - return DropModeInvalid; -} - - -//============================================================================ -void DockContainerWidgetPrivate::onVisibleDockAreaCountChanged() -{ - auto TopLevelDockArea = _this->topLevelDockArea(); - - if (TopLevelDockArea) - { - this->TopLevelDockArea = TopLevelDockArea; - TopLevelDockArea->titleBarButton(TitleBarButtonUndock)->setVisible(false || !_this->isFloating()); - TopLevelDockArea->titleBarButton(TitleBarButtonClose)->setVisible(false || !_this->isFloating()); - } - else if (this->TopLevelDockArea) - { - this->TopLevelDockArea->titleBarButton(TitleBarButtonUndock)->setVisible(true); - this->TopLevelDockArea->titleBarButton(TitleBarButtonClose)->setVisible(true); - this->TopLevelDockArea = nullptr; - } -} - - -//============================================================================ -void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* FloatingWidget, - DockWidgetArea area) -{ - auto InsertParam = internal::dockAreaInsertParameters(area); - CDockContainerWidget* FloatingDockContainer = FloatingWidget->dockContainer(); - auto NewDockAreas = FloatingDockContainer->findChildren( - QString(), Qt::FindChildrenRecursively); - QSplitter* Splitter = RootSplitter; - - if (DockAreas.count() <= 1) - { - Splitter->setOrientation(InsertParam.orientation()); - } - else if (Splitter->orientation() != InsertParam.orientation()) - { - QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); - QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter); - NewSplitter->addWidget(Splitter); - Splitter = NewSplitter; - delete li; - } - - // Now we can insert the floating widget content into this container - auto FloatingSplitter = FloatingDockContainer->rootSplitter(); - 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()); - } - } - else - { - insertWidgetIntoSplitter(Splitter, FloatingSplitter, InsertParam.append()); - } - - RootSplitter = Splitter; - addDockAreasToList(NewDockAreas); - - // 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()) - { - Splitter->show(); - } - _this->dumpLayout(); -} - - -//============================================================================ -void DockContainerWidgetPrivate::dropIntoCenterOfSection( - CFloatingDockContainer* FloatingWidget, CDockAreaWidget* TargetArea) -{ - CDockContainerWidget* FloatingContainer = FloatingWidget->dockContainer(); - auto NewDockWidgets = FloatingContainer->dockWidgets(); - auto TopLevelDockArea = FloatingContainer->topLevelDockArea(); - int NewCurrentIndex = -1; - - // 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) - { - NewCurrentIndex = TopLevelDockArea->currentIndex(); - } - - for (int i = 0; i < NewDockWidgets.count(); ++i) - { - CDockWidget* DockWidget = NewDockWidgets[i]; - TargetArea->insertDockWidget(i, DockWidget, false); - // 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()) - { - NewCurrentIndex = i; - } - } - TargetArea->setCurrentIndex(NewCurrentIndex); - TargetArea->updateTitleBarVisibility(); - return; -} - - -//============================================================================ -void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* FloatingWidget, - CDockAreaWidget* TargetArea, DockWidgetArea area) -{ - // Dropping into center means all dock widgets in the dropped floating - // widget will become tabs of the drop area - if (CenterDockWidgetArea == area) - { - dropIntoCenterOfSection(FloatingWidget, TargetArea); - return; - } - - auto InsertParam = internal::dockAreaInsertParameters(area); - auto NewDockAreas = FloatingWidget->dockContainer()->findChildren( - QString(), Qt::FindChildrenRecursively); - QSplitter* TargetAreaSplitter = internal::findParent(TargetArea); - - if (!TargetAreaSplitter) - { - QSplitter* Splitter = newSplitter(InsertParam.orientation()); - Layout->replaceWidget(TargetArea, Splitter); - Splitter->addWidget(TargetArea); - TargetAreaSplitter = Splitter; - } - int AreaIndex = TargetAreaSplitter->indexOf(TargetArea); - auto Widget = FloatingWidget->dockContainer()->findChild(QString(), Qt::FindDirectChildrenOnly); - auto FloatingSplitter = qobject_cast(Widget); - - if (TargetAreaSplitter->orientation() == InsertParam.orientation()) - { - auto Sizes = TargetAreaSplitter->sizes(); - int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height(); - bool AdjustSplitterSizes = true; - if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1) - { - TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), Widget); - } - else - { - AdjustSplitterSizes = (FloatingSplitter->count() == 1); - int InsertIndex = AreaIndex + InsertParam.insertOffset(); - while (FloatingSplitter->count()) - { - TargetAreaSplitter->insertWidget(InsertIndex++, FloatingSplitter->widget(0)); - } - } - - if (AdjustSplitterSizes) - { - int Size = (TargetAreaSize - TargetAreaSplitter->handleWidth()) / 2; - Sizes[AreaIndex] = Size; - Sizes.insert(AreaIndex, Size); - TargetAreaSplitter->setSizes(Sizes); - } - } - else - { - QList NewSplitterSizes; - QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); - int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height(); - bool AdjustSplitterSizes = true; - if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1) - { - NewSplitter->addWidget(Widget); - } - else - { - AdjustSplitterSizes = (FloatingSplitter->count() == 1); - while (FloatingSplitter->count()) - { - NewSplitter->addWidget(FloatingSplitter->widget(0)); - } - } - - // Save the sizes before insertion and restore it later to prevent - // shrinking of existing area - auto Sizes = TargetAreaSplitter->sizes(); - insertWidgetIntoSplitter(NewSplitter, TargetArea, !InsertParam.append()); - if (AdjustSplitterSizes) - { - int Size = TargetAreaSize / 2; - NewSplitter->setSizes({Size, Size}); - } - TargetAreaSplitter->insertWidget(AreaIndex, NewSplitter); - TargetAreaSplitter->setSizes(Sizes); - } - - addDockAreasToList(NewDockAreas); - _this->dumpLayout(); -} - - -//============================================================================ -void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea) -{ - auto DroppedDockWidget = qobject_cast(Widget); - auto DroppedArea = qobject_cast(Widget); - - if (DroppedDockWidget) - { - CDockAreaWidget* OldDockArea = DroppedDockWidget->dockAreaWidget(); - if (OldDockArea) - { - OldDockArea->removeDockWidget(DroppedDockWidget); - } - TargetArea->insertDockWidget(0, DroppedDockWidget, true); - } - else - { - QList NewDockWidgets = DroppedArea->dockWidgets(); - int NewCurrentIndex = DroppedArea->currentIndex(); - for (int i = 0; i < NewDockWidgets.count(); ++i) - { - CDockWidget* DockWidget = NewDockWidgets[i]; - TargetArea->insertDockWidget(i, DockWidget, false); - } - TargetArea->setCurrentIndex(NewCurrentIndex); - DroppedArea->dockContainer()->removeDockArea(DroppedArea); - DroppedArea->deleteLater(); - } - - TargetArea->updateTitleBarVisibility(); - return; -} - - -//============================================================================ -void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidget* TargetArea, DockWidgetArea area) -{ - // Dropping into center means all dock widgets in the dropped floating - // widget will become tabs of the drop area - if (CenterDockWidgetArea == area) - { - moveIntoCenterOfSection(Widget, TargetArea); - return; - } - - - CDockWidget* DroppedDockWidget = qobject_cast(Widget); - CDockAreaWidget* DroppedDockArea = qobject_cast(Widget); - CDockAreaWidget* NewDockArea; - if (DroppedDockWidget) - { - NewDockArea = new CDockAreaWidget(DockManager, _this); - CDockAreaWidget* OldDockArea = DroppedDockWidget->dockAreaWidget(); - if (OldDockArea) - { - OldDockArea->removeDockWidget(DroppedDockWidget); - } - NewDockArea->addDockWidget(DroppedDockWidget); - } - else - { - DroppedDockArea->dockContainer()->removeDockArea(DroppedDockArea); - NewDockArea = DroppedDockArea; - } - - auto InsertParam = internal::dockAreaInsertParameters(area); - QSplitter* TargetAreaSplitter = internal::findParent(TargetArea); - int AreaIndex = TargetAreaSplitter->indexOf(TargetArea); - auto Sizes = TargetAreaSplitter->sizes(); - if (TargetAreaSplitter->orientation() == InsertParam.orientation()) - { - int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height(); - TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), NewDockArea); - int Size = (TargetAreaSize - TargetAreaSplitter->handleWidth()) / 2; - Sizes[AreaIndex] = Size; - Sizes.insert(AreaIndex, Size); - } - else - { - auto Sizes = TargetAreaSplitter->sizes(); - int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height(); - QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); - NewSplitter->addWidget(TargetArea); - insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append()); - int Size = TargetAreaSize / 2; - NewSplitter->setSizes({Size, Size}); - TargetAreaSplitter->insertWidget(AreaIndex, NewSplitter); - } - TargetAreaSplitter->setSizes(Sizes); - - addDockAreasToList({NewDockArea}); -} - - -//============================================================================ -void DockContainerWidgetPrivate::moveToContainer(QWidget* Widget, DockWidgetArea area) -{ - CDockWidget* DroppedDockWidget = qobject_cast(Widget); - CDockAreaWidget* DroppedDockArea = qobject_cast(Widget); - CDockAreaWidget* NewDockArea; - - if (DroppedDockWidget) - { - NewDockArea = new CDockAreaWidget(DockManager, _this); - CDockAreaWidget* OldDockArea = DroppedDockWidget->dockAreaWidget(); - if (OldDockArea) - { - OldDockArea->removeDockWidget(DroppedDockWidget); - } - NewDockArea->addDockWidget(DroppedDockWidget); - } - else - { - DroppedDockArea->dockContainer()->removeDockArea(DroppedDockArea); - NewDockArea = DroppedDockArea; - } - - addDockArea(NewDockArea, area); - LastAddedAreaCache[areaIdToIndex(area)] = NewDockArea; -} - - -//============================================================================ -void DockContainerWidgetPrivate::addDockAreasToList(const QList NewDockAreas) -{ - int CountBefore = DockAreas.count(); - 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 - // likely hidden. We need to ensure, that it is visible - for (auto DockArea : NewDockAreas) - { - DockArea->titleBarButton(TitleBarButtonUndock)->setVisible(true); - DockArea->titleBarButton(TitleBarButtonClose)->setVisible(true); - } - - // 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) - { - DockAreas.at(0)->updateTitleBarVisibility(); - } - - if (1 == NewAreaCount) - { - DockAreas.last()->updateTitleBarVisibility(); - } - - emitDockAreasAdded(); -} - - -//============================================================================ -void DockContainerWidgetPrivate::appendDockAreas(const QList NewDockAreas) -{ - DockAreas.append(NewDockAreas); - for (auto DockArea : NewDockAreas) - { - QObject::connect(DockArea, - &CDockAreaWidget::viewToggled, - _this, - std::bind(&DockContainerWidgetPrivate::onDockAreaViewToggled, this, std::placeholders::_1)); - } -} - - -//============================================================================ -void DockContainerWidgetPrivate::saveChildNodesState(QXmlStreamWriter& s, QWidget* Widget) -{ - QSplitter* Splitter = dynamic_cast(Widget); - if (Splitter) - { - s.writeStartElement("Splitter"); - s.writeAttribute("Orientation", (Splitter->orientation() == Qt::Horizontal) ? "|" : "-"); - s.writeAttribute("Count", QString::number(Splitter->count())); - ADS_PRINT("NodeSplitter orient: " << Splitter->orientation() - << " WidgetCont: " << Splitter->count()); - for (int i = 0; i < Splitter->count(); ++i) - { - saveChildNodesState(s, Splitter->widget(i)); - } - - s.writeStartElement("Sizes"); - for (auto Size : Splitter->sizes()) - { - s.writeCharacters(QString::number(Size) + " "); - } - s.writeEndElement(); - s.writeEndElement(); - } - else - { - CDockAreaWidget* DockArea = dynamic_cast(Widget); - if (DockArea) - { - DockArea->saveState(s); - } - } -} - - -//============================================================================ -bool DockContainerWidgetPrivate::restoreSplitter(CDockingStateReader& s, - QWidget*& CreatedWidget, bool Testing) -{ - bool Ok; - QString OrientationStr = s.attributes().value("Orientation").toString(); - - // Check if the orientation string is right - if (!OrientationStr.startsWith("|") && !OrientationStr.startsWith("-")) - { - return false; - } - - // The "|" shall indicate a vertical splitter handle which in turn means - // a Horizontal orientation of the splitter layout. - bool HorizontalSplitter = OrientationStr.startsWith("|"); - // In version 0 we had a small bug. The "|" indicated a vertical orientation, - // but this is wrong, because only the splitter handle is vertical, the - // layout of the splitter is a horizontal layout. We fix this here - if (s.fileVersion() == 0) - { - HorizontalSplitter = !HorizontalSplitter; - } - - int Orientation = HorizontalSplitter ? Qt::Horizontal : Qt::Vertical; - int WidgetCount = s.attributes().value("Count").toInt(&Ok); - if (!Ok) - { - return false; - } - ADS_PRINT("Restore NodeSplitter Orientation: " << Orientation << - " WidgetCount: " << WidgetCount); - QSplitter* Splitter = nullptr; - if (!Testing) - { - Splitter = newSplitter(static_cast(Orientation)); - } - bool Visible = false; - QList Sizes; - while (s.readNextStartElement()) - { - QWidget* ChildNode = nullptr; - bool Result = true; - if (s.name().toString() == "Splitter") - { - Result = restoreSplitter(s, ChildNode, Testing); - } - else if (s.name().toString() == "Area") - { - Result = restoreDockArea(s, ChildNode, Testing); - } - else if (s.name().toString() == "Sizes") - { - QString sSizes = s.readElementText().trimmed(); - ADS_PRINT("Sizes: " << sSizes); - QTextStream TextStream(&sSizes); - while (!TextStream.atEnd()) - { - int value; - TextStream >> value; - Sizes.append(value); - } - } - else - { - s.skipCurrentElement(); - } - - if (!Result) - { - return false; - } - - if (Testing || !ChildNode) - { - continue; - } - - ADS_PRINT("ChildNode isVisible " << ChildNode->isVisible() - << " isVisibleTo " << ChildNode->isVisibleTo(Splitter)); - Splitter->addWidget(ChildNode); - Visible |= ChildNode->isVisibleTo(Splitter); - } - - if (Sizes.count() != WidgetCount) - { - return false; - } - - if (!Testing) - { - if (!Splitter->count()) - { - delete Splitter; - Splitter = nullptr; - } - else - { - Splitter->setSizes(Sizes); - Splitter->setVisible(Visible); - } - CreatedWidget = Splitter; - } - else - { - CreatedWidget = nullptr; - } - - return true; -} - - -//============================================================================ -bool DockContainerWidgetPrivate::restoreDockArea(CDockingStateReader& s, - QWidget*& CreatedWidget, bool Testing) -{ - bool Ok; -#ifdef ADS_DEBUG_PRINT - int Tabs = s.attributes().value("Tabs").toInt(&Ok); - if (!Ok) - { - return false; - } -#endif - - QString CurrentDockWidget = s.attributes().value("Current").toString(); - ADS_PRINT("Restore NodeDockArea Tabs: " << Tabs << " Current: " - << CurrentDockWidget); - - CDockAreaWidget* DockArea = nullptr; - if (!Testing) - { - DockArea = new CDockAreaWidget(DockManager, _this); - } - - while (s.readNextStartElement()) - { - if (s.name().toString() != "Widget") - { - continue; - } - - auto ObjectName = s.attributes().value("Name"); - if (ObjectName.isEmpty()) - { - return false; - } - - bool Closed = s.attributes().value("Closed").toInt(&Ok); - if (!Ok) - { - return false; - } - - s.skipCurrentElement(); - CDockWidget* DockWidget = DockManager->findDockWidget(ObjectName.toString()); - if (!DockWidget || Testing) - { - continue; - } - - ADS_PRINT("Dock Widget found - parent " << DockWidget->parent()); - // We hide the DockArea here to prevent the short display (the flashing) - // of the dock areas during application startup - DockArea->hide(); - DockArea->addDockWidget(DockWidget); - DockWidget->setToggleViewActionChecked(!Closed); - DockWidget->setClosedState(Closed); - DockWidget->setProperty(internal::ClosedProperty, Closed); - DockWidget->setProperty(internal::DirtyProperty, false); - } - - if (Testing) - { - return true; - } - - if (!DockArea->dockWidgetsCount()) - { - delete DockArea; - DockArea = nullptr; - } - else - { - DockArea->setProperty("currentDockWidget", CurrentDockWidget); - appendDockAreas({DockArea}); - } - - CreatedWidget = DockArea; - return true; -} - - -//============================================================================ -bool DockContainerWidgetPrivate::restoreChildNodes(CDockingStateReader& s, - QWidget*& CreatedWidget, bool Testing) -{ - bool Result = true; - while (s.readNextStartElement()) - { - if (s.name().toString() == "Splitter") - { - Result = restoreSplitter(s, CreatedWidget, Testing); - ADS_PRINT("Splitter"); - } - else if (s.name().toString() == "Area") - { - Result = restoreDockArea(s, CreatedWidget, Testing); - ADS_PRINT("DockAreaWidget"); - } - else - { - s.skipCurrentElement(); - ADS_PRINT("Unknown element"); - } - } - - return Result; -} - - -//============================================================================ -CDockAreaWidget* DockContainerWidgetPrivate::dockWidgetIntoContainer(DockWidgetArea area, - CDockWidget* Dockwidget) -{ - CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this); - NewDockArea->addDockWidget(Dockwidget); - addDockArea(NewDockArea, area); - NewDockArea->updateTitleBarVisibility(); - LastAddedAreaCache[areaIdToIndex(area)] = NewDockArea; - return NewDockArea; -} - - -//============================================================================ -void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockWidgetArea area) -{ - auto InsertParam = internal::dockAreaInsertParameters(area); - // As long as we have only one dock area in the splitter we can adjust - // its orientation - if (DockAreas.count() <= 1) - { - RootSplitter->setOrientation(InsertParam.orientation()); - } - - QSplitter* Splitter = RootSplitter; - if (Splitter->orientation() == InsertParam.orientation()) - { - insertWidgetIntoSplitter(Splitter, NewDockArea, InsertParam.append()); - } - else - { - QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); - if (InsertParam.append()) - { - QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter); - NewSplitter->addWidget(Splitter); - NewSplitter->addWidget(NewDockArea); - delete li; - } - else - { - NewSplitter->addWidget(NewDockArea); - QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter); - NewSplitter->addWidget(Splitter); - delete li; - } - RootSplitter = NewSplitter; - } - - addDockAreasToList({NewDockArea}); -} - - -//============================================================================ -void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget) -{ -#if defined(QT_DEBUG) - QSplitter* Splitter = dynamic_cast(widget); - QByteArray buf; - buf.fill(' ', level * 4); - if (Splitter) - { -#ifdef ADS_DEBUG_PRINT - qDebug("%sSplitter %s v: %s c: %s", - (const char*)buf, - (Splitter->orientation() == Qt::Vertical) ? "--" : "|", - Splitter->isHidden() ? " " : "v", - QString::number(Splitter->count()).toStdString().c_str()); - std::cout << (const char*)buf << "Splitter " - << ((Splitter->orientation() == Qt::Vertical) ? "--" : "|") << " " - << (Splitter->isHidden() ? " " : "v") << " " - << QString::number(Splitter->count()).toStdString() << std::endl; -#endif - for (int i = 0; i < Splitter->count(); ++i) - { - dumpRecursive(level + 1, Splitter->widget(i)); - } - } - else - { - CDockAreaWidget* DockArea = dynamic_cast(widget); - if (!DockArea) - { - return; - } -#ifdef ADS_DEBUG_PRINT - qDebug("%sDockArea", (const char*)buf); - std::cout << (const char*)buf - << (DockArea->isHidden() ? " " : "v") - << (DockArea->openDockWidgetsCount() > 0 ? " " : "c") - << " DockArea" << std::endl; - buf.fill(' ', (level + 1) * 4); - for (int i = 0; i < DockArea->dockWidgetsCount(); ++i) - { - std::cout << (const char*)buf << (i == DockArea->currentIndex() ? "*" : " "); - CDockWidget* DockWidget = DockArea->dockWidget(i); - std::cout << (DockWidget->isHidden() ? " " : "v"); - std::cout << (DockWidget->isClosed() ? "c" : " ") << " "; - std::cout << DockWidget->windowTitle().toStdString() << std::endl; - } -#endif - } -#else - Q_UNUSED(level); - Q_UNUSED(widget); -#endif -} - - -//============================================================================ -CDockAreaWidget* DockContainerWidgetPrivate::dockWidgetIntoDockArea(DockWidgetArea area, - CDockWidget* Dockwidget, CDockAreaWidget* TargetDockArea) -{ - if (CenterDockWidgetArea == area) - { - TargetDockArea->addDockWidget(Dockwidget); - TargetDockArea->updateTitleBarVisibility(); - return TargetDockArea; - } - - CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this); - NewDockArea->addDockWidget(Dockwidget); - auto InsertParam = internal::dockAreaInsertParameters(area); - - QSplitter* TargetAreaSplitter = internal::findParent(TargetDockArea); - int index = TargetAreaSplitter ->indexOf(TargetDockArea); - if (TargetAreaSplitter->orientation() == InsertParam.orientation()) - { - ADS_PRINT("TargetAreaSplitter->orientation() == InsertParam.orientation()"); - TargetAreaSplitter->insertWidget(index + InsertParam.insertOffset(), NewDockArea); - } - else - { - ADS_PRINT("TargetAreaSplitter->orientation() != InsertParam.orientation()"); - QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); - NewSplitter->addWidget(TargetDockArea); - insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append()); - TargetAreaSplitter->insertWidget(index, NewSplitter); - } - - appendDockAreas({NewDockArea}); - emitDockAreasAdded(); - return NewDockArea; -} - - -//============================================================================ -CDockContainerWidget::CDockContainerWidget(CDockManager* DockManager, QWidget *parent) : - QFrame(parent), - d(new DockContainerWidgetPrivate(this)) -{ - d->DockManager = DockManager; - d->isFloating = floatingWidget() != nullptr; - - d->Layout = new QGridLayout(); - d->Layout->setContentsMargins(0, 1, 0, 1); - d->Layout->setSpacing(0); - setLayout(d->Layout); - - // The function d->newSplitter() accesses the config flags from dock - // manager which in turn requires a properly constructed dock manager. - // If this dock container is the dock manager, then it is not properly - // constructed yet because this base class constructor is called before - // the constructor of the DockManager private class - if (DockManager != this) - { - d->DockManager->registerDockContainer(this); - createRootSplitter(); - } -} - -//============================================================================ -CDockContainerWidget::~CDockContainerWidget() -{ - if (d->DockManager) - { - d->DockManager->removeDockContainer(this); - } - delete d; -} - - -//============================================================================ -CDockAreaWidget* CDockContainerWidget::addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget, - CDockAreaWidget* DockAreaWidget) -{ - CDockAreaWidget* OldDockArea = Dockwidget->dockAreaWidget(); - if (OldDockArea) - { - OldDockArea->removeDockWidget(Dockwidget); - } - - Dockwidget->setDockManager(d->DockManager); - if (DockAreaWidget) - { - return d->dockWidgetIntoDockArea(area, Dockwidget, DockAreaWidget); - } - else - { - return d->dockWidgetIntoContainer(area, Dockwidget); - } -} - -//============================================================================ -void CDockContainerWidget::removeDockWidget(CDockWidget* Dockwidget) -{ - CDockAreaWidget* Area = Dockwidget->dockAreaWidget(); - if (Area) - { - Area->removeDockWidget(Dockwidget); - } -} - -//============================================================================ -unsigned int CDockContainerWidget::zOrderIndex() const -{ - return d->zOrderIndex; -} - - -//============================================================================ -bool CDockContainerWidget::isInFrontOf(CDockContainerWidget* Other) const -{ - return this->zOrderIndex() > Other->zOrderIndex(); -} - - -//============================================================================ -bool CDockContainerWidget::event(QEvent *e) -{ - bool Result = QWidget::event(e); - if (e->type() == QEvent::WindowActivate) - { - d->zOrderIndex = ++zOrderCounter; - } - else if (e->type() == QEvent::Show && !d->zOrderIndex) - { - d->zOrderIndex = ++zOrderCounter; - } - - return Result; -} - - -//============================================================================ -void CDockContainerWidget::addDockArea(CDockAreaWidget* DockAreaWidget, - DockWidgetArea area) -{ - CDockContainerWidget* Container = DockAreaWidget->dockContainer(); - if (Container && Container != this) - { - Container->removeDockArea(DockAreaWidget); - } - - d->addDockArea(DockAreaWidget, area); -} - - -//============================================================================ -void CDockContainerWidget::removeDockArea(CDockAreaWidget* area) -{ - ADS_PRINT("CDockContainerWidget::removeDockArea"); - area->disconnect(this); - d->DockAreas.removeAll(area); - CDockSplitter* Splitter = internal::findParent(area); - - // Remove are from parent splitter and recursively hide tree of parent - // splitters if it has no visible content - area->setParent(nullptr); - internal::hideEmptyParentSplitters(Splitter); - - // Remove this area from cached areas - const auto& cache = d->LastAddedAreaCache; - if (auto p = std::find(cache, cache+sizeof(cache)/sizeof(cache[0]), area)) { - d->LastAddedAreaCache[std::distance(cache, p)] = nullptr; - } - - // If splitter has more than 1 widgets, we are finished and can leave - if (Splitter->count() > 1) - { - goto emitAndExit; - } - - // If this is the RootSplitter we need to remove empty splitters to - // avoid too many empty splitters - if (Splitter == d->RootSplitter) - { - ADS_PRINT("Removed from RootSplitter"); - // If splitter is empty, we are finished - if (!Splitter->count()) - { - Splitter->hide(); - goto emitAndExit; - } - - QWidget* widget = Splitter->widget(0); - QSplitter* ChildSplitter = dynamic_cast(widget); - // If the one and only content widget of the splitter is not a splitter - // then we are finished - if (!ChildSplitter) - { - goto emitAndExit; - } - - // We replace the superfluous RootSplitter with the ChildSplitter - ChildSplitter->setParent(nullptr); - QLayoutItem* li = d->Layout->replaceWidget(Splitter, ChildSplitter); - d->RootSplitter = ChildSplitter; - delete li; - ADS_PRINT("RootSplitter replaced by child splitter"); - } - else if (Splitter->count() == 1) - { - ADS_PRINT("Replacing splitter with content"); - QSplitter* ParentSplitter = internal::findParent(Splitter); - auto Sizes = ParentSplitter->sizes(); - QWidget* widget = Splitter->widget(0); - widget->setParent(this); - internal::replaceSplitterWidget(ParentSplitter, Splitter, widget); - ParentSplitter->setSizes(Sizes); - } - - delete Splitter; - -emitAndExit: - CDockWidget* TopLevelWidget = topLevelDockWidget(); - - // Updated the title bar visibility of the dock widget if there is only - // one single visible dock widget - CDockWidget::emitTopLevelEventForWidget(TopLevelWidget, true); - dumpLayout(); - d->emitDockAreasRemoved(); -} - - -//============================================================================ -CDockAreaWidget* CDockContainerWidget::dockAreaAt(const QPoint& GlobalPos) const -{ - for (const auto& DockArea : d->DockAreas) - { - if (DockArea->isVisible() && DockArea->rect().contains(DockArea->mapFromGlobal(GlobalPos))) - { - return DockArea; - } - } - - return nullptr; -} - - -//============================================================================ -CDockAreaWidget* CDockContainerWidget::dockArea(int Index) const -{ - return (Index < dockAreaCount()) ? d->DockAreas[Index] : nullptr; -} - - -//============================================================================ -bool CDockContainerWidget::isFloating() const -{ - return d->isFloating; -} - - -//============================================================================ -int CDockContainerWidget::dockAreaCount() const -{ - return d->DockAreas.count(); -} - - -//============================================================================ -int CDockContainerWidget::visibleDockAreaCount() const -{ - int Result = 0; - for (auto DockArea : d->DockAreas) - { - Result += DockArea->isHidden() ? 0 : 1; - } - - return Result; - - // TODO Cache or precalculate this to speed it up because it is used during - // movement of floating widget - //return d->visibleDockAreaCount(); -} - - -//============================================================================ -void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWidget, - const QPoint& TargetPos) -{ - ADS_PRINT("CDockContainerWidget::dropFloatingWidget"); - CDockWidget* SingleDroppedDockWidget = FloatingWidget->topLevelDockWidget(); - CDockWidget* SingleDockWidget = topLevelDockWidget(); - CDockAreaWidget* DockArea = dockAreaAt(TargetPos); - auto dropArea = InvalidDockWidgetArea; - auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor(); - bool Dropped = false; - - if (DockArea) - { - auto dropOverlay = d->DockManager->dockAreaOverlay(); - dropOverlay->setAllowedAreas(AllDockAreas); - dropArea = dropOverlay->showOverlay(DockArea); - if (ContainerDropArea != InvalidDockWidgetArea && - ContainerDropArea != dropArea) - { - dropArea = InvalidDockWidgetArea; - } - - if (dropArea != InvalidDockWidgetArea) - { - ADS_PRINT("Dock Area Drop Content: " << dropArea); - d->dropIntoSection(FloatingWidget, DockArea, dropArea); - Dropped = true; - } - } - - // mouse is over container - if (InvalidDockWidgetArea == dropArea) - { - dropArea = ContainerDropArea; - ADS_PRINT("Container Drop Content: " << dropArea); - if (dropArea != InvalidDockWidgetArea) - { - d->dropIntoContainer(FloatingWidget, dropArea); - Dropped = true; - } - } - - if (Dropped) - { - FloatingWidget->deleteLater(); - - // If we dropped a floating widget with only one single dock widget, then we - // drop a top level widget that changes from floating to docked now - CDockWidget::emitTopLevelEventForWidget(SingleDroppedDockWidget, false); - - // If there was a top level widget before the drop, then it is not top - // level widget anymore - CDockWidget::emitTopLevelEventForWidget(SingleDockWidget, false); - } -} - - -//============================================================================ -void CDockContainerWidget::dropWidget(QWidget* Widget, const QPoint& TargetPos) -{ - ADS_PRINT("CDockContainerWidget::dropFloatingWidget"); - CDockWidget* SingleDockWidget = topLevelDockWidget(); - CDockAreaWidget* DockArea = dockAreaAt(TargetPos); - auto dropArea = InvalidDockWidgetArea; - auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor(); - - if (DockArea) - { - auto dropOverlay = d->DockManager->dockAreaOverlay(); - dropOverlay->setAllowedAreas(AllDockAreas); - dropArea = dropOverlay->showOverlay(DockArea); - if (ContainerDropArea != InvalidDockWidgetArea && - ContainerDropArea != dropArea) - { - dropArea = InvalidDockWidgetArea; - } - - if (dropArea != InvalidDockWidgetArea) - { - ADS_PRINT("Dock Area Drop Content: " << dropArea); - d->moveToNewSection(Widget, DockArea, dropArea); - } - } - - // mouse is over container - if (InvalidDockWidgetArea == dropArea) - { - dropArea = ContainerDropArea; - ADS_PRINT("Container Drop Content: " << dropArea); - if (dropArea != InvalidDockWidgetArea) - { - d->moveToContainer(Widget, dropArea); - } - } - - // If there was a top level widget before the drop, then it is not top - // level widget anymore - CDockWidget::emitTopLevelEventForWidget(SingleDockWidget, false); -} - - -//============================================================================ -QList CDockContainerWidget::openedDockAreas() const -{ - QList Result; - for (auto DockArea : d->DockAreas) - { - if (!DockArea->isHidden()) - { - Result.append(DockArea); - } - } - - return Result; -} - - -//============================================================================ -void CDockContainerWidget::saveState(QXmlStreamWriter& s) const -{ - ADS_PRINT("CDockContainerWidget::saveState isFloating " - << isFloating()); - - s.writeStartElement("Container"); - s.writeAttribute("Floating", QString::number(isFloating() ? 1 : 0)); - if (isFloating()) - { - CFloatingDockContainer* FloatingWidget = floatingWidget(); - QByteArray Geometry = FloatingWidget->saveGeometry(); -#if QT_VERSION < 0x050900 - s.writeTextElement("Geometry", qByteArrayToHex(Geometry, ' ')); -#else - s.writeTextElement("Geometry", Geometry.toHex(' ')); -#endif - } - d->saveChildNodesState(s, d->RootSplitter); - s.writeEndElement(); -} - - -//============================================================================ -bool CDockContainerWidget::restoreState(CDockingStateReader& s, bool Testing) -{ - bool IsFloating = s.attributes().value("Floating").toInt(); - ADS_PRINT("Restore CDockContainerWidget Floating" << IsFloating); - - QWidget*NewRootSplitter {}; - if (!Testing) - { - d->VisibleDockAreaCount = -1;// invalidate the dock area count - d->DockAreas.clear(); - std::fill(std::begin(d->LastAddedAreaCache),std::end(d->LastAddedAreaCache), nullptr); - } - - if (IsFloating) - { - ADS_PRINT("Restore floating widget"); - if (!s.readNextStartElement() || s.name().toString() != "Geometry") - { - return false; - } - - QByteArray GeometryString = s.readElementText(CDockingStateReader::ErrorOnUnexpectedElement).toLocal8Bit(); - QByteArray Geometry = QByteArray::fromHex(GeometryString); - if (Geometry.isEmpty()) - { - return false; - } - - if (!Testing) - { - CFloatingDockContainer* FloatingWidget = floatingWidget(); - FloatingWidget->restoreGeometry(Geometry); - } - } - - if (!d->restoreChildNodes(s, NewRootSplitter, Testing)) - { - return false; - } - - 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) - { - NewRootSplitter = d->newSplitter(Qt::Horizontal); - } - - d->Layout->replaceWidget(d->RootSplitter, NewRootSplitter); - QSplitter* OldRoot = d->RootSplitter; - d->RootSplitter = dynamic_cast(NewRootSplitter); - OldRoot->deleteLater(); - - return true; -} - - -//============================================================================ -QSplitter* CDockContainerWidget::rootSplitter() const -{ - return d->RootSplitter; -} - - -//============================================================================ -void CDockContainerWidget::createRootSplitter() -{ - if (d->RootSplitter) - { - return; - } - d->RootSplitter = d->newSplitter(Qt::Horizontal); - d->Layout->addWidget(d->RootSplitter); -} - - -//============================================================================ -void CDockContainerWidget::dumpLayout() -{ -#if (ADS_DEBUG_LEVEL > 0) - qDebug("\n\nDumping layout --------------------------"); - std::cout << "\n\nDumping layout --------------------------" << std::endl; - d->dumpRecursive(0, d->RootSplitter); - qDebug("--------------------------\n\n"); - std::cout << "--------------------------\n\n" << std::endl; -#endif -} - - -//============================================================================ -CDockAreaWidget* CDockContainerWidget::lastAddedDockAreaWidget(DockWidgetArea area) const -{ - return d->LastAddedAreaCache[areaIdToIndex(area)]; -} - - -//============================================================================ -bool CDockContainerWidget::hasTopLevelDockWidget() const -{ - if (!isFloating()) - { - return false; - } - - auto DockAreas = openedDockAreas(); - if (DockAreas.count() != 1) - { - return false; - } - - return DockAreas[0]->openDockWidgetsCount() == 1; -} - - -//============================================================================ -CDockWidget* CDockContainerWidget::topLevelDockWidget() const -{ - auto TopLevelDockArea = topLevelDockArea(); - if (!TopLevelDockArea) - { - return nullptr; - } - - auto DockWidgets = TopLevelDockArea->openedDockWidgets(); - if (DockWidgets.count() != 1) - { - return nullptr; - } - - return DockWidgets[0]; - -} - - -//============================================================================ -CDockAreaWidget* CDockContainerWidget::topLevelDockArea() const -{ - if (!isFloating()) - { - return nullptr; - } - - auto DockAreas = openedDockAreas(); - if (DockAreas.count() != 1) - { - return nullptr; - } - - return DockAreas[0]; -} - - -//============================================================================ -QList CDockContainerWidget::dockWidgets() const -{ - QList Result; - for (const auto DockArea : d->DockAreas) - { - Result.append(DockArea->dockWidgets()); - } - - return Result; -} - - -//============================================================================ -CDockWidget::DockWidgetFeatures CDockContainerWidget::features() const -{ - CDockWidget::DockWidgetFeatures Features(CDockWidget::AllDockWidgetFeatures); - for (const auto DockArea : d->DockAreas) - { - Features &= DockArea->features(); - } - - return Features; -} - - -//============================================================================ -CFloatingDockContainer* CDockContainerWidget::floatingWidget() const -{ - return internal::findParent(this); -} - - -//============================================================================ -void CDockContainerWidget::closeOtherAreas(CDockAreaWidget* KeepOpenArea) -{ - for (const auto DockArea : d->DockAreas) - { - if (DockArea == KeepOpenArea) - { - continue; - } - - if (!DockArea->features(BitwiseAnd).testFlag(CDockWidget::DockWidgetClosable)) - { - continue; - } - - // We do not close areas with widgets with custom close handling - if (DockArea->features(BitwiseOr).testFlag(CDockWidget::CustomCloseHandling)) - { - continue; - } - - DockArea->closeArea(); - } -} - - -} // namespace ads - -//--------------------------------------------------------------------------- -// EOF DockContainerWidget.cpp diff --git a/src/ui/AdvDock/DockContainerWidget.h b/src/ui/AdvDock/DockContainerWidget.h deleted file mode 100644 index 4fbc45a5..00000000 --- a/src/ui/AdvDock/DockContainerWidget.h +++ /dev/null @@ -1,278 +0,0 @@ -#ifndef DockContainerWidgetH -#define DockContainerWidgetH -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockContainerWidget.h -/// \author Uwe Kindler -/// \date 24.02.2017 -/// \brief Declaration of CDockContainerWidget class -//============================================================================ - - -//============================================================================ -// INCLUDES -//============================================================================ -#include - -#include "DockWidget.h" - -class QXmlStreamWriter; - - -namespace ads -{ -class DockContainerWidgetPrivate; -class CDockAreaWidget; -class CDockWidget; -class CDockManager; -struct DockManagerPrivate; -class CFloatingDockContainer; -struct FloatingDockContainerPrivate; -class CFloatingDragPreview; -struct FloatingDragPreviewPrivate; -class CDockingStateReader; - -/** - * Container that manages a number of dock areas with single dock widgets - * or tabyfied dock widgets in each area. - * Each window that support docking has a DockContainerWidget. That means - * the main application window and all floating windows are ore contain - * an DockContainerWidget. - */ -class CDockContainerWidget : public QFrame -{ - Q_OBJECT -private: - DockContainerWidgetPrivate* d; ///< private data (pimpl) - friend class DockContainerWidgetPrivate; - friend class CDockManager; - friend struct DockManagerPrivate; - friend class CDockAreaWidget; - friend struct DockAreaWidgetPrivate; - friend class CFloatingDockContainer; - friend struct FloatingDockContainerPrivate; - friend class CDockWidget; - friend class CFloatingDragPreview; - friend struct FloatingDragPreviewPrivate; - -protected: - /** - * Handles activation events to update zOrderIndex - */ - virtual bool event(QEvent *e) override; - - /** - * Access function for the internal root splitter - */ - QSplitter* rootSplitter() const; - - /** - * Helper function for creation of the root splitter - */ - void createRootSplitter(); - - /** - * Drop floating widget into the container - */ - void dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos); - - /** - * Drop a dock area or a dock widget given in widget parameter - */ - void dropWidget(QWidget* Widget, const QPoint& TargetPos); - - /** - * Adds the given dock area to this container widget - */ - void addDockArea(CDockAreaWidget* DockAreaWidget, DockWidgetArea area = CenterDockWidgetArea); - - /** - * Removes the given dock area from this container - */ - void removeDockArea(CDockAreaWidget* area); - - /** - * Saves the state into the given stream - */ - void saveState(QXmlStreamWriter& Stream) const; - - /** - * Restores the state from given stream. - * If Testing is true, the function only parses the data from the given - * stream but does not restore anything. You can use this check for - * faulty files before you start restoring the state - */ - bool restoreState(CDockingStateReader& Stream, bool Testing); - - /** - * This function returns the last added dock area widget for the given - * area identifier or 0 if no dock area widget has been added for the given - * area - */ - CDockAreaWidget* lastAddedDockAreaWidget(DockWidgetArea area) const; - - /** - * This function returns true if this dock area has only one single - * visible dock widget. - * A top level widget is a real floating widget. Only the isFloating() - * function of top level widgets may returns true. - */ - bool hasTopLevelDockWidget() const; - - /** - * If hasSingleVisibleDockWidget() returns true, this function returns the - * one and only visible dock widget. Otherwise it returns a nullptr. - */ - CDockWidget* topLevelDockWidget() const; - - /** - * Returns the top level dock area. - */ - CDockAreaWidget* topLevelDockArea() const; - - /** - * This function returns a list of all dock widgets in this floating widget. - * It may be possible, depending on the implementation, that dock widgets, - * that are not visible to the user have no parent widget. Therefore simply - * calling findChildren() would not work here. Therefore this function - * iterates over all dock areas and creates a list that contains all - * dock widgets returned from all dock areas. - */ - QList dockWidgets() const; - -public: - /** - * Default Constructor - */ - CDockContainerWidget(CDockManager* DockManager, QWidget* parent = 0); - - /** - * Virtual Destructor - */ - virtual ~CDockContainerWidget(); - - /** - * Adds dockwidget into the given area. - * If DockAreaWidget is not null, then the area parameter indicates the area - * into the DockAreaWidget. If DockAreaWidget is null, the Dockwidget will - * be dropped into the container. - * \return Returns the dock area widget that contains the new DockWidget - */ - CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget, - CDockAreaWidget* DockAreaWidget = nullptr); - - /** - * Removes dockwidget - */ - void removeDockWidget(CDockWidget* Dockwidget); - - /** - * Returns the current zOrderIndex - */ - virtual unsigned int zOrderIndex() const; - - /** - * This function returns true if this container widgets z order index is - * higher than the index of the container widget given in Other parameter - */ - bool isInFrontOf(CDockContainerWidget* Other) const; - - /** - * Returns the dock area at teh given global position or 0 if there is no - * dock area at this position - */ - CDockAreaWidget* dockAreaAt(const QPoint& GlobalPos) const; - - /** - * Returns the dock area at the given Index or 0 if the index is out of - * range - */ - CDockAreaWidget* dockArea(int Index) const; - - /** - * Returns the list of dock areas that are not closed - * If all dock widgets in a dock area are closed, the dock area will be closed - */ - QList openedDockAreas() const; - - /** - * Returns the number of dock areas in this container - */ - int dockAreaCount() const; - - /** - * Returns the number of visible dock areas - */ - int visibleDockAreaCount() const; - - /** - * This function returns true, if this container is in a floating widget - */ - bool isFloating() const; - - /** - * Dumps the layout for debugging purposes - */ - void dumpLayout(); - - /** - * This functions returns the dock widget features of all dock widget in - * this container. - * A bitwise and is used to combine the flags of all dock widgets. That - * means, if only dock widget does not support a certain flag, the whole - * dock are does not support the flag. - */ - CDockWidget::DockWidgetFeatures features() const; - - /** - * If this dock container is in a floating widget, this function returns - * the floating widget. - * Else, it returns a nullptr. - */ - CFloatingDockContainer* floatingWidget() const; - - /** - * Call this function to close all dock areas except the KeepOpenArea - */ - void closeOtherAreas(CDockAreaWidget* KeepOpenArea); - -signals: - /** - * This signal is emitted if one or multiple dock areas has been added to - * the internal list of dock areas. - * If multiple dock areas are inserted, this signal is emitted only once - */ - void dockAreasAdded(); - - /** - * This signal is emitted if one or multiple dock areas has been removed - */ - void dockAreasRemoved(); - - /** - * This signal is emitted if a dock area is opened or closed via - * toggleView() function - */ - void dockAreaViewToggled(CDockAreaWidget* DockArea, bool Open); -}; // class DockContainerWidget -} // namespace ads -//----------------------------------------------------------------------------- -#endif // DockContainerWidgetH diff --git a/src/ui/AdvDock/DockManager.cpp b/src/ui/AdvDock/DockManager.cpp deleted file mode 100644 index 50df2bbb..00000000 --- a/src/ui/AdvDock/DockManager.cpp +++ /dev/null @@ -1,852 +0,0 @@ -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockManager.cpp -/// \author Uwe Kindler -/// \date 26.02.2017 -/// \brief Implementation of CDockManager class -//============================================================================ - - -//============================================================================ -// INCLUDES -//============================================================================ -#include "DockWidgetTab.h" -#include "DockManager.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "FloatingDockContainer.h" -#include "DockOverlay.h" -#include "DockWidget.h" -#include "ads_globals.h" -#include "DockAreaWidget.h" -#include "IconProvider.h" -#include "DockingStateReader.h" - - - -namespace ads -{ -static CDockManager::ConfigFlags StaticConfigFlags = CDockManager::DefaultConfig; - -/** - * Private data class of CDockManager class (pimpl) - */ -struct DockManagerPrivate -{ - CDockManager* _this; - QList FloatingWidgets; - QList Containers; - CDockOverlay* ContainerOverlay; - CDockOverlay* DockAreaOverlay; - QMap DockWidgetsMap; - QMap Perspectives; - QMap ViewMenuGroups; - QMenu* ViewMenu; - CDockManager::eViewMenuInsertionOrder MenuInsertionOrder = CDockManager::MenuAlphabeticallySorted; - bool RestoringState = false; - QVector UninitializedFloatingWidgets; - - /** - * Private data constructor - */ - DockManagerPrivate(CDockManager* _public); - - /** - * Checks if the given data stream is a valid docking system state - * file. - */ - bool checkFormat(const QByteArray &state, int version); - - /** - * Restores the state - */ - bool restoreStateFromXml(const QByteArray &state, int version, bool Testing = internal::Restore); - - /** - * Restore state - */ - bool restoreState(const QByteArray &state, int version); - - void restoreDockWidgetsOpenState(); - void restoreDockAreasIndices(); - void emitTopLevelEvents(); - - void hideFloatingWidgets() - { - // Hide updates of floating widgets from user - for (auto FloatingWidget : FloatingWidgets) - { - FloatingWidget->hide(); - } - } - - void markDockWidgetsDirty() - { - for (auto DockWidget : DockWidgetsMap) - { - DockWidget->setProperty("dirty", true); - } - } - - /** - * Restores the container with the given index - */ - bool restoreContainer(int Index, CDockingStateReader& stream, bool Testing); - - /** - * Loads the stylesheet - */ - void loadStylesheet(); - - /** - * Adds action to menu - optionally in sorted order - */ - void addActionToMenu(QAction* Action, QMenu* Menu, bool InsertSorted); -}; -// struct DockManagerPrivate - -//============================================================================ -DockManagerPrivate::DockManagerPrivate(CDockManager* _public) : - _this(_public) -{ - -} - - -//============================================================================ -void DockManagerPrivate::loadStylesheet() -{ - QString Result; -#ifdef Q_OS_LINUX - QFile StyleSheetFile(":ads/stylesheets/default_linux.css"); -#else - QFile StyleSheetFile(":ads/stylesheets/default.css"); -#endif - StyleSheetFile.open(QIODevice::ReadOnly); - QTextStream StyleSheetStream(&StyleSheetFile); - Result = StyleSheetStream.readAll(); - StyleSheetFile.close(); - _this->setStyleSheet(Result); -} - - -//============================================================================ -bool DockManagerPrivate::restoreContainer(int Index, CDockingStateReader& stream, bool Testing) -{ - if (Testing) - { - Index = 0; - } - - bool Result = false; - if (Index >= Containers.count()) - { - CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this); - Result = FloatingWidget->restoreState(stream, Testing); - } - else - { - ADS_PRINT("d->Containers[i]->restoreState "); - auto Container = Containers[Index]; - if (Container->isFloating()) - { - Result = Container->floatingWidget()->restoreState(stream, Testing); - } - else - { - Result = Container->restoreState(stream, Testing); - } - } - - return Result; -} - - -//============================================================================ -bool DockManagerPrivate::checkFormat(const QByteArray &state, int version) -{ - return restoreStateFromXml(state, version, internal::RestoreTesting); -} - - -//============================================================================ -bool DockManagerPrivate::restoreStateFromXml(const QByteArray &state, int version, - bool Testing) -{ - Q_UNUSED(version); - - if (state.isEmpty()) - { - return false; - } - CDockingStateReader s(state); - s.readNextStartElement(); - if (s.name().toString() != "QtAdvancedDockingSystem") - { - return false; - } - ADS_PRINT(s.attributes().value("Version")); - bool ok; - int v = s.attributes().value("Version").toInt(&ok); - if (!ok || v > CurrentVersion) - { - return false; - } - - s.setFileVersion(v); - bool Result = true; -#ifdef ADS_DEBUG_PRINT - int DockContainers = s.attributes().value("Containers").toInt(); -#endif - ADS_PRINT(DockContainers); - int DockContainerCount = 0; - while (s.readNextStartElement()) - { - if (s.name().toString() == "Container") - { - Result = restoreContainer(DockContainerCount, s, Testing); - if (!Result) - { - break; - } - DockContainerCount++; - } - } - - if (!Testing) - { - // Delete remaining empty floating widgets - int FloatingWidgetIndex = DockContainerCount - 1; - int DeleteCount = FloatingWidgets.count() - FloatingWidgetIndex; - for (int i = 0; i < DeleteCount; ++i) - { - FloatingWidgets[FloatingWidgetIndex + i]->deleteLater(); - _this->removeDockContainer(FloatingWidgets[FloatingWidgetIndex + i]->dockContainer()); - } - } - - return Result; -} - - -//============================================================================ -void DockManagerPrivate::restoreDockWidgetsOpenState() -{ - // All dock widgets, that have not been processed in the restore state - // function are invisible to the user now and have no assigned dock area - // They do not belong to any dock container, until the user toggles the - // toggle view action the next time - for (auto DockWidget : DockWidgetsMap) - { - if (DockWidget->property(internal::DirtyProperty).toBool()) - { - DockWidget->flagAsUnassigned(); - emit DockWidget->viewToggled(false); - } - else - { - DockWidget->toggleViewInternal(!DockWidget->property(internal::ClosedProperty).toBool()); - } - } -} - - -//============================================================================ -void DockManagerPrivate::restoreDockAreasIndices() -{ - // Now all dock areas are properly restored and we setup the index of - // The dock areas because the previous toggleView() action has changed - // the dock area index - int Count = 0; - for (auto DockContainer : Containers) - { - Count++; - for (int i = 0; i < DockContainer->dockAreaCount(); ++i) - { - CDockAreaWidget* DockArea = DockContainer->dockArea(i); - QString DockWidgetName = DockArea->property("currentDockWidget").toString(); - CDockWidget* DockWidget = nullptr; - if (!DockWidgetName.isEmpty()) - { - DockWidget = _this->findDockWidget(DockWidgetName); - } - - if (!DockWidget || DockWidget->isClosed()) - { - int Index = DockArea->indexOfFirstOpenDockWidget(); - if (Index < 0) - { - continue; - } - DockArea->setCurrentIndex(Index); - } - else - { - DockArea->internalSetCurrentDockWidget(DockWidget); - } - } - } -} - - - -//============================================================================ -void DockManagerPrivate::emitTopLevelEvents() -{ - // Finally we need to send the topLevelChanged() signals for all dock - // widgets if top level changed - for (auto DockContainer : Containers) - { - CDockWidget* TopLevelDockWidget = DockContainer->topLevelDockWidget(); - if (TopLevelDockWidget) - { - TopLevelDockWidget->emitTopLevelChanged(true); - } - else - { - for (int i = 0; i < DockContainer->dockAreaCount(); ++i) - { - auto DockArea = DockContainer->dockArea(i); - for (auto DockWidget : DockArea->dockWidgets()) - { - DockWidget->emitTopLevelChanged(false); - } - } - } - } -} - - -//============================================================================ -bool DockManagerPrivate::restoreState(const QByteArray& State, int version) -{ - QByteArray state = State.startsWith("actions(); - auto it = std::find_if(Actions.begin(), Actions.end(), - [&Action](const QAction* a) - { - return a->text().compare(Action->text(), Qt::CaseInsensitive) > 0; - }); - - if (it == Actions.end()) - { - Menu->addAction(Action); - } - else - { - Menu->insertAction(*it, Action); - } - } - else - { - Menu->addAction(Action); - } -} - - -//============================================================================ -CDockManager::CDockManager(QWidget *parent) : - CDockContainerWidget(this, parent), - d(new DockManagerPrivate(this)) -{ - createRootSplitter(); - QMainWindow* MainWindow = dynamic_cast(parent); - if (MainWindow) - { - MainWindow->setCentralWidget(this); - } - - d->ViewMenu = new QMenu(tr("Show View"), this); - d->DockAreaOverlay = new CDockOverlay(this, CDockOverlay::ModeDockAreaOverlay); - d->ContainerOverlay = new CDockOverlay(this, CDockOverlay::ModeContainerOverlay); - d->Containers.append(this); - d->loadStylesheet(); -} - -//============================================================================ -CDockManager::~CDockManager() -{ - auto FloatingWidgets = d->FloatingWidgets; - for (auto FloatingWidget : FloatingWidgets) - { - delete FloatingWidget; - } - delete d; -} - - -//============================================================================ -void CDockManager::registerFloatingWidget(CFloatingDockContainer* FloatingWidget) -{ - d->FloatingWidgets.append(FloatingWidget); - ADS_PRINT("d->FloatingWidgets.count() " << d->FloatingWidgets.count()); -} - - -//============================================================================ -void CDockManager::removeFloatingWidget(CFloatingDockContainer* FloatingWidget) -{ - d->FloatingWidgets.removeAll(FloatingWidget); -} - - -//============================================================================ -void CDockManager::registerDockContainer(CDockContainerWidget* DockContainer) -{ - d->Containers.append(DockContainer); -} - - -//============================================================================ -void CDockManager::removeDockContainer(CDockContainerWidget* DockContainer) -{ - if (this != DockContainer) - { - d->Containers.removeAll(DockContainer); - } -} - - -//============================================================================ -CDockOverlay* CDockManager::containerOverlay() const -{ - return d->ContainerOverlay; -} - - -//============================================================================ -CDockOverlay* CDockManager::dockAreaOverlay() const -{ - return d->DockAreaOverlay; -} - - -//============================================================================ -const QList CDockManager::dockContainers() const -{ - return d->Containers; -} - - -//============================================================================ -const QList CDockManager::floatingWidgets() const -{ - return d->FloatingWidgets; -} - - -//============================================================================ -unsigned int CDockManager::zOrderIndex() const -{ - return 0; -} - - -//============================================================================ -QByteArray CDockManager::saveState(int version) const -{ - QByteArray xmldata; - QXmlStreamWriter s(&xmldata); - auto ConfigFlags = CDockManager::configFlags(); - s.setAutoFormatting(ConfigFlags.testFlag(XmlAutoFormattingEnabled)); - s.writeStartDocument(); - s.writeStartElement("QtAdvancedDockingSystem"); - s.writeAttribute("Version", QString::number(version)); - s.writeAttribute("Containers", QString::number(d->Containers.count())); - for (auto Container : d->Containers) - { - Container->saveState(s); - } - - s.writeEndElement(); - s.writeEndDocument(); - - return ConfigFlags.testFlag(XmlCompressionEnabled) - ? qCompress(xmldata, 9) : xmldata; -} - - -//============================================================================ -bool CDockManager::restoreState(const QByteArray &state, int version) -{ - // Prevent multiple calls as long as state is not restore. This may - // happen, if QApplication::processEvents() is called somewhere - if (d->RestoringState) - { - return false; - } - - // We hide the complete dock manager here. Restoring the state means - // that DockWidgets are removed from the DockArea internal stack layout - // which in turn means, that each time a widget is removed the stack - // will show and raise the next available widget which in turn - // triggers show events for the dock widgets. To avoid this we hide the - // dock manager. Because there will be no processing of application - // events until this function is finished, the user will not see this - // hiding - bool IsHidden = this->isHidden(); - if (!IsHidden) - { - hide(); - } - d->RestoringState = true; - emit restoringState(); - bool Result = d->restoreState(state, version); - d->RestoringState = false; - emit stateRestored(); - if (!IsHidden) - { - show(); - } - - return Result; -} - - -//============================================================================ -CFloatingDockContainer* CDockManager::addDockWidgetFloating(CDockWidget* Dockwidget) -{ - d->DockWidgetsMap.insert(Dockwidget->objectName(), Dockwidget); - CDockAreaWidget* OldDockArea = Dockwidget->dockAreaWidget(); - if (OldDockArea) - { - OldDockArea->removeDockWidget(Dockwidget); - } - - Dockwidget->setDockManager(this); - CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(Dockwidget); - FloatingWidget->resize(Dockwidget->size()); - if (isVisible()) - { - FloatingWidget->show(); - } - else - { - d->UninitializedFloatingWidgets.append(FloatingWidget); - } - return FloatingWidget; -} - - -//============================================================================ -void CDockManager::showEvent(QShowEvent *event) -{ - Super::showEvent(event); - if (d->UninitializedFloatingWidgets.empty()) - { - return; - } - - for (auto FloatingWidget : d->UninitializedFloatingWidgets) - { - FloatingWidget->show(); - } - d->UninitializedFloatingWidgets.clear(); -} - - -//============================================================================ -CDockAreaWidget* CDockManager::addDockWidget(DockWidgetArea area, - CDockWidget* Dockwidget, CDockAreaWidget* DockAreaWidget) -{ - d->DockWidgetsMap.insert(Dockwidget->objectName(), Dockwidget); - return CDockContainerWidget::addDockWidget(area, Dockwidget, DockAreaWidget); -} - - -//============================================================================ -CDockAreaWidget* CDockManager::addDockWidgetTab(DockWidgetArea area, - CDockWidget* Dockwidget) -{ - CDockAreaWidget* AreaWidget = lastAddedDockAreaWidget(area); - if (AreaWidget) - { - return addDockWidget(ads::CenterDockWidgetArea, Dockwidget, AreaWidget); - } - else if (!openedDockAreas().isEmpty()) - { - return addDockWidget(area, Dockwidget, openedDockAreas().last()); - } - else - { - return addDockWidget(area, Dockwidget, nullptr); - } -} - - -//============================================================================ -CDockAreaWidget* CDockManager::addDockWidgetTabToArea(CDockWidget* Dockwidget, - CDockAreaWidget* DockAreaWidget) -{ - return addDockWidget(ads::CenterDockWidgetArea, Dockwidget, DockAreaWidget); -} - - -//============================================================================ -CDockWidget* CDockManager::findDockWidget(const QString& ObjectName) const -{ - return d->DockWidgetsMap.value(ObjectName, nullptr); -} - -//============================================================================ -void CDockManager::removeDockWidget(CDockWidget* Dockwidget) -{ - emit dockWidgetAboutToBeRemoved(Dockwidget); - d->DockWidgetsMap.remove(Dockwidget->objectName()); - CDockContainerWidget::removeDockWidget(Dockwidget); - emit dockWidgetRemoved(Dockwidget); -} - -//============================================================================ -QMap CDockManager::dockWidgetsMap() const -{ - return d->DockWidgetsMap; -} - - -//============================================================================ -void CDockManager::addPerspective(const QString& UniquePrespectiveName) -{ - d->Perspectives.insert(UniquePrespectiveName, saveState()); - emit perspectiveListChanged(); -} - - -//============================================================================ -void CDockManager::removePerspective(const QString& Name) -{ - removePerspectives({Name}); -} - - -//============================================================================ -void CDockManager::removePerspectives(const QStringList& Names) -{ - int Count = 0; - for (auto Name : Names) - { - Count += d->Perspectives.remove(Name); - } - - if (Count) - { - emit perspectivesRemoved(); - emit perspectiveListChanged(); - } -} - - -//============================================================================ -QStringList CDockManager::perspectiveNames() const -{ - return d->Perspectives.keys(); -} - - -//============================================================================ -void CDockManager::openPerspective(const QString& PerspectiveName) -{ - const auto Iterator = d->Perspectives.find(PerspectiveName); - if (d->Perspectives.end() == Iterator) - { - return; - } - - emit openingPerspective(PerspectiveName); - restoreState(Iterator.value()); - emit perspectiveOpened(PerspectiveName); -} - - -//============================================================================ -void CDockManager::savePerspectives(QSettings& Settings) const -{ - Settings.beginWriteArray("Perspectives", d->Perspectives.size()); - int i = 0; - for (auto it = d->Perspectives.constBegin(); it != d->Perspectives.constEnd(); ++it) - { - Settings.setArrayIndex(i); - Settings.setValue("Name", it.key()); - Settings.setValue("State", it.value()); - ++i; - } - Settings.endArray(); -} - - -//============================================================================ -void CDockManager::loadPerspectives(QSettings& Settings) -{ - d->Perspectives.clear(); - int Size = Settings.beginReadArray("Perspectives"); - if (!Size) - { - Settings.endArray(); - return; - } - - for (int i = 0; i < Size; ++i) - { - Settings.setArrayIndex(i); - QString Name = Settings.value("Name").toString(); - QByteArray Data = Settings.value("State").toByteArray(); - if (Name.isEmpty() || Data.isEmpty()) - { - continue; - } - - d->Perspectives.insert(Name, Data); - } - - Settings.endArray(); -} - -//============================================================================ -QAction* CDockManager::addToggleViewActionToMenu(QAction* ToggleViewAction, - const QString& Group, const QIcon& GroupIcon) -{ - bool AlphabeticallySorted = (MenuAlphabeticallySorted == d->MenuInsertionOrder); - if (!Group.isEmpty()) - { - QMenu* GroupMenu = d->ViewMenuGroups.value(Group, 0); - if (!GroupMenu) - { - GroupMenu = new QMenu(Group, this); - GroupMenu->setIcon(GroupIcon); - d->addActionToMenu(GroupMenu->menuAction(), d->ViewMenu, AlphabeticallySorted); - d->ViewMenuGroups.insert(Group, GroupMenu); - } - - d->addActionToMenu(ToggleViewAction, GroupMenu, AlphabeticallySorted); - return GroupMenu->menuAction(); - } - else - { - d->addActionToMenu(ToggleViewAction, d->ViewMenu, AlphabeticallySorted); - return ToggleViewAction; - } -} - - -//============================================================================ -QMenu* CDockManager::viewMenu() const -{ - return d->ViewMenu; -} - - -//============================================================================ -void CDockManager::setViewMenuInsertionOrder(eViewMenuInsertionOrder Order) -{ - d->MenuInsertionOrder = Order; -} - - -//=========================================================================== -bool CDockManager::isRestoringState() const -{ - return d->RestoringState; -} - - -//=========================================================================== -int CDockManager::startDragDistance() -{ - return QApplication::startDragDistance() * 1.5; -} - - -//=========================================================================== -CDockManager::ConfigFlags CDockManager::configFlags() -{ - return StaticConfigFlags; -} - - -//=========================================================================== -void CDockManager::setConfigFlags(const ConfigFlags Flags) -{ - StaticConfigFlags = Flags; -} - - -//=========================================================================== -void CDockManager::setConfigFlag(eConfigFlag Flag, bool On) -{ - internal::setFlag(StaticConfigFlags, Flag, On); -} - - -//=========================================================================== -CIconProvider& CDockManager::iconProvider() -{ - static CIconProvider Instance; - return Instance; -} - - -} // namespace ads - -//--------------------------------------------------------------------------- -// EOF DockManager.cpp diff --git a/src/ui/AdvDock/DockManager.h b/src/ui/AdvDock/DockManager.h deleted file mode 100644 index 2c6f05f6..00000000 --- a/src/ui/AdvDock/DockManager.h +++ /dev/null @@ -1,460 +0,0 @@ -#ifndef DockManagerH -#define DockManagerH -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockManager.h -/// \author Uwe Kindler -/// \date 26.02.2017 -/// \brief Declaration of CDockManager class -//============================================================================ - - -//============================================================================ -// INCLUDES -//============================================================================ - -#include "DockContainerWidget.h" -#include "DockWidget.h" -#include "FloatingDockContainer.h" -#include -#include -#include -#include -#include -#include -#include -#include - -class QSettings; -class QMenu; - -namespace ads -{ -struct DockManagerPrivate; -class CFloatingDockContainer; -struct FloatingDockContainerPrivate; -class CDockContainerWidget; -class DockContainerWidgetPrivate; -class CDockOverlay; -class CDockAreaTabBar; -class CDockWidgetTab; -struct DockWidgetTabPrivate; -struct DockAreaWidgetPrivate; -class CIconProvider; - -/** - * The central dock manager that maintains the complete docking system. - * With the configuration flags you can globally control the functionality - * of the docking system. The dock manager uses an internal stylesheet to - * style its components like splitters, tabs and buttons. If you want to - * disable this stylesheet because your application uses its own, - * just call the function for settings the stylesheet with an empty - * string. - * \code - * DockManager->setStyleSheet(""); - * \endcode - **/ -class CDockManager : public CDockContainerWidget -{ - Q_OBJECT -private: - DockManagerPrivate* d; ///< private data (pimpl) - friend struct DockManagerPrivate; - friend class CFloatingDockContainer; - friend struct FloatingDockContainerPrivate; - friend class CDockContainerWidget; - friend class DockContainerWidgetPrivate; - friend class CDockAreaTabBar; - friend class CDockWidgetTab; - friend struct DockAreaWidgetPrivate; - friend struct DockWidgetTabPrivate; - friend class CFloatingDragPreview; - friend struct FloatingDragPreviewPrivate; - -protected: - /** - * Registers the given floating widget in the internal list of - * floating widgets - */ - void registerFloatingWidget(CFloatingDockContainer* FloatingWidget); - - /** - * Remove the given floating widget from the list of registered floating - * widgets - */ - void removeFloatingWidget(CFloatingDockContainer* FloatingWidget); - - /** - * Registers the given dock container widget - */ - void registerDockContainer(CDockContainerWidget* DockContainer); - - /** - * Remove dock container from the internal list of registered dock - * containers - */ - void removeDockContainer(CDockContainerWidget* DockContainer); - - /** - * Overlay for containers - */ - CDockOverlay* containerOverlay() const; - - /** - * Overlay for dock areas - */ - CDockOverlay* dockAreaOverlay() const; - - /** - * Show the floating widgets that has been created floating - */ - virtual void showEvent(QShowEvent *event) override; - -public: - using Super = CDockContainerWidget; - - enum eViewMenuInsertionOrder - { - MenuSortedByInsertion, - MenuAlphabeticallySorted - }; - - /** - * These global configuration flags configure some global dock manager - * settings. - */ - enum eConfigFlag - { - ActiveTabHasCloseButton = 0x0001, //!< If this flag is set, the active tab in a tab area has a close button - DockAreaHasCloseButton = 0x0002, //!< If the flag is set each dock area has a close button - DockAreaCloseButtonClosesTab = 0x0004,//!< If the flag is set, the dock area close button closes the active tab, if not set, it closes the complete cock area - OpaqueSplitterResize = 0x0008, //!< See QSplitter::setOpaqueResize() documentation - XmlAutoFormattingEnabled = 0x0010,//!< If enabled, the XML writer automatically adds line-breaks and indentation to empty sections between elements (ignorable whitespace). - XmlCompressionEnabled = 0x0020,//!< If enabled, the XML output will be compressed and is not human readable anymore - TabCloseButtonIsToolButton = 0x0040,//! If enabled the tab close buttons will be QToolButtons instead of QPushButtons - disabled by default - AllTabsHaveCloseButton = 0x0080, //!< if this flag is set, then all tabs that are closable show a close button - RetainTabSizeWhenCloseButtonHidden = 0x0100, //!< if this flag is set, the space for the close button is reserved even if the close button is not visible - OpaqueUndocking = 0x0200,///< If enabled, the widgets are immediately undocked into floating widgets, if disabled, only a draw preview is undocked and the real undocking is deferred until the mouse is released - DragPreviewIsDynamic = 0x0400,///< If opaque undocking is disabled, this flag defines the behavior of the drag preview window, if this flag is enabled, the preview will be adjusted dynamically to the drop area - DragPreviewShowsContentPixmap = 0x0800,///< If opaque undocking is disabled, the created drag preview window shows a copy of the content of the dock widget / dock are that is dragged - DragPreviewHasWindowFrame = 0x1000,///< If opaque undocking is disabled, then this flag configures if the drag preview is frameless or looks like a real window - DefaultConfig = ActiveTabHasCloseButton - | DockAreaHasCloseButton - | OpaqueSplitterResize - | XmlCompressionEnabled - | OpaqueUndocking, ///< the default configuration - DefaultNonOpaqueConfig = ActiveTabHasCloseButton - | DockAreaHasCloseButton - | XmlCompressionEnabled - | DragPreviewShowsContentPixmap, ///< the default configuration for non opaque operations - NonOpaqueWithWindowFrame = ActiveTabHasCloseButton - | DockAreaHasCloseButton - | XmlCompressionEnabled - | DragPreviewShowsContentPixmap - | DragPreviewHasWindowFrame ///< the default configuration for non opaque operations that show a real window with frame - }; - Q_DECLARE_FLAGS(ConfigFlags, eConfigFlag) - - /** - * Default Constructor. - * If the given parent is a QMainWindow, the dock manager sets itself as the - * central widget. - * Before you create any dock widgets, you should properly setup the - * configuration flags via setConfigFlags(). - */ - CDockManager(QWidget* parent = 0); - - /** - * Virtual Destructor - */ - virtual ~CDockManager(); - - /** - * This function returns the global configuration flags - */ - static ConfigFlags configFlags(); - - /** - * Sets the global configuration flags for the whole docking system. - * Call this function before you create your first dock widget. - */ - static void setConfigFlags(const ConfigFlags Flags); - - /** - * Set a certain config flag - */ - static void setConfigFlag(eConfigFlag Flag, bool On = true); - - /** - * Returns the global icon provider. - * The icon provider enables the use of custom icons in case using - * styleheets for icons is not an option. - */ - static CIconProvider& iconProvider(); - - /** - * Adds dockwidget into the given area. - * If DockAreaWidget is not null, then the area parameter indicates the area - * into the DockAreaWidget. If DockAreaWidget is null, the Dockwidget will - * be dropped into the container. If you would like to add a dock widget - * tabified, then you need to add it to an existing dock area object - * into the CenterDockWidgetArea. The following code shows this: - * \code - * DockManager->addDockWidget(ads::CenterDockWidgetArea, NewDockWidget, - * ExisitingDockArea); - * \endcode - * \return Returns the dock area widget that contains the new DockWidget - */ - CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget, - CDockAreaWidget* DockAreaWidget = nullptr); - - /** - * This function will add the given Dockwidget to the given dock area as - * a new tab. - * If no dock area widget exists for the given area identifier, a new - * dock area widget is created. - */ - CDockAreaWidget* addDockWidgetTab(DockWidgetArea area, - CDockWidget* Dockwidget); - - /** - * This function will add the given Dockwidget to the given DockAreaWidget - * as a new tab. - */ - CDockAreaWidget* addDockWidgetTabToArea(CDockWidget* Dockwidget, - CDockAreaWidget* DockAreaWidget); - - /** - * Adds the given DockWidget floating and returns the created - * CFloatingDockContainer instance. - */ - CFloatingDockContainer* addDockWidgetFloating(CDockWidget* Dockwidget); - - /** - * Searches for a registered doc widget with the given ObjectName - * \return Return the found dock widget or nullptr if a dock widget with the - * given name is not registered - */ - CDockWidget* findDockWidget(const QString& ObjectName) const; - - /** - * Remove the given Dock from the dock manager - */ - void removeDockWidget(CDockWidget* Dockwidget); - - /** - * This function returns a readable reference to the internal dock - * widgets map so that it is possible to iterate over all dock widgets - */ - QMap dockWidgetsMap() const; - - /** - * Returns the list of all active and visible dock containers - * Dock containers are the main dock manager and all floating widgets - */ - const QList dockContainers() const; - - /** - * Returns the list of all floating widgets - */ - const QList floatingWidgets() const; - - /** - * This function always return 0 because the main window is always behind - * any floating widget - */ - virtual unsigned int zOrderIndex() const; - - /** - * Saves the current state of the dockmanger and all its dock widgets - * into the returned QByteArray. - * The XmlMode enables / disables the auto formatting for the XmlStreamWriter. - * 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. - */ - QByteArray saveState(int version = Version1) const; - - /** - * Restores the state of this dockmanagers dockwidgets. - * The version number is compared with that stored in state. If they do - * not match, the dockmanager's state is left unchanged, and this function - * returns false; otherwise, the state is restored, and this function - * returns true. - */ - bool restoreState(const QByteArray &state, int version = Version1); - - /** - * Saves the current perspective to the internal list of perspectives. - * A perspective is the current state of the dock manager assigned - * with a certain name. This makes it possible for the user, - * to switch between different perspectives quickly. - * If a perspective with the given name already exists, then - * it will be overwritten with the new state. - */ - void addPerspective(const QString& UniquePrespectiveName); - - /** - * Removes the perspective with the given name from the list of perspectives - */ - void removePerspective(const QString& Name); - - /** - * Removes the given perspectives from the dock manager - */ - void removePerspectives(const QStringList& Names); - - /** - * Returns the names of all available perspectives - */ - QStringList perspectiveNames() const; - - /** - * Saves the perspectives to the given settings file. - */ - void savePerspectives(QSettings& Settings) const; - - /** - * Loads the perspectives from the given settings file - */ - void loadPerspectives(QSettings& Settings); - - /** - * Adds a toggle view action to the the internal view menu. - * You can either manage the insertion of the toggle view actions in your - * application or you can add the actions to the internal view menu and - * then simply insert the menu object into your. - * \param[in] ToggleViewAction The action to insert. If no group is provided - * the action is directly inserted into the menu. If a group - * is provided, the action is inserted into the group and the - * group is inserted into the menu if it is not existing yet. - * \param[in] Group This is the text used for the group menu item - * \param[in] GroupIcon The icon used for grouping the workbenches in the - * view menu. I.e. if there is a workbench for each device - * like for spectrometer devices, it is good to group all these - * workbenches under a menu item - * \return If Group is not empty, this function returns the GroupAction - * for this group. If the group is empty, the function returns - * the given ToggleViewAction. - */ - QAction* addToggleViewActionToMenu(QAction* ToggleViewAction, - const QString& Group = QString(), const QIcon& GroupIcon = QIcon()); - - /** - * This function returns the internal view menu. - * To fill the view menu, you can use the addToggleViewActionToMenu() - * function. - */ - QMenu* viewMenu() const; - - /** - * Define the insertion order for toggle view menu items. - * The order defines how the actions are added to the view menu. - * The default insertion order is MenuAlphabeticallySorted to make it - * easier for users to find the menu entry for a certain dock widget. - * You need to call this function befor you insert the first menu item - * into the view menu. - */ - void setViewMenuInsertionOrder(eViewMenuInsertionOrder Order); - - /** - * This function returns true between the restoringState() and - * stateRestored() signals. - */ - bool isRestoringState() const; - - /** - * The distance the user needs to move the mouse with the left button - * hold down before a dock widget start floating - */ - static int startDragDistance(); - -public slots: - /** - * Opens the perspective with the given name. - */ - void openPerspective(const QString& PerspectiveName); - -signals: - /** - * This signal is emitted if the list of perspectives changed - */ - void perspectiveListChanged(); - - /** - * This signal is emitted if perspectives have been removed - */ - void perspectivesRemoved(); - - /** - * This signal is emitted, if the restore function is called, just before - * the dock manager starts restoring the state. - * If this function is called, nothing has changed yet - */ - void restoringState(); - - /** - * This signal is emitted if the state changed in restoreState. - * The signal is emitted if the restoreState() function is called or - * if the openPerspective() function is called - */ - void stateRestored(); - - /** - * This signal is emitted, if the dock manager starts opening a - * perspective. - * Opening a perspective may take more than a second if there are - * many complex widgets. The application may use this signal - * to show some progress indicator or to change the mouse cursor - * into a busy cursor. - */ - void openingPerspective(const QString& PerspectiveName); - - /** - * This signal is emitted if the dock manager finished opening a - * perspective - */ - void perspectiveOpened(const QString& PerspectiveName); - - /** - * This signal is emitted, if a new DockArea has been created. - * An application can use this signal to set custom icons or custom - * tooltips for the DockArea buttons. - */ - void dockAreaCreated(CDockAreaWidget* DockArea); - - /** - * This signal is emitted just before the given dock widget is removed - * from the - */ - void dockWidgetAboutToBeRemoved(CDockWidget* DockWidget); - - /** - * This signal is emitted if a dock widget has been removed with the remove - * removeDockWidget() function. - * If this signal is emitted, the dock widget has been removed from the - * docking system but it is not deleted yet. - */ - void dockWidgetRemoved(CDockWidget* DockWidget); -}; // class DockManager -} // namespace ads -//----------------------------------------------------------------------------- -#endif // DockManagerH diff --git a/src/ui/AdvDock/DockOverlay.cpp b/src/ui/AdvDock/DockOverlay.cpp deleted file mode 100644 index 09de8139..00000000 --- a/src/ui/AdvDock/DockOverlay.cpp +++ /dev/null @@ -1,817 +0,0 @@ -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -// INCLUDES -//============================================================================ -#include "DockOverlay.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "DockAreaWidget.h" - -#include - -namespace ads -{ - -/** - * Private data class of CDockOverlay - */ -struct DockOverlayPrivate -{ - CDockOverlay* _this; - DockWidgetAreas AllowedAreas = InvalidDockWidgetArea; - CDockOverlayCross* Cross; - QPointer TargetWidget; - DockWidgetArea LastLocation = InvalidDockWidgetArea; - bool DropPreviewEnabled = true; - CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay; - QRect DropAreaRect; - - /** - * Private data constructor - */ - DockOverlayPrivate(CDockOverlay* _public) : _this(_public) {} -}; - -/** - * Private data of CDockOverlayCross class - */ -struct DockOverlayCrossPrivate -{ - CDockOverlayCross* _this; - CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay; - CDockOverlay* DockOverlay; - QHash DropIndicatorWidgets; - QGridLayout* GridLayout; - QColor IconColors[5]; - bool UpdateRequired = false; - double LastDevicePixelRatio = 0.1; - - /** - * Private data constructor - */ - DockOverlayCrossPrivate(CDockOverlayCross* _public) : _this(_public) {} - - /** - * - * @param area - * @return - */ - QPoint areaGridPosition(const DockWidgetArea area); - - - /** - * Palette based default icon colors - */ - QColor defaultIconColor(CDockOverlayCross::eIconColor ColorIndex) - { - QPalette pal = _this->palette(); - switch (ColorIndex) - { - case CDockOverlayCross::FrameColor: return pal.color(QPalette::Active, QPalette::Highlight); - case CDockOverlayCross::WindowBackgroundColor: return pal.color(QPalette::Active, QPalette::Base); - case CDockOverlayCross::OverlayColor: - { - QColor Color = pal.color(QPalette::Active, QPalette::Highlight); - Color.setAlpha(64); - return Color; - } - break; - - case CDockOverlayCross::ArrowColor: return pal.color(QPalette::Active, QPalette::Base); - case CDockOverlayCross::ShadowColor: return QColor(0, 0, 0, 64); - default: - return QColor(); - } - - return QColor(); - } - - /** - * Stylehseet based icon colors - */ - QColor iconColor(CDockOverlayCross::eIconColor ColorIndex) - { - QColor Color = IconColors[ColorIndex]; - if (!Color.isValid()) - { - Color = defaultIconColor(ColorIndex); - IconColors[ColorIndex] = Color; - } - return Color; - } - - //============================================================================ - /** - * Helper function that returns the drop indicator width depending on the - * operating system - */ - qreal dropIndicatiorWidth(QLabel* l) const - { - #ifdef Q_OS_LINUX - Q_UNUSED(l) - return 40; - #else - return static_cast(l->fontMetrics().height()) * 3.f; - #endif - } - - - //============================================================================ - QWidget* createDropIndicatorWidget(DockWidgetArea DockWidgetArea, - CDockOverlay::eMode Mode) - { - QLabel* l = new QLabel(); - l->setObjectName("DockWidgetAreaLabel"); - - const qreal metric = dropIndicatiorWidth(l); - const QSizeF size(metric, metric); - - l->setPixmap(createHighDpiDropIndicatorPixmap(size, DockWidgetArea, Mode)); - l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint); - l->setAttribute(Qt::WA_TranslucentBackground); - l->setProperty("dockWidgetArea", DockWidgetArea); - return l; - } - - //============================================================================ - void updateDropIndicatorIcon(QWidget* DropIndicatorWidget) - { - QLabel* l = qobject_cast(DropIndicatorWidget); - const qreal metric = dropIndicatiorWidth(l); - const QSizeF size(metric, metric); - - int Area = l->property("dockWidgetArea").toInt(); - l->setPixmap(createHighDpiDropIndicatorPixmap(size, (DockWidgetArea)Area, Mode)); - } - - //============================================================================ - QPixmap createHighDpiDropIndicatorPixmap(const QSizeF& size, DockWidgetArea DockWidgetArea, - CDockOverlay::eMode Mode) - { - QColor borderColor = iconColor(CDockOverlayCross::FrameColor); - QColor backgroundColor = iconColor(CDockOverlayCross::WindowBackgroundColor); - -#if QT_VERSION >= 0x050600 - double DevicePixelRatio = _this->window()->devicePixelRatioF(); -#else - double DevicePixelRatio = _this->window()->devicePixelRatio(); -#endif - QSizeF PixmapSize = size * DevicePixelRatio; - QPixmap pm(PixmapSize.toSize()); - pm.fill(QColor(0, 0, 0, 0)); - - QPainter p(&pm); - QPen pen = p.pen(); - QRectF ShadowRect(pm.rect()); - QRectF baseRect; - baseRect.setSize(ShadowRect.size() * 0.7); - baseRect.moveCenter(ShadowRect.center()); - - // Fill - QColor ShadowColor = iconColor(CDockOverlayCross::ShadowColor); - if (ShadowColor.alpha() == 255) - { - ShadowColor.setAlpha(64); - } - p.fillRect(ShadowRect, ShadowColor); - - // Drop area rect. - p.save(); - QRectF areaRect; - QLineF areaLine; - QRectF nonAreaRect; - switch (DockWidgetArea) - { - case TopDockWidgetArea: - areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f); - nonAreaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f); - areaLine = QLineF(areaRect.bottomLeft(), areaRect.bottomRight()); - break; - case RightDockWidgetArea: - areaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height()); - nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height()); - areaLine = QLineF(areaRect.topLeft(), areaRect.bottomLeft()); - break; - case BottomDockWidgetArea: - areaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f); - nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f); - areaLine = QLineF(areaRect.topLeft(), areaRect.topRight()); - break; - case LeftDockWidgetArea: - areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height()); - nonAreaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height()); - areaLine = QLineF(areaRect.topRight(), areaRect.bottomRight()); - break; - default: - break; - } - - QSizeF baseSize = baseRect.size(); - if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea) - { - baseRect = areaRect; - } - - p.fillRect(baseRect, backgroundColor); - if (areaRect.isValid()) - { - pen = p.pen(); - pen.setColor(borderColor); - QColor Color = iconColor(CDockOverlayCross::OverlayColor); - if (Color.alpha() == 255) - { - Color.setAlpha(64); - } - p.setBrush(Color); - p.setPen(Qt::NoPen); - p.drawRect(areaRect); - - pen = p.pen(); - pen.setWidth(1); - pen.setColor(borderColor); - pen.setStyle(Qt::DashLine); - p.setPen(pen); - p.drawLine(areaLine); - } - p.restore(); - - p.save(); - // Draw outer border - pen = p.pen(); - pen.setColor(borderColor); - pen.setWidth(1); - p.setBrush(Qt::NoBrush); - p.setPen(pen); - p.drawRect(baseRect); - - // draw window title bar - p.setBrush(borderColor); - QRectF FrameRect(baseRect.topLeft(), QSizeF(baseRect.width(), baseSize.height() / 10)); - p.drawRect(FrameRect); - p.restore(); - - // Draw arrow for outer container drop indicators - if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea) - { - QRectF ArrowRect; - ArrowRect.setSize(baseSize); - ArrowRect.setWidth(ArrowRect.width() / 4.6); - ArrowRect.setHeight(ArrowRect.height() / 2); - ArrowRect.moveCenter(QPointF(0, 0)); - QPolygonF Arrow; - Arrow << ArrowRect.topLeft() - << QPointF( ArrowRect.right(), ArrowRect.center().y()) - << ArrowRect.bottomLeft(); - p.setPen(Qt::NoPen); - p.setBrush(iconColor(CDockOverlayCross::ArrowColor)); - p.setRenderHint(QPainter::Antialiasing, true); - p.translate(nonAreaRect.center().x(), nonAreaRect.center().y()); - - switch (DockWidgetArea) - { - case TopDockWidgetArea: - p.rotate(-90); - break; - case RightDockWidgetArea: - break; - case BottomDockWidgetArea: - p.rotate(90); - break; - case LeftDockWidgetArea: - p.rotate(180); - break; - default: - break; - } - - p.drawPolygon(Arrow); - } - - pm.setDevicePixelRatio(DevicePixelRatio); - return pm; - } - -}; - - -//============================================================================ -CDockOverlay::CDockOverlay(QWidget* parent, eMode Mode) : - QFrame(parent), - d(new DockOverlayPrivate(this)) -{ - d->Mode = Mode; - d->Cross = new CDockOverlayCross(this); -#ifdef Q_OS_LINUX - setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); -#else - setWindowFlags(Qt::Tool | Qt::FramelessWindowHint); -#endif - setWindowOpacity(1); - setWindowTitle("DockOverlay"); - setAttribute(Qt::WA_NoSystemBackground); - setAttribute(Qt::WA_TranslucentBackground); - - d->Cross->setVisible(false); - setVisible(false); -} - - -//============================================================================ -CDockOverlay::~CDockOverlay() -{ - delete d; -} - - -//============================================================================ -void CDockOverlay::setAllowedAreas(DockWidgetAreas areas) -{ - if (areas == d->AllowedAreas) - return; - d->AllowedAreas = areas; - d->Cross->reset(); -} - - -//============================================================================ -DockWidgetAreas CDockOverlay::allowedAreas() const -{ - return d->AllowedAreas; -} - - -//============================================================================ -DockWidgetArea CDockOverlay::dropAreaUnderCursor() const -{ - DockWidgetArea Result = d->Cross->cursorLocation(); - if (Result != InvalidDockWidgetArea) - { - return Result; - } - - CDockAreaWidget* DockArea = dynamic_cast(d->TargetWidget.data()); - if (!DockArea) - { - return Result; - } - - if (DockArea->titleBarGeometry().contains(DockArea->mapFromGlobal(QCursor::pos()))) - { - return CenterDockWidgetArea; - } - - return Result; -} - - -//============================================================================ -DockWidgetArea CDockOverlay::showOverlay(QWidget* target) -{ - if (d->TargetWidget == target) - { - // Hint: We could update geometry of overlay here. - DockWidgetArea da = dropAreaUnderCursor(); - if (da != d->LastLocation) - { - repaint(); - d->LastLocation = da; - } - return da; - } - - d->TargetWidget = target; - d->LastLocation = InvalidDockWidgetArea; - - // Move it over the target. - resize(target->size()); - QPoint TopLeft = target->mapToGlobal(target->rect().topLeft()); - move(TopLeft); - show(); - d->Cross->updatePosition(); - d->Cross->updateOverlayIcons(); - return dropAreaUnderCursor(); -} - - -//============================================================================ -void CDockOverlay::hideOverlay() -{ - hide(); - d->TargetWidget.clear(); - d->LastLocation = InvalidDockWidgetArea; - d->DropAreaRect = QRect(); -} - - -//============================================================================ -void CDockOverlay::enableDropPreview(bool Enable) -{ - d->DropPreviewEnabled = Enable; - update(); -} - - -//============================================================================ -bool CDockOverlay::dropPreviewEnabled() const -{ - return d->DropPreviewEnabled; -} - - -//============================================================================ -void CDockOverlay::paintEvent(QPaintEvent* event) -{ - Q_UNUSED(event); - // Draw rect based on location - if (!d->DropPreviewEnabled) - { - d->DropAreaRect = QRect(); - return; - } - - QRect r = rect(); - const DockWidgetArea da = dropAreaUnderCursor(); - double Factor = (CDockOverlay::ModeContainerOverlay == d->Mode) ? - 3 : 2; - - switch (da) - { - case TopDockWidgetArea: r.setHeight(r.height() / Factor); break; - case RightDockWidgetArea: r.setX(r.width() * (1 - 1 / Factor)); break; - case BottomDockWidgetArea: r.setY(r.height() * (1 - 1 / Factor)); break; - case LeftDockWidgetArea: r.setWidth(r.width() / Factor); break; - case CenterDockWidgetArea: r = rect();break; - default: return; - } - QPainter painter(this); - QColor Color = palette().color(QPalette::Active, QPalette::Highlight); - QPen Pen = painter.pen(); - Pen.setColor(Color.darker(120)); - Pen.setStyle(Qt::SolidLine); - Pen.setWidth(1); - Pen.setCosmetic(true); - painter.setPen(Pen); - Color = Color.lighter(130); - Color.setAlpha(64); - painter.setBrush(Color); - painter.drawRect(r.adjusted(0, 0, -1, -1)); - d->DropAreaRect = r; -} - - -//============================================================================ -QRect CDockOverlay::dropOverlayRect() const -{ - return d->DropAreaRect; -} - - -//============================================================================ -void CDockOverlay::showEvent(QShowEvent* e) -{ - d->Cross->show(); - QFrame::showEvent(e); -} - - -//============================================================================ -void CDockOverlay::hideEvent(QHideEvent* e) -{ - d->Cross->hide(); - QFrame::hideEvent(e); -} - - -//============================================================================ -bool CDockOverlay::event(QEvent *e) -{ - bool Result = Super::event(e); - if (e->type() == QEvent::Polish) - { - d->Cross->setupOverlayCross(d->Mode); - } - return Result; -} - - -//============================================================================ -static int areaAlignment(const DockWidgetArea area) -{ - switch (area) - { - case TopDockWidgetArea: return (int) Qt::AlignHCenter | Qt::AlignBottom; - case RightDockWidgetArea: return (int) Qt::AlignLeft | Qt::AlignVCenter; - case BottomDockWidgetArea: return (int) Qt::AlignHCenter | Qt::AlignTop; - case LeftDockWidgetArea: return (int) Qt::AlignRight | Qt::AlignVCenter; - case CenterDockWidgetArea: return (int) Qt::AlignCenter; - default: return Qt::AlignCenter; - } -} - -//============================================================================ -// DockOverlayCrossPrivate -//============================================================================ -QPoint DockOverlayCrossPrivate::areaGridPosition(const DockWidgetArea area) -{ - if (CDockOverlay::ModeDockAreaOverlay == Mode) - { - switch (area) - { - case TopDockWidgetArea: return QPoint(1, 2); - case RightDockWidgetArea: return QPoint(2, 3); - case BottomDockWidgetArea: return QPoint(3, 2); - case LeftDockWidgetArea: return QPoint(2, 1); - case CenterDockWidgetArea: return QPoint(2, 2); - default: return QPoint(); - } - } - else - { - switch (area) - { - case TopDockWidgetArea: return QPoint(0, 2); - case RightDockWidgetArea: return QPoint(2, 4); - case BottomDockWidgetArea: return QPoint(4, 2); - case LeftDockWidgetArea: return QPoint(2, 0); - case CenterDockWidgetArea: return QPoint(2, 2); - default: return QPoint(); - } - } -} - - -//============================================================================ -CDockOverlayCross::CDockOverlayCross(CDockOverlay* overlay) : - QWidget(overlay->parentWidget()), - d(new DockOverlayCrossPrivate(this)) -{ - d->DockOverlay = overlay; -#ifdef Q_OS_LINUX - setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); -#else - setWindowFlags(Qt::Tool | Qt::FramelessWindowHint); -#endif - setWindowTitle("DockOverlayCross"); - setAttribute(Qt::WA_TranslucentBackground); - - d->GridLayout = new QGridLayout(); - d->GridLayout->setSpacing(0); - setLayout(d->GridLayout); -} - - -//============================================================================ -CDockOverlayCross::~CDockOverlayCross() -{ - delete d; -} - - -//============================================================================ -void CDockOverlayCross::setupOverlayCross(CDockOverlay::eMode Mode) -{ - d->Mode = Mode; - - QHash areaWidgets; - areaWidgets.insert(TopDockWidgetArea, d->createDropIndicatorWidget(TopDockWidgetArea, Mode)); - areaWidgets.insert(RightDockWidgetArea, d->createDropIndicatorWidget(RightDockWidgetArea, Mode)); - areaWidgets.insert(BottomDockWidgetArea, d->createDropIndicatorWidget(BottomDockWidgetArea, Mode)); - areaWidgets.insert(LeftDockWidgetArea, d->createDropIndicatorWidget(LeftDockWidgetArea, Mode)); - areaWidgets.insert(CenterDockWidgetArea, d->createDropIndicatorWidget(CenterDockWidgetArea, Mode)); -#if QT_VERSION >= 0x050600 - d->LastDevicePixelRatio = devicePixelRatioF(); -#else - d->LastDevicePixelRatio = devicePixelRatio(); -#endif - setAreaWidgets(areaWidgets); - d->UpdateRequired = false; -} - - -//============================================================================ -void CDockOverlayCross::updateOverlayIcons() -{ - if (windowHandle()->devicePixelRatio() == d->LastDevicePixelRatio) - { - return; - } - - for (auto Widget : d->DropIndicatorWidgets) - { - d->updateDropIndicatorIcon(Widget); - } -#if QT_VESION >= 0x050600 - d->LastDevicePixelRatio = devicePixelRatioF(); -#else - d->LastDevicePixelRatio = devicePixelRatio(); -#endif -} - - -//============================================================================ -void CDockOverlayCross::setIconColor(eIconColor ColorIndex, const QColor& Color) -{ - d->IconColors[ColorIndex] = Color; - d->UpdateRequired = true; -} - - -//============================================================================ -QColor CDockOverlayCross::iconColor(eIconColor ColorIndex) const -{ - return d->IconColors[ColorIndex]; -} - - -//============================================================================ -void CDockOverlayCross::setAreaWidgets(const QHash& widgets) -{ - // Delete old widgets. - QMutableHashIterator i(d->DropIndicatorWidgets); - while (i.hasNext()) - { - i.next(); - QWidget* widget = i.value(); - d->GridLayout->removeWidget(widget); - delete widget; - i.remove(); - } - - // Insert new widgets into grid. - d->DropIndicatorWidgets = widgets; - QHashIterator i2(d->DropIndicatorWidgets); - while (i2.hasNext()) - { - i2.next(); - const DockWidgetArea area = i2.key(); - QWidget* widget = i2.value(); - QPoint p = d->areaGridPosition(area); - d->GridLayout->addWidget(widget, p.x(), p.y(), (Qt::Alignment) areaAlignment(area)); - } - - if (CDockOverlay::ModeDockAreaOverlay == d->Mode) - { - d->GridLayout->setContentsMargins(0, 0, 0, 0); - d->GridLayout->setRowStretch(0, 1); - d->GridLayout->setRowStretch(1, 0); - d->GridLayout->setRowStretch(2, 0); - d->GridLayout->setRowStretch(3, 0); - d->GridLayout->setRowStretch(4, 1); - - d->GridLayout->setColumnStretch(0, 1); - d->GridLayout->setColumnStretch(1, 0); - d->GridLayout->setColumnStretch(2, 0); - d->GridLayout->setColumnStretch(3, 0); - d->GridLayout->setColumnStretch(4, 1); - } - else - { - d->GridLayout->setContentsMargins(4, 4, 4, 4); - d->GridLayout->setRowStretch(0, 0); - d->GridLayout->setRowStretch(1, 1); - d->GridLayout->setRowStretch(2, 1); - d->GridLayout->setRowStretch(3, 1); - d->GridLayout->setRowStretch(4, 0); - - d->GridLayout->setColumnStretch(0, 0); - d->GridLayout->setColumnStretch(1, 1); - d->GridLayout->setColumnStretch(2, 1); - d->GridLayout->setColumnStretch(3, 1); - d->GridLayout->setColumnStretch(4, 0); - } - reset(); -} - - -//============================================================================ -DockWidgetArea CDockOverlayCross::cursorLocation() const -{ - const QPoint pos = mapFromGlobal(QCursor::pos()); - QHashIterator i(d->DropIndicatorWidgets); - while (i.hasNext()) - { - i.next(); - if (d->DockOverlay->allowedAreas().testFlag(i.key()) - && i.value() - && i.value()->isVisible() - && i.value()->geometry().contains(pos)) - { - return i.key(); - } - } - return InvalidDockWidgetArea; -} - - -//============================================================================ -void CDockOverlayCross::showEvent(QShowEvent*) -{ - if (d->UpdateRequired) - { - setupOverlayCross(d->Mode); - } - this->updatePosition(); -} - - -//============================================================================ -void CDockOverlayCross::updatePosition() -{ - resize(d->DockOverlay->size()); - QPoint TopLeft = d->DockOverlay->pos(); - QPoint Offest((this->width() - d->DockOverlay->width()) / 2, - (this->height() - d->DockOverlay->height()) / 2); - QPoint CrossTopLeft = TopLeft - Offest; - move(CrossTopLeft); -} - - -//============================================================================ -void CDockOverlayCross::reset() -{ - QList allAreas; - allAreas << TopDockWidgetArea << RightDockWidgetArea - << BottomDockWidgetArea << LeftDockWidgetArea << CenterDockWidgetArea; - const DockWidgetAreas allowedAreas = d->DockOverlay->allowedAreas(); - - // Update visibility of area widgets based on allowedAreas. - for (int i = 0; i < allAreas.count(); ++i) - { - QPoint p = d->areaGridPosition(allAreas.at(i)); - QLayoutItem* item = d->GridLayout->itemAtPosition(p.x(), p.y()); - QWidget* w = nullptr; - if (item && (w = item->widget()) != nullptr) - { - w->setVisible(allowedAreas.testFlag(allAreas.at(i))); - } - } -} - - -//============================================================================ -void CDockOverlayCross::setIconColors(const QString& Colors) -{ - static const QMap ColorCompenentStringMap{ - {"Frame", CDockOverlayCross::FrameColor}, - {"Background", CDockOverlayCross::WindowBackgroundColor}, - {"Overlay", CDockOverlayCross::OverlayColor}, - {"Arrow", CDockOverlayCross::ArrowColor}, - {"Shadow", CDockOverlayCross::ShadowColor}}; - - auto ColorList = Colors.split(' ', Qt::SkipEmptyParts); - for (const auto& ColorListEntry : ColorList) - { - auto ComponentColor = ColorListEntry.split('=', Qt::SkipEmptyParts); - int Component = ColorCompenentStringMap.value(ComponentColor[0], -1); - if (Component < 0) - { - continue; - } - d->IconColors[Component] = QColor(ComponentColor[1]); - } - - d->UpdateRequired = true; -} - -//============================================================================ -QString CDockOverlayCross::iconColors() const -{ - return QString(); -} - - - -} // namespace ads -//---------------------------------------------------------------------------- - diff --git a/src/ui/AdvDock/DockOverlay.h b/src/ui/AdvDock/DockOverlay.h deleted file mode 100644 index a61fdd76..00000000 --- a/src/ui/AdvDock/DockOverlay.h +++ /dev/null @@ -1,257 +0,0 @@ -#ifndef DockOverlayH -#define DockOverlayH -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -// INCLUDES -//============================================================================ -#include -#include -#include -#include - -#include "ads_globals.h" - -class QGridLayout; - -namespace ads -{ -struct DockOverlayPrivate; -class CDockOverlayCross; - -/*! - * DockOverlay paints a translucent rectangle over another widget. The geometry - * of the rectangle is based on the mouse location. - */ -class CDockOverlay : public QFrame -{ - Q_OBJECT -private: - DockOverlayPrivate* d; //< private data class - friend struct DockOverlayPrivate; - friend class DockOverlayCross; - -public: - using Super = QFrame; - - enum eMode - { - ModeDockAreaOverlay, - ModeContainerOverlay - }; - - /** - * Creates a dock overlay - */ - CDockOverlay(QWidget* parent, eMode Mode = ModeDockAreaOverlay); - - /** - * Virtual destructor - */ - virtual ~CDockOverlay(); - - /** - * Configures the areas that are allowed for docking - */ - void setAllowedAreas(DockWidgetAreas areas); - - /** - * Returns flags with all allowed drop areas - */ - DockWidgetAreas allowedAreas() const; - - /** - * Returns the drop area under the current cursor location - */ - DockWidgetArea dropAreaUnderCursor() const; - - /** - * Show the drop overly for the given target widget - */ - DockWidgetArea showOverlay(QWidget* target); - - /** - * Hides the overlay - */ - void hideOverlay(); - - /** - * Enables / disables the semi transparent overlay rectangle that represents - * the future area of the dropped widget - */ - void enableDropPreview(bool Enable); - - /** - * Returns true if drop preview is enabled - */ - bool dropPreviewEnabled() const; - - /** - * The drop overlay rectangle for the target area - */ - QRect dropOverlayRect() const; - - /** - * Handle polish events - */ - virtual bool event(QEvent *e) override; - -protected: - virtual void paintEvent(QPaintEvent *e) override; - virtual void showEvent(QShowEvent* e) override; - virtual void hideEvent(QHideEvent* e) override; -}; - - -struct DockOverlayCrossPrivate; -/*! - * DockOverlayCross shows a cross with 5 different drop area possibilities. - * I could have handled everything inside DockOverlay, but because of some - * styling issues it's better to have a separate class for the cross. - * You can style the cross icon using the property system. - * \code - * ads--CDockOverlayCross - { - qproperty-iconFrameColor: palette(highlight); - qproperty-iconBackgroundColor: palette(base); - qproperty-iconOverlayColor: palette(highlight); - qproperty-iconArrowColor: rgb(227, 227, 227); - qproperty-iconShadowColor: rgb(0, 0, 0); - } - * \endcode - * Or you can use the iconColors property to pass in AARRGGBB values as - * hex string like shown in the example below. - * \code - * ads--CDockOverlayCross - * { - * qproperty-iconColors: "Frame=#ff3d3d3d Background=#ff929292 Overlay=#1f3d3d3d Arrow=#ffb4b4b4 Shadow=#40474747"; - * } - * \endcode - */ -class CDockOverlayCross : public QWidget -{ - Q_OBJECT - Q_PROPERTY(QString iconColors READ iconColors WRITE setIconColors) - Q_PROPERTY(QColor iconFrameColor READ iconColor WRITE setIconFrameColor) - Q_PROPERTY(QColor iconBackgroundColor READ iconColor WRITE setIconBackgroundColor) - Q_PROPERTY(QColor iconOverlayColor READ iconColor WRITE setIconOverlayColor) - Q_PROPERTY(QColor iconArrowColor READ iconColor WRITE setIconArrowColor) - Q_PROPERTY(QColor iconShadowColor READ iconColor WRITE setIconShadowColor) - -public: - enum eIconColor - { - FrameColor,///< the color of the frame of the small window icon - WindowBackgroundColor,///< the background color of the small window in the icon - OverlayColor,///< the color that shows the overlay (the dock side) in the icon - ArrowColor,///< the arrow that points into the direction - ShadowColor///< the color of the shadow rectangle that is painted below the icons - }; - -private: - DockOverlayCrossPrivate* d; - friend struct DockOverlayCrossPrivate; - friend class CDockOverlay; - -protected: - /** - * This function returns an empty string and is only here to silence - * moc - */ - QString iconColors() const; - - /** - * This is a dummy function for the property system - */ - QColor iconColor() const {return QColor();} - void setIconFrameColor(const QColor& Color) {setIconColor(FrameColor, Color);} - void setIconBackgroundColor(const QColor& Color) {setIconColor(WindowBackgroundColor, Color);} - void setIconOverlayColor(const QColor& Color) {setIconColor(OverlayColor, Color);} - void setIconArrowColor(const QColor& Color) {setIconColor(ArrowColor, Color);} - void setIconShadowColor(const QColor& Color) {setIconColor(ShadowColor, Color);} - -public: - /** - * Creates an overlay cross for the given overlay - */ - CDockOverlayCross(CDockOverlay* overlay); - - /** - * Virtual destructor - */ - virtual ~CDockOverlayCross(); - - /** - * Sets a certain icon color - */ - void setIconColor(eIconColor ColorIndex, const QColor& Color); - - /** - * Returns the icon color given by ColorIndex - */ - QColor iconColor(eIconColor ColorIndex) const; - - /** - * Returns the dock widget area depending on the current cursor location. - * The function checks, if the mouse cursor is inside of any drop indicator - * widget and returns the corresponding DockWidgetArea. - */ - DockWidgetArea cursorLocation() const; - - /** - * Sets up the overlay cross for the given overlay mode - */ - void setupOverlayCross(CDockOverlay::eMode Mode); - - /** - * Recreates the overlay icons. - */ - void updateOverlayIcons(); - - /** - * Resets and updates the - */ - void reset(); - - /** - * Updates the current position - */ - void updatePosition(); - - /** - * A string with all icon colors to set. - * You can use this property to style the overly icon via CSS stylesheet - * file. The colors are set via a color identifier and a hex AARRGGBB value like - * in the example below. - * \code - * ads--CDockOverlayCross - * { - * qproperty-iconColors: "Frame=#ff3d3d3d Background=#ff929292 Overlay=#1f3d3d3d Arrow=#ffb4b4b4 Shadow=#40474747"; - * } - */ - void setIconColors(const QString& Colors); - -protected: - virtual void showEvent(QShowEvent* e) override; - void setAreaWidgets(const QHash& widgets); -}; // CDockOverlayCross - -} // namespace ads -#endif // DockOverlayH diff --git a/src/ui/AdvDock/DockSplitter.cpp b/src/ui/AdvDock/DockSplitter.cpp deleted file mode 100644 index 52155c31..00000000 --- a/src/ui/AdvDock/DockSplitter.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockSplitter.cpp -/// \author Uwe Kindler -/// \date 24.03.2017 -/// \brief Implementation of CDockSplitter -//============================================================================ - -//============================================================================ -// INCLUDES -//============================================================================ -#include "DockSplitter.h" - -#include -#include -#include - -#include "DockAreaWidget.h" - -namespace ads -{ -/** - * Private dock splitter data - */ -struct DockSplitterPrivate -{ - CDockSplitter* _this; - int VisibleContentCount = 0; - - DockSplitterPrivate(CDockSplitter* _public) : _this(_public) {} -}; - -//============================================================================ -CDockSplitter::CDockSplitter(QWidget *parent) - : QSplitter(parent), - d(new DockSplitterPrivate(this)) -{ - setProperty("ads-splitter", true); - setChildrenCollapsible(false); -} - - -//============================================================================ -CDockSplitter::CDockSplitter(Qt::Orientation orientation, QWidget *parent) - : QSplitter(orientation, parent), - d(new DockSplitterPrivate(this)) -{ - -} - -//============================================================================ -CDockSplitter::~CDockSplitter() -{ - ADS_PRINT("~CDockSplitter"); - delete d; -} - - -//============================================================================ -bool CDockSplitter::hasVisibleContent() const -{ - // TODO Cache or precalculate this to speed up - for (int i = 0; i < count(); ++i) - { - if (!widget(i)->isHidden()) - { - return true; - } - } - - return false; -} - -} // namespace ads - -//--------------------------------------------------------------------------- -// EOF DockSplitter.cpp diff --git a/src/ui/AdvDock/DockSplitter.h b/src/ui/AdvDock/DockSplitter.h deleted file mode 100644 index 4ab7aac7..00000000 --- a/src/ui/AdvDock/DockSplitter.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef DockSplitterH -#define DockSplitterH -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockSplitter.h -/// \author Uwe Kindler -/// \date 24.03.2017 -/// \brief Declaration of CDockSplitter -//============================================================================ - -//============================================================================ -// INCLUDES -//============================================================================ -#include - -#include "ads_globals.h" - -namespace ads -{ -struct DockSplitterPrivate; - -/** - * Splitter used internally instead of QSplitter with some additional - * fuctionality. - */ -class CDockSplitter : public QSplitter -{ - Q_OBJECT -private: - DockSplitterPrivate* d; - friend struct DockSplitterPrivate; - -public: - CDockSplitter(QWidget *parent = Q_NULLPTR); - CDockSplitter(Qt::Orientation orientation, QWidget *parent = Q_NULLPTR); - - /** - * Prints debug info - */ - virtual ~CDockSplitter(); - - /** - * Returns true, if any of the internal widgets is visible - */ - bool hasVisibleContent() const; -}; // class CDockSplitter - -} // namespace ads - -//--------------------------------------------------------------------------- -#endif // DockSplitterH diff --git a/src/ui/AdvDock/DockWidget.cpp b/src/ui/AdvDock/DockWidget.cpp deleted file mode 100644 index e57dfc34..00000000 --- a/src/ui/AdvDock/DockWidget.cpp +++ /dev/null @@ -1,823 +0,0 @@ -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockWidget.cpp -/// \author Uwe Kindler -/// \date 26.02.2017 -/// \brief Implementation of CDockWidget class -//============================================================================ - - -//============================================================================ -// INCLUDES -//============================================================================ -#include "DockWidgetTab.h" -#include "DockWidget.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "DockContainerWidget.h" -#include "DockAreaWidget.h" -#include "DockManager.h" -#include "FloatingDockContainer.h" -#include "DockSplitter.h" -#include "ads_globals.h" - - -namespace ads -{ -/** - * Private data class of CDockWidget class (pimpl) - */ -struct DockWidgetPrivate -{ - CDockWidget* _this = nullptr; - QBoxLayout* Layout = nullptr; - QWidget* Widget = nullptr; - CDockWidgetTab* TabWidget = nullptr; - CDockWidget::DockWidgetFeatures Features = CDockWidget::DefaultDockWidgetFeatures; - CDockManager* DockManager = nullptr; - CDockAreaWidget* DockArea = nullptr; - QAction* ToggleViewAction = nullptr; - bool Closed = false; - QScrollArea* ScrollArea = nullptr; - QToolBar* ToolBar = nullptr; - Qt::ToolButtonStyle ToolBarStyleDocked = Qt::ToolButtonIconOnly; - Qt::ToolButtonStyle ToolBarStyleFloating = Qt::ToolButtonTextUnderIcon; - QSize ToolBarIconSizeDocked = QSize(16, 16); - QSize ToolBarIconSizeFloating = QSize(24, 24); - bool IsFloatingTopLevel = false; - - /** - * Private data constructor - */ - DockWidgetPrivate(CDockWidget* _public); - - /** - * Show dock widget - */ - void showDockWidget(); - - /** - * Hide dock widget. - */ - void hideDockWidget(); - - /** - * Hides a dock area if all dock widgets in the area are closed. - * This function updates the current selected tab and hides the parent - * dock area if it is empty - */ - void updateParentDockArea(); - - /** - * Setup the top tool bar - */ - void setupToolBar(); - - /** - * Setup the main scroll area - */ - void setupScrollArea(); -}; -// struct DockWidgetPrivate - -//============================================================================ -DockWidgetPrivate::DockWidgetPrivate(CDockWidget* _public) : - _this(_public) -{ - -} - - -//============================================================================ -void DockWidgetPrivate::showDockWidget() -{ - if (!DockArea) - { - CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this); - FloatingWidget->resize(_this->size()); - FloatingWidget->show(); - } - else - { - DockArea->setCurrentDockWidget(_this); - DockArea->toggleView(true); - TabWidget->show(); - QSplitter* Splitter = internal::findParent(DockArea); - while (Splitter && !Splitter->isVisible()) - { - Splitter->show(); - Splitter = internal::findParent(Splitter); - } - - CDockContainerWidget* Container = DockArea->dockContainer(); - if (Container->isFloating()) - { - CFloatingDockContainer* FloatingWidget = internal::findParent< - CFloatingDockContainer*>(Container); - FloatingWidget->show(); - } - } -} - - -//============================================================================ -void DockWidgetPrivate::hideDockWidget() -{ - TabWidget->hide(); - updateParentDockArea(); -} - - -//============================================================================ -void DockWidgetPrivate::updateParentDockArea() -{ - if (!DockArea) - { - return; - } - - auto NextDockWidget = DockArea->nextOpenDockWidget(_this); - if (NextDockWidget) - { - DockArea->setCurrentDockWidget(NextDockWidget); - } - else - { - DockArea->hideAreaWithNoVisibleContent(); - } -} - - -//============================================================================ -void DockWidgetPrivate::setupToolBar() -{ - ToolBar = new QToolBar(_this); - ToolBar->setObjectName("dockWidgetToolBar"); - Layout->insertWidget(0, ToolBar); - ToolBar->setIconSize(QSize(16, 16)); - ToolBar->toggleViewAction()->setEnabled(false); - ToolBar->toggleViewAction()->setVisible(false); - _this->connect(_this, SIGNAL(topLevelChanged(bool)), SLOT(setToolbarFloatingStyle(bool))); -} - - - -//============================================================================ -void DockWidgetPrivate::setupScrollArea() -{ - ScrollArea = new QScrollArea(_this); - ScrollArea->setObjectName("dockWidgetScrollArea"); - ScrollArea->setWidgetResizable(true); - Layout->addWidget(ScrollArea); -} - - -//============================================================================ -CDockWidget::CDockWidget(const QString &title, QWidget *parent) : - QFrame(parent), - d(new DockWidgetPrivate(this)) -{ - d->Layout = new QBoxLayout(QBoxLayout::TopToBottom); - d->Layout->setContentsMargins(0, 0, 0, 0); - d->Layout->setSpacing(0); - setLayout(d->Layout); - setWindowTitle(title); - setObjectName(title); - - d->TabWidget = new CDockWidgetTab(this); - d->ToggleViewAction = new QAction(title, this); - d->ToggleViewAction->setCheckable(true); - connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this, - SLOT(toggleView(bool))); - setToolbarFloatingStyle(false); -} - -//============================================================================ -CDockWidget::~CDockWidget() -{ - ADS_PRINT("~CDockWidget()"); - delete d; -} - - -//============================================================================ -void CDockWidget::setToggleViewActionChecked(bool Checked) -{ - QAction* Action = d->ToggleViewAction; - Action->blockSignals(true); - Action->setChecked(Checked); - Action->blockSignals(false); -} - - -//============================================================================ -void CDockWidget::setWidget(QWidget* widget, eInsertMode InsertMode) -{ - QScrollArea* ScrollAreaWidget = qobject_cast(widget); - if (ScrollAreaWidget || ForceNoScrollArea == InsertMode) - { - d->Layout->addWidget(widget); - if (ScrollAreaWidget && ScrollAreaWidget->viewport()) - { - ScrollAreaWidget->viewport()->setProperty("dockWidgetContent", true); - } - } - else - { - d->setupScrollArea(); - d->ScrollArea->setWidget(widget); - } - - d->Widget = widget; - d->Widget->setProperty("dockWidgetContent", true); -} - - -//============================================================================ -QWidget* CDockWidget::takeWidget() -{ - d->ScrollArea->takeWidget(); - d->Layout->removeWidget(d->Widget); - d->Widget->setParent(nullptr); - return d->Widget; -} - - -//============================================================================ -QWidget* CDockWidget::widget() const -{ - return d->Widget; -} - - -//============================================================================ -CDockWidgetTab* CDockWidget::tabWidget() const -{ - return d->TabWidget; -} - - -//============================================================================ -void CDockWidget::setFeatures(DockWidgetFeatures features) -{ - if (d->Features == features) - { - return; - } - d->Features = features; - emit featuresChanged(d->Features); - d->TabWidget->onDockWidgetFeaturesChanged(); -} - - -//============================================================================ -void CDockWidget::setFeature(DockWidgetFeature flag, bool on) -{ - auto Features = features(); - internal::setFlag(Features, flag, on); - setFeatures(Features); -} - - -//============================================================================ -CDockWidget::DockWidgetFeatures CDockWidget::features() const -{ - return d->Features; -} - - -//============================================================================ -CDockManager* CDockWidget::dockManager() const -{ - return d->DockManager; -} - - -//============================================================================ -void CDockWidget::setDockManager(CDockManager* DockManager) -{ - d->DockManager = DockManager; -} - - -//============================================================================ -CDockContainerWidget* CDockWidget::dockContainer() const -{ - if (d->DockArea) - { - return d->DockArea->dockContainer(); - } - else - { - return 0; - } -} - - -//============================================================================ -CDockAreaWidget* CDockWidget::dockAreaWidget() const -{ - return d->DockArea; -} - - -//============================================================================ -bool CDockWidget::isFloating() const -{ - if (!isInFloatingContainer()) - { - return false; - } - - return dockContainer()->topLevelDockWidget() == this; -} - - -//============================================================================ -bool CDockWidget::isInFloatingContainer() const -{ - auto Container = dockContainer(); - if (!Container) - { - return false; - } - - if (!Container->isFloating()) - { - return false; - } - - return true; -} - - -//============================================================================ -bool CDockWidget::isClosed() const -{ - return d->Closed; -} - - -//============================================================================ -QAction* CDockWidget::toggleViewAction() const -{ - return d->ToggleViewAction; -} - - -//============================================================================ -void CDockWidget::setToggleViewActionMode(eToggleViewActionMode Mode) -{ - if (ActionModeToggle == Mode) - { - d->ToggleViewAction->setCheckable(true); - d->ToggleViewAction->setIcon(QIcon()); - } - else - { - d->ToggleViewAction->setCheckable(false); - d->ToggleViewAction->setIcon(d->TabWidget->icon()); - } -} - - -//============================================================================ -void CDockWidget::toggleView(bool Open) -{ - // If the toggle view action mode is ActionModeShow, then Open is always - // true if the sender is the toggle view action - QAction* Sender = qobject_cast(sender()); - if (Sender == d->ToggleViewAction && !d->ToggleViewAction->isCheckable()) - { - Open = true; - } - // If the dock widget state is different, then we really need to toggle - // the state. If we are in the right state, then we simply make this - // dock widget the current dock widget - if (d->Closed != !Open) - { - toggleViewInternal(Open); - } - else if (Open && d->DockArea) - { - d->DockArea->setCurrentDockWidget(this); - } -} - - -//============================================================================ -void CDockWidget::toggleViewInternal(bool Open) -{ - CDockContainerWidget* DockContainer = dockContainer(); - CDockWidget* TopLevelDockWidgetBefore = DockContainer - ? DockContainer->topLevelDockWidget() : nullptr; - - if (Open) - { - d->showDockWidget(); - } - else - { - d->hideDockWidget(); - } - d->Closed = !Open; - d->ToggleViewAction->blockSignals(true); - d->ToggleViewAction->setChecked(Open); - d->ToggleViewAction->blockSignals(false); - if (d->DockArea) - { - d->DockArea->toggleDockWidgetView(this, Open); - } - - if (Open && TopLevelDockWidgetBefore) - { - CDockWidget::emitTopLevelEventForWidget(TopLevelDockWidgetBefore, false); - } - - // Here we need to call the dockContainer() function again, because if - // this dock widget was unassigned before the call to showDockWidget() then - // it has a dock container now - DockContainer = dockContainer(); - CDockWidget* TopLevelDockWidgetAfter = DockContainer - ? DockContainer->topLevelDockWidget() : nullptr; - CDockWidget::emitTopLevelEventForWidget(TopLevelDockWidgetAfter, true); - CFloatingDockContainer* FloatingContainer = DockContainer->floatingWidget(); - if (FloatingContainer) - { - FloatingContainer->updateWindowTitle(); - } - - if (!Open) - { - emit closed(); - } - emit viewToggled(Open); -} - - -//============================================================================ -void CDockWidget::setDockArea(CDockAreaWidget* DockArea) -{ - d->DockArea = DockArea; - d->ToggleViewAction->setChecked(DockArea != nullptr && !this->isClosed()); -} - - -//============================================================================ -void CDockWidget::saveState(QXmlStreamWriter& s) const -{ - s.writeStartElement("Widget"); - s.writeAttribute("Name", objectName()); - s.writeAttribute("Closed", QString::number(d->Closed ? 1 : 0)); - s.writeEndElement(); -} - - -//============================================================================ -void CDockWidget::flagAsUnassigned() -{ - d->Closed = true; - setParent(d->DockManager); - setVisible(false); - setDockArea(nullptr); - tabWidget()->setParent(this); -} - - -//============================================================================ -bool CDockWidget::event(QEvent *e) -{ - switch (e->type()) - { - case QEvent::Hide: - emit visibilityChanged(false); - break; - - case QEvent::Show: - emit visibilityChanged(geometry().right() >= 0 && geometry().bottom() >= 0); - break; - - case QEvent::WindowTitleChange : - { - const auto title = windowTitle(); - if (d->TabWidget) - { - d->TabWidget->setText(title); - } - if (d->ToggleViewAction) - { - d->ToggleViewAction->setText(title); - } - if (d->DockArea) - { - d->DockArea->markTitleBarMenuOutdated();//update tabs menu - } - emit titleChanged(title); - } - break; - - default: - break; - } - - return Super::event(e); -} - - -#ifndef QT_NO_TOOLTIP -//============================================================================ -void CDockWidget::setTabToolTip(const QString &text) -{ - if (d->TabWidget) - { - d->TabWidget->setToolTip(text); - } - if (d->ToggleViewAction) - { - d->ToggleViewAction->setToolTip(text); - } - if (d->DockArea) - { - d->DockArea->markTitleBarMenuOutdated();//update tabs menu - } -} -#endif - - -//============================================================================ -void CDockWidget::setIcon(const QIcon& Icon) -{ - d->TabWidget->setIcon(Icon); - if (!d->ToggleViewAction->isCheckable()) - { - d->ToggleViewAction->setIcon(Icon); - } -} - - -//============================================================================ -QIcon CDockWidget::icon() const -{ - return d->TabWidget->icon(); -} - - -//============================================================================ -QToolBar* CDockWidget::toolBar() const -{ - return d->ToolBar; -} - - -//============================================================================ -QToolBar* CDockWidget::createDefaultToolBar() -{ - if (!d->ToolBar) - { - d->setupToolBar(); - } - - return d->ToolBar; -} - - -//============================================================================ -void CDockWidget::setToolBar(QToolBar* ToolBar) -{ - if (d->ToolBar) - { - delete d->ToolBar; - } - - d->ToolBar = ToolBar; - d->Layout->insertWidget(0, d->ToolBar); - this->connect(this, SIGNAL(topLevelChanged(bool)), SLOT(setToolbarFloatingStyle(bool))); - setToolbarFloatingStyle(isFloating()); -} - - -//============================================================================ -void CDockWidget::setToolBarStyle(Qt::ToolButtonStyle Style, eState State) -{ - if (StateFloating == State) - { - d->ToolBarStyleFloating = Style; - } - else - { - d->ToolBarStyleDocked = Style; - } - - setToolbarFloatingStyle(isFloating()); -} - - -//============================================================================ -Qt::ToolButtonStyle CDockWidget::toolBarStyle(eState State) const -{ - if (StateFloating == State) - { - return d->ToolBarStyleFloating; - } - else - { - return d->ToolBarStyleDocked; - } -} - - -//============================================================================ -void CDockWidget::setToolBarIconSize(const QSize& IconSize, eState State) -{ - if (StateFloating == State) - { - d->ToolBarIconSizeFloating = IconSize; - } - else - { - d->ToolBarIconSizeDocked = IconSize; - } - - setToolbarFloatingStyle(isFloating()); -} - - -//============================================================================ -QSize CDockWidget::toolBarIconSize(eState State) const -{ - if (StateFloating == State) - { - return d->ToolBarIconSizeFloating; - } - else - { - return d->ToolBarIconSizeDocked; - } -} - - -//============================================================================ -void CDockWidget::setToolbarFloatingStyle(bool Floating) -{ - if (!d->ToolBar) - { - return; - } - - auto IconSize = Floating ? d->ToolBarIconSizeFloating : d->ToolBarIconSizeDocked; - if (IconSize != d->ToolBar->iconSize()) - { - d->ToolBar->setIconSize(IconSize); - } - - auto ButtonStyle = Floating ? d->ToolBarStyleFloating : d->ToolBarStyleDocked; - if (ButtonStyle != d->ToolBar->toolButtonStyle()) - { - d->ToolBar->setToolButtonStyle(ButtonStyle); - } -} - - -//============================================================================ -void CDockWidget::emitTopLevelEventForWidget(CDockWidget* TopLevelDockWidget, bool Floating) -{ - if (TopLevelDockWidget) - { - TopLevelDockWidget->dockAreaWidget()->updateTitleBarVisibility(); - TopLevelDockWidget->emitTopLevelChanged(Floating); - } -} - - -//============================================================================ -void CDockWidget::emitTopLevelChanged(bool Floating) -{ - if (Floating != d->IsFloatingTopLevel) - { - d->IsFloatingTopLevel = Floating; - emit topLevelChanged(d->IsFloatingTopLevel); - } -} - - -//============================================================================ -void CDockWidget::setClosedState(bool Closed) -{ - d->Closed = Closed; -} - - -//============================================================================ -QSize CDockWidget::minimumSizeHint() const -{ - return QSize(60, 40); -} - - -//============================================================================ -void CDockWidget::setFloating() -{ - if (isClosed()) - { - return; - } - d->TabWidget->detachDockWidget(); -} - - -//============================================================================ -void CDockWidget::deleteDockWidget() -{ - dockManager()->removeDockWidget(this); - deleteLater(); - d->Closed = true; -} - - -//============================================================================ -void CDockWidget::closeDockWidget() -{ - closeDockWidgetInternal(true); -} - - -//============================================================================ -bool CDockWidget::closeDockWidgetInternal(bool ForceClose) -{ - if (!ForceClose) - { - emit closeRequested(); - } - - if (!ForceClose && features().testFlag(CDockWidget::CustomCloseHandling)) - { - return false; - } - - if (features().testFlag(CDockWidget::DockWidgetDeleteOnClose)) - { - // If the dock widget is floating, then we check if we also need to - // delete the floating widget - if (isFloating()) - { - CFloatingDockContainer* FloatingWidget = internal::findParent< - CFloatingDockContainer*>(this); - if (FloatingWidget->dockWidgets().count() == 1) - { - FloatingWidget->deleteLater(); - } - else - { - FloatingWidget->hide(); - } - } - deleteDockWidget(); - } - else - { - toggleView(false); - } - - return true; -} - - -} // namespace ads - -//--------------------------------------------------------------------------- -// EOF DockWidget.cpp diff --git a/src/ui/AdvDock/DockWidget.h b/src/ui/AdvDock/DockWidget.h deleted file mode 100644 index 2dc709a0..00000000 --- a/src/ui/AdvDock/DockWidget.h +++ /dev/null @@ -1,488 +0,0 @@ -#ifndef DockWidgetH -#define DockWidgetH -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockWidget.h -/// \author Uwe Kindler -/// \date 26.02.2017 -/// \brief Declaration of CDockWidget class -//============================================================================ - - -//============================================================================ -// INCLUDES -//============================================================================ -#include - -#include "ads_globals.h" - -class QToolBar; -class QXmlStreamWriter; - -namespace ads -{ -struct DockWidgetPrivate; -class CDockWidgetTab; -class CDockManager; -class CDockContainerWidget; -class CDockAreaWidget; -class DockContainerWidgetPrivate; -class CFloatingDockContainer; - -/** - * The QDockWidget class provides a widget that can be docked inside a - * CDockManager or floated as a top-level window on the desktop. - */ -class CDockWidget : public QFrame -{ - Q_OBJECT -private: - DockWidgetPrivate* d; ///< private data (pimpl) - friend struct DockWidgetPrivate; - -private slots: - /** - * Adjusts the toolbar icon sizes according to the floating state - */ - void setToolbarFloatingStyle(bool topLevel); - -protected: - friend class CDockContainerWidget; - friend class CDockAreaWidget; - friend class CFloatingDockContainer; - friend class CDockManager; - friend struct DockManagerPrivate; - friend class DockContainerWidgetPrivate; - friend class CDockAreaTabBar; - friend class CDockWidgetTab; - friend struct DockWidgetTabPrivate; - - /** - * Assigns the dock manager that manages this dock widget - */ - void setDockManager(CDockManager* DockManager); - - /** - * If this dock widget is inserted into a dock area, the dock area will - * be registered on this widget via this function. If a dock widget is - * removed from a dock area, this function will be called with nullptr - * value. - */ - void setDockArea(CDockAreaWidget* DockArea); - - /** - * This function changes the toggle view action without emitting any - * signal - */ - void setToggleViewActionChecked(bool Checked); - - /** - * Saves the state into the given stream - */ - void saveState(QXmlStreamWriter& Stream) const; - - /** - * This is a helper function for the dock manager to flag this widget - * as unassigned. - * When calling the restore function, it may happen, that the saved state - * contains less dock widgets then currently available. All widgets whose - * data is not contained in the saved state, are flagged as unassigned - * after the restore process. If the user shows an unassigned dock widget, - * a floating widget will be created to take up the dock widget. - */ - void flagAsUnassigned(); - - /** - * Call this function to emit a topLevelChanged() signal and to update - * the dock area tool bar visibility - */ - static void emitTopLevelEventForWidget(CDockWidget* TopLevelDockWidget, bool Floating); - - /** - * Use this function to emit a top level changed event. - * Do never use emit topLevelChanged(). Always use this function because - * it only emits a signal if the floating state has really changed - */ - void emitTopLevelChanged(bool Floating); - - /** - * Internal function for modifying the closed state when restoring - * a saved docking state - */ - void setClosedState(bool Closed); - - /** - * Internal toggle view function that does not check if the widget - * already is in the given state - */ - void toggleViewInternal(bool Open); - - /** - * Internal close dock widget implementation. - * The function returns true if the dock widget has been closed or hidden - */ - bool closeDockWidgetInternal(bool ForceClose = false); - -public: - using Super = QFrame; - - enum DockWidgetFeature - { - DockWidgetClosable = 0x01, - DockWidgetMovable = 0x02,///< this feature is not properly implemented yet and is ignored - DockWidgetFloatable = 0x04, - DockWidgetDeleteOnClose = 0x08, ///< deletes the dock widget when it is closed - CustomCloseHandling = 0x10, - DefaultDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable, - AllDockWidgetFeatures = DefaultDockWidgetFeatures | DockWidgetDeleteOnClose | CustomCloseHandling, - NoDockWidgetFeatures = 0x00 - }; - Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature) - - enum eState - { - StateHidden, - StateDocked, - StateFloating - }; - - /** - * Sets the widget for the dock widget to widget. - * The InsertMode defines how the widget is inserted into the dock widget. - * The content of a dock widget should be resizable do a very small size to - * prevent the dock widget from blocking the resizing. To ensure, that a - * dock widget can be resized very well, it is better to insert the content+ - * widget into a scroll area or to provide a widget that is already a scroll - * area or that contains a scroll area. - * If the InsertMode is AutoScrollArea, the DockWidget tries to automatically - * detect how to insert the given widget. If the widget is derived from - * QScrollArea (i.e. an QAbstractItemView), then the widget is inserted - * directly. If the given widget is not a scroll area, the widget will be - * inserted into a scroll area. - * To force insertion into a scroll area, you can also provide the InsertMode - * ForceScrollArea. To prevent insertion into a scroll area, you can - * provide the InsertMode ForceNoScrollArea - */ - enum eInsertMode - { - AutoScrollArea, - ForceScrollArea, - ForceNoScrollArea - }; - - /** - * This mode configures the behavior of the toggle view action. - * If the mode if ActionModeToggle, then the toggle view action is - * a checkable action to show / hide the dock widget. If the mode - * is ActionModeShow, then the action is not checkable an it will - * always show the dock widget if clicked. If the mode is ActionModeShow, - * the user can only close the DockWidget with the close button. - */ - enum eToggleViewActionMode - { - ActionModeToggle,//!< ActionModeToggle - ActionModeShow //!< ActionModeShow - }; - - - /** - * This constructor creates a dock widget with the given title. - * The title is the text that is shown in the window title when the dock - * widget is floating and it is the title that is shown in the titlebar - * or the tab of this dock widget if it is tabified. - * The object name of the dock widget is also set to the title. The - * object name is required by the dock manager to properly save and restore - * the state of the dock widget. That means, the title needs to be unique. - * If your title is not unique or if you would like to change the title - * during runtime, you need to set a unique object name explicitely - * by calling setObjectName() after construction. - * Use the layoutFlags to configure the layout of the dock widget. - */ - CDockWidget(const QString &title, QWidget* parent = 0); - - /** - * Virtual Destructor - */ - virtual ~CDockWidget(); - - /** - * We return a fixed minimum size hint for all dock widgets - */ - virtual QSize minimumSizeHint() const override; - - /** - * Sets the widget for the dock widget to widget. - * The InsertMode defines how the widget is inserted into the dock widget. - * The content of a dock widget should be resizable do a very small size to - * prevent the dock widget from blocking the resizing. To ensure, that a - * dock widget can be resized very well, it is better to insert the content+ - * widget into a scroll area or to provide a widget that is already a scroll - * area or that contains a scroll area. - * If the InsertMode is AutoScrollArea, the DockWidget tries to automatically - * detect how to insert the given widget. If the widget is derived from - * QScrollArea (i.e. an QAbstractItemView), then the widget is inserted - * directly. If the given widget is not a scroll area, the widget will be - * inserted into a scroll area. - * To force insertion into a scroll area, you can also provide the InsertMode - * ForceScrollArea. To prevent insertion into a scroll area, you can - * provide the InsertMode ForceNoScrollArea - */ - void setWidget(QWidget* widget, eInsertMode InsertMode = AutoScrollArea); - - /** - * Remove the widget from the dock and give ownership back to the caller - */ - QWidget* takeWidget(); - - /** - * Returns the widget for the dock widget. This function returns zero if - * the widget has not been set. - */ - QWidget* widget() const; - - /** - * Returns the tab widget of this dock widget that is shown in the dock - * area title bar - */ - CDockWidgetTab* tabWidget() const; - - /** - * Sets, whether the dock widget is movable, closable, and floatable. - */ - void setFeatures(DockWidgetFeatures features); - - /** - * Sets the feature flag for this dock widget if on is true; otherwise - * clears the flag. - */ - void setFeature(DockWidgetFeature flag, bool on); - - /** - * This property holds whether the dock widget is movable, closable, and - * floatable. - * By default, this property is set to a combination of DockWidgetClosable, - * DockWidgetMovable and DockWidgetFloatable. - */ - DockWidgetFeatures features() const; - - /** - * Returns the dock manager that manages the dock widget or 0 if the widget - * has not been assigned to any dock manager yet - */ - CDockManager* dockManager() const; - - /** - * Returns the dock container widget this dock area widget belongs to or 0 - * if this dock widget has not been docked yet - */ - CDockContainerWidget* dockContainer() const; - - /** - * Returns the dock area widget this dock widget belongs to or 0 - * if this dock widget has not been docked yet - */ - CDockAreaWidget* dockAreaWidget() const; - - /** - * This property holds whether the dock widget is floating. - * A dock widget is only floating, if it is the one and only widget inside - * of a floating container. If there are more than one dock widget in a - * floating container, the all dock widgets are docked and not floating. - */ - bool isFloating() const; - - /** - * This function returns true, if this dock widget is in a floating. - * The function returns true, if the dock widget is floating and it also - * returns true if it is docked inside of a floating container. - */ - bool isInFloatingContainer() const; - - /** - * Returns true, if this dock widget is closed. - */ - bool isClosed() const; - - /** - * Returns a checkable action that can be used to show or close this dock widget. - * The action's text is set to the dock widget's window title. - */ - QAction* toggleViewAction() const; - - /** - * Configures the behavior of the toggle view action. - * \see eToggleViewActionMode for a detailed description - */ - void setToggleViewActionMode(eToggleViewActionMode Mode); - - /** - * Sets the dock widget icon that is shown in tabs and in toggle view - * actions - */ - void setIcon(const QIcon& Icon); - - /** - * Returns the icon that has been assigned to the dock widget - */ - QIcon icon() const; - - /** - * If the WithToolBar layout flag is enabled, then this function returns - * the dock widget toolbar. If the flag is disabled, the function returns - * a nullptr. - * This function returns the dock widget top tool bar. - * If no toolbar is assigned, this function returns nullptr. To get a vaild - * toolbar you either need to create a default empty toolbar via - * createDefaultToolBar() function or you need to assign you custom - * toolbar via setToolBar(). - */ - QToolBar* toolBar() const; - - /** - * If you would like to use the default top tool bar, then call this - * function to create the default tool bar. - * After this function the toolBar() function will return a valid toolBar() - * object. - */ - QToolBar* createDefaultToolBar(); - - /** - * Assign a new tool bar that is shown above the content widget. - * The dock widget will become the owner of the tool bar and deletes it - * on destruction - */ - void setToolBar(QToolBar* ToolBar); - - /** - * This function sets the tool button style for the given dock widget state. - * It is possible to switch the tool button style depending on the state. - * If a dock widget is floating, then here are more space and it is - * possible to select a style that requires more space like - * Qt::ToolButtonTextUnderIcon. For the docked state Qt::ToolButtonIconOnly - * might be better. - */ - void setToolBarStyle(Qt::ToolButtonStyle Style, eState State); - - /** - * Returns the tool button style for the given docking state. - * \see setToolBarStyle() - */ - Qt::ToolButtonStyle toolBarStyle(eState State) const; - - /** - * This function sets the tool button icon size for the given state. - * If a dock widget is floating, there is more space an increasing the - * icon size is possible. For docked widgets, small icon sizes, eg. 16 x 16 - * might be better. - */ - void setToolBarIconSize(const QSize& IconSize, eState State); - - /** - * Returns the icon size for a given docking state. - * \see setToolBarIconSize() - */ - QSize toolBarIconSize(eState State) const; - - -#ifndef QT_NO_TOOLTIP - /** - * This is function sets text tooltip for title bar widget - * and tooltip for toggle view action - */ - void setTabToolTip(const QString &text); -#endif - -public: // reimplements QFrame ----------------------------------------------- - /** - * Emits titleChanged signal if title change event occurs - */ - virtual bool event(QEvent *e) override; - -public slots: - /** - * This property controls whether the dock widget is open or closed. - * The toogleViewAction triggers this slot - */ - void toggleView(bool Open = true); - - /** - * This function will make a docked widget floating - */ - void setFloating(); - - /** - * This function will delete the dock widget and its content from the - * docking system - */ - void deleteDockWidget(); - - /** - * Closes the dock widget - */ - void closeDockWidget(); - - -signals: - /** - * This signal is emitted if the dock widget is opened or closed - */ - void viewToggled(bool Open); - - /** - * This signal is emitted if the dock widget is closed - */ - void closed(); - - /** - * This signal is emitted if the window title of this dock widget - * changed - */ - void titleChanged(const QString& Title); - - /** - * This signal is emitted when the floating property changes. - * The topLevel parameter is true if the dock widget is now floating; - * otherwise it is false. - */ - void topLevelChanged(bool topLevel); - - /** - * This signal is emitted, if close is requested - */ - void closeRequested(); - - /** - * This signal is emitted when the dock widget becomes visible (or invisible). - * This happens when the widget is hidden or shown, as well as when it is - * docked in a tabbed dock area and its tab becomes selected or unselected. - */ - void visibilityChanged(bool visible); - - /** - * This signal is emitted when the features property changes. - * The features parameter gives the new value of the property. - */ - void featuresChanged(DockWidgetFeatures features); -}; // class DockWidget -} - // namespace ads -//----------------------------------------------------------------------------- -#endif // DockWidgetH diff --git a/src/ui/AdvDock/DockWidgetTab.cpp b/src/ui/AdvDock/DockWidgetTab.cpp deleted file mode 100644 index e7a91c5a..00000000 --- a/src/ui/AdvDock/DockWidgetTab.cpp +++ /dev/null @@ -1,623 +0,0 @@ -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockWidgetTab.cpp -/// \author Uwe Kindler -/// \date 27.02.2017 -/// \brief Implementation of CDockWidgetTab class -//============================================================================ - - -//============================================================================ -// INCLUDES -//============================================================================ -#include "FloatingDragPreview.h" -#include "ElidingLabel.h" -#include "DockWidgetTab.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "DockWidget.h" -#include "DockAreaWidget.h" -#include "FloatingDockContainer.h" -#include "DockOverlay.h" -#include "DockManager.h" -#include "IconProvider.h" - -#include - -namespace ads -{ - -using tTabLabel = CElidingLabel; - -/** - * Private data class of CDockWidgetTab class (pimpl) - */ -struct DockWidgetTabPrivate -{ - CDockWidgetTab* _this; - CDockWidget* DockWidget; - QLabel* IconLabel = nullptr; - tTabLabel* TitleLabel; - QPoint GlobalDragStartMousePosition; - bool IsActiveTab = false; - CDockAreaWidget* DockArea = nullptr; - eDragState DragState = DraggingInactive; - IFloatingWidget* FloatingWidget = nullptr; - QIcon Icon; - QAbstractButton* CloseButton = nullptr; - QSpacerItem* IconTextSpacer; - QPoint TabDragStartPosition; - - /** - * Private data constructor - */ - DockWidgetTabPrivate(CDockWidgetTab* _public); - - /** - * Creates the complete layout including all controls - */ - void createLayout(); - - /** - * Moves the tab depending on the position in the given mouse event - */ - void moveTab(QMouseEvent* ev); - - /** - * Test function for current drag state - */ - bool isDraggingState(eDragState dragState) const - { - return this->DragState == dragState; - } - - /** - * Returns true if the given global point is inside the title area geometry - * rectangle. - * The position is given as global position. - */ - bool titleAreaGeometryContains(const QPoint& GlobalPos) const - { - return DockArea->titleBarGeometry().contains(DockArea->mapFromGlobal(GlobalPos)); - } - - /** - * Starts floating of the dock widget that belongs to this title bar - * Returns true, if floating has been started and false if floating - * is not possible for any reason - */ - bool startFloating(eDragState DraggingState = DraggingFloatingWidget); - - /** - * Returns true if the given config flag is set - */ - bool testConfigFlag(CDockManager::eConfigFlag Flag) const - { - return CDockManager::configFlags().testFlag(Flag); - } - - /** - * Creates the close button as QPushButton or as QToolButton - */ - QAbstractButton* createCloseButton() const - { - if (testConfigFlag(CDockManager::TabCloseButtonIsToolButton)) - { - auto Button = new QToolButton(); - Button->setAutoRaise(true); - return Button; - } - else - { - return new QPushButton(); - } - } - - template - IFloatingWidget* createFloatingWidget(T* Widget, bool OpaqueUndocking) - { - if (OpaqueUndocking) - { - return new CFloatingDockContainer(Widget); - } - else - { - auto w = new CFloatingDragPreview(Widget); - _this->connect(w, &CFloatingDragPreview::draggingCanceled, [=]() - { - DragState = DraggingInactive; - }); - return w; - } - } -}; -// struct DockWidgetTabPrivate - - -//============================================================================ -DockWidgetTabPrivate::DockWidgetTabPrivate(CDockWidgetTab* _public) : - _this(_public) -{ - -} - - -//============================================================================ -void DockWidgetTabPrivate::createLayout() -{ - TitleLabel = new tTabLabel(); - TitleLabel->setElideMode(Qt::ElideRight); - TitleLabel->setText(DockWidget->windowTitle()); - TitleLabel->setObjectName("dockWidgetTabLabel"); - TitleLabel->setAlignment(Qt::AlignCenter); - - CloseButton = createCloseButton(); - CloseButton->setObjectName("tabCloseButton"); - QIcon CloseIcon = CDockManager::iconProvider().customIcon(TabCloseIcon); - if (CloseIcon.isNull()) - { - // The standard icons do does not look good on high DPI screens - QPixmap normalPixmap = _this->style()->standardPixmap(QStyle::SP_TitleBarCloseButton, 0, CloseButton); - CloseIcon.addPixmap(normalPixmap, QIcon::Normal); - CloseIcon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled); - } - CloseButton->setIcon(CloseIcon); - CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - _this->onDockWidgetFeaturesChanged(); -#ifndef QT_NO_TOOLTIP - CloseButton->setToolTip(QObject::tr("Close Tab")); -#endif - _this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeRequested())); - - QFontMetrics fm(TitleLabel->font()); - int Spacing = qRound(fm.height() / 4.0); - - // Fill the layout - QBoxLayout* Layout = new QBoxLayout(QBoxLayout::LeftToRight); - Layout->setContentsMargins(2 * Spacing,0,0,0); - Layout->setSpacing(0); - _this->setLayout(Layout); - Layout->addWidget(TitleLabel, 1); - Layout->addSpacing(Spacing); - Layout->addWidget(CloseButton); - Layout->addSpacing(qRound(Spacing * 4.0 / 3.0)); - Layout->setAlignment(Qt::AlignCenter); - - TitleLabel->setVisible(true); -} - -//============================================================================ -void DockWidgetTabPrivate::moveTab(QMouseEvent* ev) -{ - ev->accept(); - QPoint Distance = ev->globalPos() - GlobalDragStartMousePosition; - Distance.setY(0); - auto TargetPos = Distance + TabDragStartPosition; - _this->move(TargetPos); - _this->raise(); -} - - -//============================================================================ -bool DockWidgetTabPrivate::startFloating(eDragState DraggingState) -{ - auto dockContainer = DockWidget->dockContainer(); - ADS_PRINT("isFloating " << dockContainer->isFloating()); - ADS_PRINT("areaCount " << dockContainer->dockAreaCount()); - ADS_PRINT("widgetCount " << DockWidget->dockAreaWidget()->dockWidgetsCount()); - // if this is the last dock widget inside of this floating widget, - // then it does not make any sense, to make it floating because - // it is already floating - if (dockContainer->isFloating() - && (dockContainer->visibleDockAreaCount() == 1) - && (DockWidget->dockAreaWidget()->dockWidgetsCount() == 1)) - { - return false; - } - - ADS_PRINT("startFloating"); - DragState = DraggingState; - auto DragStartMousePosition = _this->mapFromGlobal(GlobalDragStartMousePosition); - QSize Size = DockArea->size(); - IFloatingWidget* FloatingWidget = nullptr; - bool OpaqueUndocking = CDockManager::configFlags().testFlag(CDockManager::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 - if (DockArea->dockWidgetsCount() > 1) - { - FloatingWidget = createFloatingWidget(DockWidget, OpaqueUndocking); - } - else - { - FloatingWidget = createFloatingWidget(DockArea, OpaqueUndocking); - } - - if (DraggingFloatingWidget == DraggingState) - { - FloatingWidget->startFloating(DragStartMousePosition, Size, DraggingFloatingWidget, _this); - auto Overlay = DockWidget->dockManager()->containerOverlay(); - Overlay->setAllowedAreas(OuterDockAreas); - this->FloatingWidget = FloatingWidget; - } - else - { - FloatingWidget->startFloating(DragStartMousePosition, Size, DraggingInactive, nullptr); - } - - return true; -} - - -//============================================================================ -CDockWidgetTab::CDockWidgetTab(CDockWidget* DockWidget, QWidget *parent) : - QFrame(parent), - d(new DockWidgetTabPrivate(this)) -{ - setAttribute(Qt::WA_NoMousePropagation, true); - d->DockWidget = DockWidget; - d->createLayout(); -} - -//============================================================================ -CDockWidgetTab::~CDockWidgetTab() -{ - ADS_PRINT("~CDockWidgetTab()"); - delete d; -} - - -//============================================================================ -void CDockWidgetTab::mousePressEvent(QMouseEvent* ev) -{ - if (ev->button() == Qt::LeftButton) - { - ev->accept(); - d->GlobalDragStartMousePosition = ev->globalPos(); - d->DragState = DraggingMousePressed; - emit clicked(); - return; - } - Super::mousePressEvent(ev); -} - - - -//============================================================================ -void CDockWidgetTab::mouseReleaseEvent(QMouseEvent* ev) -{ - if (ev->button() == Qt::LeftButton) - { - auto CurrentDragState = d->DragState; - d->GlobalDragStartMousePosition = QPoint(); - d->DragState = DraggingInactive; - - switch (CurrentDragState) - { - case DraggingTab: - // End of tab moving, emit signal - if (d->DockArea) - { - emit moved(ev->globalPos()); - } - break; - - case DraggingFloatingWidget: - d->FloatingWidget->finishDragging(); - break; - - default:; // do nothing - } - } - - Super::mouseReleaseEvent(ev); -} - - -//============================================================================ -void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev) -{ - if (!(ev->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive)) - { - d->DragState = DraggingInactive; - Super::mouseMoveEvent(ev); - return; - } - - // move floating window - if (d->isDraggingState(DraggingFloatingWidget)) - { - d->FloatingWidget->moveFloating(); - Super::mouseMoveEvent(ev); - return; - } - - // move tab - if (d->isDraggingState(DraggingTab)) - { - // Moving the tab is always allowed because it does not mean moving the - // dock widget around - d->moveTab(ev); - } - - // Maybe a fixed drag distance is better here ? - int DragDistanceY = qAbs(d->GlobalDragStartMousePosition.y() - ev->globalPos().y()); - if (DragDistanceY >= CDockManager::startDragDistance()) - { - // If this is the last dock area in a dock container with only - // one single dock widget it does not make sense to move it to a new - // floating widget and leave this one empty - if (d->DockArea->dockContainer()->isFloating() - && d->DockArea->openDockWidgetsCount() == 1 - && d->DockArea->dockContainer()->visibleDockAreaCount() == 1) - { - return; - } - - // Floating is only allowed for widgets that are movable - if (d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable)) - { - // 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) && !CDockManager::configFlags().testFlag(CDockManager::OpaqueUndocking)) - { - this->move(d->TabDragStartPosition); - } - d->startFloating(); - } - return; - } - else if (d->DockArea->openDockWidgetsCount() > 1 - && (ev->globalPos() - d->GlobalDragStartMousePosition).manhattanLength() >= QApplication::startDragDistance()) // Wait a few pixels before start moving - { - // If we start dragging the tab, we save its inital position to - // restore it later - if (DraggingTab != d->DragState) - { - d->TabDragStartPosition = this->pos(); - } - d->DragState = DraggingTab; - return; - } - - Super::mouseMoveEvent(ev); -} - - -//============================================================================ -void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev) -{ - ev->accept(); - if (d->isDraggingState(DraggingFloatingWidget)) - { - return; - } - - d->GlobalDragStartMousePosition = ev->globalPos(); - QMenu Menu(this); - auto Action = Menu.addAction(tr("Detach"), this, SLOT(detachDockWidget())); - Action->setEnabled(d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable)); - Menu.addSeparator(); - Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested())); - Action->setEnabled(isClosable()); - Menu.addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested())); - Menu.exec(ev->globalPos()); -} - - -//============================================================================ -bool CDockWidgetTab::isActiveTab() const -{ - return d->IsActiveTab; -} - - -//============================================================================ -void CDockWidgetTab::setActiveTab(bool active) -{ - bool DockWidgetClosable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetClosable); - bool ActiveTabHasCloseButton = d->testConfigFlag(CDockManager::ActiveTabHasCloseButton); - bool AllTabsHaveCloseButton = d->testConfigFlag(CDockManager::AllTabsHaveCloseButton); - bool TabHasCloseButton = (ActiveTabHasCloseButton && active) | AllTabsHaveCloseButton; - d->CloseButton->setVisible(DockWidgetClosable && TabHasCloseButton); - if (d->IsActiveTab == active) - { - return; - } - - d->IsActiveTab = active; - style()->unpolish(this); - style()->polish(this); - d->TitleLabel->style()->unpolish(d->TitleLabel); - d->TitleLabel->style()->polish(d->TitleLabel); - update(); - - emit activeTabChanged(); -} - - -//============================================================================ -CDockWidget* CDockWidgetTab::dockWidget() const -{ - return d->DockWidget; -} - - -//============================================================================ -void CDockWidgetTab::setDockAreaWidget(CDockAreaWidget* DockArea) -{ - d->DockArea = DockArea; -} - - -//============================================================================ -CDockAreaWidget* CDockWidgetTab::dockAreaWidget() const -{ - return d->DockArea; -} - - -//============================================================================ -void CDockWidgetTab::setIcon(const QIcon& Icon) -{ - QBoxLayout* Layout = qobject_cast(layout()); - if (!d->IconLabel && Icon.isNull()) - { - return; - } - - if (!d->IconLabel) - { - d->IconLabel = new QLabel(); - d->IconLabel->setAlignment(Qt::AlignVCenter); - d->IconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); - #ifndef QT_NO_TOOLTIP - d->IconLabel->setToolTip(d->TitleLabel->toolTip()); - #endif - Layout->insertWidget(0, d->IconLabel, Qt::AlignVCenter); - Layout->insertSpacing(1, qRound(1.5 * Layout->contentsMargins().left() / 2.0)); - } - else if (Icon.isNull()) - { - // Remove icon label and spacer item - Layout->removeWidget(d->IconLabel); - Layout->removeItem(Layout->itemAt(0)); - delete d->IconLabel; - d->IconLabel = nullptr; - } - - d->Icon = Icon; - if (d->IconLabel) - { - d->IconLabel->setPixmap(Icon.pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, this))); - d->IconLabel->setVisible(true); - } -} - - -//============================================================================ -const QIcon& CDockWidgetTab::icon() const -{ - return d->Icon; -} - - -//============================================================================ -QString CDockWidgetTab::text() const -{ - return d->TitleLabel->text(); -} - - -//============================================================================ -void CDockWidgetTab::mouseDoubleClickEvent(QMouseEvent *event) -{ - // If this is the last dock area in a dock container it does not make - // sense to move it to a new floating widget and leave this one - // empty - if ((!d->DockArea->dockContainer()->isFloating() || d->DockArea->dockWidgetsCount() > 1) - && d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable)) - { - d->GlobalDragStartMousePosition = event->globalPos(); - d->startFloating(DraggingInactive); - } - - Super::mouseDoubleClickEvent(event); -} - - -//============================================================================ -void CDockWidgetTab::setVisible(bool visible) -{ - // Just here for debugging to insert debug output - Super::setVisible(visible); -} - - -//============================================================================ -void CDockWidgetTab::setText(const QString& title) -{ - d->TitleLabel->setText(title); -} - - - -//============================================================================ -bool CDockWidgetTab::isClosable() const -{ - return d->DockWidget && d->DockWidget->features().testFlag(CDockWidget::DockWidgetClosable); -} - - -//=========================================================================== -void CDockWidgetTab::detachDockWidget() -{ - if (!d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable)) - { - return; - } - d->GlobalDragStartMousePosition = QCursor::pos(); - d->startFloating(DraggingInactive); -} - - -//============================================================================ -bool CDockWidgetTab::event(QEvent *e) -{ -#ifndef QT_NO_TOOLTIP - if (e->type() == QEvent::ToolTipChange) - { - const auto text = toolTip(); - d->TitleLabel->setToolTip(text); - } -#endif - return Super::event(e); -} - - -//============================================================================ -void CDockWidgetTab::onDockWidgetFeaturesChanged() -{ - auto Features = d->DockWidget->features(); - auto SizePolicy = d->CloseButton->sizePolicy(); - SizePolicy.setRetainSizeWhenHidden(Features.testFlag(CDockWidget::DockWidgetClosable) - && d->testConfigFlag(CDockManager::RetainTabSizeWhenCloseButtonHidden)); - d->CloseButton->setSizePolicy(SizePolicy); -} - - - - -} // namespace ads -//--------------------------------------------------------------------------- -// EOF DockWidgetTab.cpp diff --git a/src/ui/AdvDock/DockWidgetTab.h b/src/ui/AdvDock/DockWidgetTab.h deleted file mode 100644 index 2527c579..00000000 --- a/src/ui/AdvDock/DockWidgetTab.h +++ /dev/null @@ -1,159 +0,0 @@ -#ifndef DockWidgetTabH -#define DockWidgetTabH -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file DockWidgetTab.h -/// \author Uwe Kindler -/// \date 27.02.2017 -/// \brief Declaration of CDockWidgetTab class -//============================================================================ - - -//============================================================================ -// INCLUDES -//============================================================================ -#include - -#include "ads_globals.h" - -namespace ads -{ -class CDockWidget; -class CDockAreaWidget; -struct DockWidgetTabPrivate; - -/** - * A dock widget tab that shows a title and an icon. - * The dock widget tab is shown in the dock area title bar to switch between - * tabbed dock widgets - */ -class CDockWidgetTab : public QFrame -{ - Q_OBJECT - Q_PROPERTY(bool activeTab READ isActiveTab WRITE setActiveTab NOTIFY activeTabChanged) - -private: - DockWidgetTabPrivate* d; ///< private data (pimpl) - friend struct DockWidgetTabPrivate; - friend class CDockWidget; - void onDockWidgetFeaturesChanged(); - -private slots: - void detachDockWidget(); - -protected: - virtual void mousePressEvent(QMouseEvent* ev) override; - virtual void mouseReleaseEvent(QMouseEvent* ev) override; - virtual void mouseMoveEvent(QMouseEvent* ev) override; - virtual void contextMenuEvent(QContextMenuEvent* ev) override; - - /** - * Double clicking the tab widget makes the assigned dock widget floating - */ - virtual void mouseDoubleClickEvent(QMouseEvent *event) override; - -public: - using Super = QFrame; - /** - * Default Constructor - * param[in] DockWidget The dock widget this title bar belongs to - * param[in] parent The parent widget of this title bar - */ - CDockWidgetTab(CDockWidget* DockWidget, QWidget* parent = 0); - - /** - * Virtual Destructor - */ - virtual ~CDockWidgetTab(); - - /** - * Returns true, if this is the active tab - */ - bool isActiveTab() const; - - /** - * Set this true to make this tab the active tab - */ - void setActiveTab(bool active); - - /** - * Returns the dock widget this title widget belongs to - */ - CDockWidget* dockWidget() const; - - /** - * Sets the dock area widget the dockWidget returned by dockWidget() - * function belongs to. - */ - void setDockAreaWidget(CDockAreaWidget* DockArea); - - /** - * Returns the dock area widget this title bar belongs to. - * \return This function returns 0 if the dock widget that owns this title - * bar widget has not been added to any dock area yet. - */ - CDockAreaWidget* dockAreaWidget() const; - - /** - * Sets the icon to show in title bar - */ - void setIcon(const QIcon& Icon); - - /** - * Returns the icon - */ - const QIcon& icon() const; - - /** - * Returns the tab text - */ - QString text() const; - - /** - * Sets the tab text - */ - void setText(const QString& title); - - /** - * This function returns true if the assigned dock widget is closable - */ - bool isClosable() const; - - /** - * Track event ToolTipChange and set child ToolTip - */ - virtual bool event(QEvent *e) override; - - -public slots: - virtual void setVisible(bool visible) override; - -signals: - void activeTabChanged(); - void clicked(); - void closeRequested(); - void closeOtherTabsRequested(); - void moved(const QPoint& GlobalPos); -}; // class DockWidgetTab -} - // namespace ads -//----------------------------------------------------------------------------- -#endif // DockWidgetTabH diff --git a/src/ui/AdvDock/DockingStateReader.cpp b/src/ui/AdvDock/DockingStateReader.cpp deleted file mode 100644 index 4ae0f3c0..00000000 --- a/src/ui/AdvDock/DockingStateReader.cpp +++ /dev/null @@ -1,30 +0,0 @@ -//============================================================================ -/// \file DockingStateReader.cpp -/// \author Uwe Kindler -/// \date 29.11.2019 -/// \brief Implementation of CDockingStateReader -//============================================================================ - -//============================================================================ -// INCLUDES -//============================================================================ -#include "DockingStateReader.h" - -namespace ads -{ - -//============================================================================ -void CDockingStateReader::setFileVersion(int FileVersion) -{ - m_FileVersion = FileVersion; -} - -//============================================================================ -int CDockingStateReader::fileVersion() const -{ - return m_FileVersion; -} -} // namespace ads - -//--------------------------------------------------------------------------- -// EOF DockingStateReader.cpp diff --git a/src/ui/AdvDock/DockingStateReader.h b/src/ui/AdvDock/DockingStateReader.h deleted file mode 100644 index 5c59dc20..00000000 --- a/src/ui/AdvDock/DockingStateReader.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef DockingStateReaderH -#define DockingStateReaderH -//============================================================================ -/// \file DockingStateReader.h -/// \author Uwe Kindler -/// \date 29.11.2019 -/// \brief Declaration of CDockingStateReader -//============================================================================ - -//============================================================================ -// INCLUDES -//============================================================================ -#include - -namespace ads -{ - -/** - * Extends QXmlStreamReader with file version information - */ -class CDockingStateReader : public QXmlStreamReader -{ -private: - int m_FileVersion; - -public: - using QXmlStreamReader::QXmlStreamReader; - - /** - * Set the file version for this state reader - */ - void setFileVersion(int FileVersion); - - /** - * Returns the file version set via setFileVersion - */ - int fileVersion() const; -}; - -} // namespace ads - -//--------------------------------------------------------------------------- -#endif // DockingStateReaderH diff --git a/src/ui/AdvDock/ElidingLabel.cpp b/src/ui/AdvDock/ElidingLabel.cpp deleted file mode 100644 index edc71469..00000000 --- a/src/ui/AdvDock/ElidingLabel.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file ElidingLabel.cpp -/// \author Uwe Kindler -/// \date 05.11.2018 -/// \brief Implementation of CElidingLabel -//============================================================================ - -//============================================================================ -// INCLUDES -//============================================================================ -#include "ElidingLabel.h" -#include - - -namespace ads -{ -/** - * Private data of public CClickableLabel - */ -struct ElidingLabelPrivate -{ - CElidingLabel* _this; - Qt::TextElideMode ElideMode = Qt::ElideNone; - QString Text; - - ElidingLabelPrivate(CElidingLabel* _public) : _this(_public) {} - - void elideText(int Width); - - /** - * Convenience function to check if the - */ - bool isModeElideNone() const - { - return Qt::ElideNone == ElideMode; - } -}; - - -//============================================================================ -void ElidingLabelPrivate::elideText(int Width) -{ - if (isModeElideNone()) - { - return; - } - QFontMetrics fm = _this->fontMetrics(); - QString str = fm.elidedText(Text, ElideMode, Width - _this->margin() * 2 - _this->indent()); - if (str == "...") - { - str = Text.at(0); - } - _this->QLabel::setText(str); -} - - -//============================================================================ -CElidingLabel::CElidingLabel(QWidget* parent, Qt::WindowFlags f) - : QLabel(parent, f), - d(new ElidingLabelPrivate(this)) -{ - -} - - -//============================================================================ -CElidingLabel::CElidingLabel(const QString& text, QWidget* parent, Qt::WindowFlags f) - : QLabel(text, parent,f), - d(new ElidingLabelPrivate(this)) -{ - d->Text = text; -#ifndef QT_NO_TOOLTIP - setToolTip(text); -#endif -} - - -//============================================================================ -CElidingLabel::~CElidingLabel() -{ - delete d; -} - - -//============================================================================ -Qt::TextElideMode CElidingLabel::elideMode() const -{ - return d->ElideMode; -} - - -//============================================================================ -void CElidingLabel::setElideMode(Qt::TextElideMode mode) -{ - d->ElideMode = mode; - d->elideText(size().width()); -} - - -//============================================================================ -void CElidingLabel::mouseReleaseEvent(QMouseEvent* event) -{ - Super::mouseReleaseEvent(event); - if (event->button() != Qt::LeftButton) - { - return; - } - - emit clicked(); -} - - -//============================================================================ -void CElidingLabel::mouseDoubleClickEvent( QMouseEvent *ev ) -{ - Q_UNUSED(ev) - emit doubleClicked(); - Super::mouseDoubleClickEvent(ev); -} - - -//============================================================================ -void CElidingLabel::resizeEvent(QResizeEvent *event) -{ - if (!d->isModeElideNone()) - { - d->elideText(event->size().width()); - } - Super::resizeEvent(event); -} - - -//============================================================================ -QSize CElidingLabel::minimumSizeHint() const -{ -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - if (!pixmap().isNull() || d->isModeElideNone()) -#else - if (pixmap() || d->isModeElideNone()) -#endif - { - return QLabel::minimumSizeHint(); - } - const QFontMetrics &fm = fontMetrics(); - #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) - QSize size(fm.horizontalAdvance(d->Text.left(2) + "..."), fm.height()); - #else - QSize size(fm.width(d->Text.left(2) + "…"), fm.height()); - #endif - return size; -} - - -//============================================================================ -QSize CElidingLabel::sizeHint() const -{ -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - if (!pixmap().isNull() || d->isModeElideNone()) -#else - if (pixmap() || d->isModeElideNone()) -#endif - { - return QLabel::sizeHint(); - } - const QFontMetrics& fm = fontMetrics(); - #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) - QSize size(fm.horizontalAdvance(d->Text), QLabel::sizeHint().height()); - #else - QSize size(fm.width(d->Text), QLabel::sizeHint().height()); - #endif - return size; -} - - -//============================================================================ -void CElidingLabel::setText(const QString &text) -{ - if (d->isModeElideNone()) - { - Super::setText(text); - } - else - { - d->Text = text; -#ifndef QT_NO_TOOLTIP - setToolTip( text ); -#endif - d->elideText(this->size().width()); - } -} - - -//============================================================================ -QString CElidingLabel::text() const -{ - return d->Text; -} -} // namespace QtLabb - -//--------------------------------------------------------------------------- -// EOF ClickableLabel.cpp diff --git a/src/ui/AdvDock/ElidingLabel.h b/src/ui/AdvDock/ElidingLabel.h deleted file mode 100644 index e424f2df..00000000 --- a/src/ui/AdvDock/ElidingLabel.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef ElidingLabelH -#define ElidingLabelH -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file ElidingLabel.h -/// \author Uwe Kindler -/// \date 05.11.2018 -/// \brief Declaration of CElidingLabel -//============================================================================ - -//============================================================================ -// INCLUDES -//============================================================================ -#include - -#include "ads_globals.h" - -namespace ads -{ -struct ElidingLabelPrivate; - -/** - * A QLabel that supports eliding text. - * Because the functions setText() and text() are no virtual functions setting - * and reading the text via a pointer to the base class QLabel does not work - * properly - */ -class CElidingLabel : public QLabel -{ - Q_OBJECT -private: - ElidingLabelPrivate* d; - friend struct ElidingLabelPrivate; - -protected: - virtual void mouseReleaseEvent(QMouseEvent* event) override; - virtual void resizeEvent( QResizeEvent *event ) override; - virtual void mouseDoubleClickEvent( QMouseEvent *ev ) override; - -public: - using Super = QLabel; - - CElidingLabel(QWidget* parent = 0, Qt::WindowFlags f = Qt::Widget); - CElidingLabel(const QString& text, QWidget* parent = 0, Qt::WindowFlags f = Qt::Widget); - virtual ~CElidingLabel(); - - /** - * Returns the text elide mode. - * The default mode is ElideNone - */ - Qt::TextElideMode elideMode() const; - - /** - * Sets the text elide mode - */ - void setElideMode(Qt::TextElideMode mode); - - -public: // reimplements QLabel ---------------------------------------------- - virtual QSize minimumSizeHint() const override; - virtual QSize sizeHint() const override; - void setText(const QString &text); - QString text() const; - -signals: - /** - * This signal is emitted if the user clicks on the label (i.e. pressed - * down then released while the mouse cursor is inside the label) - */ - void clicked(); - - /** - * This signal is emitted if the user does a double click on the label - */ - void doubleClicked(); -}; //class CElidingLabel - -} // namespace QtLabb - -//--------------------------------------------------------------------------- -#endif // ElidingLabelH diff --git a/src/ui/AdvDock/FloatingDockContainer.cpp b/src/ui/AdvDock/FloatingDockContainer.cpp deleted file mode 100644 index 644f91c5..00000000 --- a/src/ui/AdvDock/FloatingDockContainer.cpp +++ /dev/null @@ -1,629 +0,0 @@ -/******************************************************************************* - ** Qt Advanced Docking System - ** Copyright (C) 2017 Uwe Kindler - ** - ** This library is free software; you can redistribute it and/or - ** modify it under the terms of the GNU Lesser General Public - ** License as published by the Free Software Foundation; either - ** version 2.1 of the License, or (at your option) any later version. - ** - ** This library is distributed in the hope that it will be useful, - ** but WITHOUT ANY WARRANTY; without even the implied warranty of - ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - ** Lesser General Public License for more details. - ** - ** You should have received a copy of the GNU Lesser General Public - ** License along with this library; If not, see . - ******************************************************************************/ - -//============================================================================ -/// \file FloatingDockContainer.cpp -/// \author Uwe Kindler -/// \date 01.03.2017 -/// \brief Implementation of CFloatingDockContainer class -//============================================================================ - -//============================================================================ -// INCLUDES -//============================================================================ -#include "FloatingDockContainer.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "DockContainerWidget.h" -#include "DockAreaWidget.h" -#include "DockManager.h" -#include "DockWidget.h" -#include "DockOverlay.h" - -#ifdef Q_OS_LINUX -#include "linux/FloatingWidgetTitleBar.h" -#include -#endif - -namespace ads -{ -static unsigned int zOrderCounter = 0; -/** - * Private data class of CFloatingDockContainer class (pimpl) - */ -struct FloatingDockContainerPrivate -{ - CFloatingDockContainer *_this; - CDockContainerWidget *DockContainer; - unsigned int zOrderIndex = ++zOrderCounter; - QPointer DockManager; - eDragState DraggingState = DraggingInactive; - QPoint DragStartMousePosition; - CDockContainerWidget *DropContainer = nullptr; - CDockAreaWidget *SingleDockArea = nullptr; -#ifdef Q_OS_LINUX - QWidget* MouseEventHandler = nullptr; - CFloatingWidgetTitleBar* TitleBar = nullptr; -#endif - - /** - * Private data constructor - */ - FloatingDockContainerPrivate(CFloatingDockContainer *_public); - - void titleMouseReleaseEvent(); - void updateDropOverlays(const QPoint &GlobalPos); - - /** - * Tests is a certain state is active - */ - bool isState(eDragState StateId) const - { - return StateId == DraggingState; - } - - void setState(eDragState StateId) - { - DraggingState = StateId; - } - - void setWindowTitle(const QString &Text) - { -#ifdef Q_OS_LINUX - TitleBar->setTitle(Text); -#else - _this->setWindowTitle(Text); -#endif - } -}; -// struct FloatingDockContainerPrivate - -//============================================================================ -FloatingDockContainerPrivate::FloatingDockContainerPrivate( - CFloatingDockContainer *_public) : - _this(_public) -{ - -} - -//============================================================================ -void FloatingDockContainerPrivate::titleMouseReleaseEvent() -{ - setState(DraggingInactive); - if (!DropContainer) - { - return; - } - - if (DockManager->dockAreaOverlay()->dropAreaUnderCursor() - != InvalidDockWidgetArea - || DockManager->containerOverlay()->dropAreaUnderCursor() - != InvalidDockWidgetArea) - { - // Resize the floating widget to the size of the highlighted drop area - // rectangle - CDockOverlay *Overlay = DockManager->containerOverlay(); - if (!Overlay->dropOverlayRect().isValid()) - { - Overlay = DockManager->dockAreaOverlay(); - } - - QRect Rect = Overlay->dropOverlayRect(); - int FrameWidth = (_this->frameSize().width() - _this->rect().width()) - / 2; - int TitleBarHeight = _this->frameSize().height() - - _this->rect().height() - FrameWidth; - if (Rect.isValid()) - { - QPoint TopLeft = Overlay->mapToGlobal(Rect.topLeft()); - TopLeft.ry() += TitleBarHeight; - _this->setGeometry( - QRect(TopLeft, - QSize(Rect.width(), Rect.height() - TitleBarHeight))); - QApplication::processEvents(); - } - DropContainer->dropFloatingWidget(_this, QCursor::pos()); - } - - DockManager->containerOverlay()->hideOverlay(); - DockManager->dockAreaOverlay()->hideOverlay(); -} - -//============================================================================ -void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos) -{ - if (!_this->isVisible() || !DockManager) - { - return; - } - - auto Containers = DockManager->dockContainers(); - CDockContainerWidget *TopContainer = nullptr; - for (auto ContainerWidget : Containers) - { - if (!ContainerWidget->isVisible()) - { - continue; - } - - if (DockContainer == ContainerWidget) - { - continue; - } - - QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos); - if (ContainerWidget->rect().contains(MappedPos)) - { - if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer)) - { - TopContainer = ContainerWidget; - } - } - } - - DropContainer = TopContainer; - auto ContainerOverlay = DockManager->containerOverlay(); - auto DockAreaOverlay = DockManager->dockAreaOverlay(); - - if (!TopContainer) - { - ContainerOverlay->hideOverlay(); - DockAreaOverlay->hideOverlay(); - return; - } - - int VisibleDockAreas = TopContainer->visibleDockAreaCount(); - ContainerOverlay->setAllowedAreas( - VisibleDockAreas > 1 ? OuterDockAreas : AllDockAreas); - DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer); - ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea); - auto DockArea = TopContainer->dockAreaAt(GlobalPos); - if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0) - { - DockAreaOverlay->enableDropPreview(true); - DockAreaOverlay->setAllowedAreas( - (VisibleDockAreas == 1) ? NoDockWidgetArea : AllDockAreas); - DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea); - - // 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)) - { - DockAreaOverlay->enableDropPreview(false); - ContainerOverlay->enableDropPreview(true); - } - else - { - ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area); - } - } - else - { - DockAreaOverlay->hideOverlay(); - } -} - -//============================================================================ -CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) : - tFloatingWidgetBase(DockManager), - d(new FloatingDockContainerPrivate(this)) -{ - d->DockManager = DockManager; - d->DockContainer = new CDockContainerWidget(DockManager, this); - connect(d->DockContainer, SIGNAL(dockAreasAdded()), this, - SLOT(onDockAreasAddedOrRemoved())); - connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this, - SLOT(onDockAreasAddedOrRemoved())); - -#ifdef Q_OS_LINUX - d->TitleBar = new CFloatingWidgetTitleBar(this); - setWindowFlags(windowFlags() | Qt::Tool); - QDockWidget::setWidget(d->DockContainer); - QDockWidget::setFloating(true); - QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures); - setTitleBarWidget(d->TitleBar); - connect(d->TitleBar, SIGNAL(closeRequested()), SLOT(close())); -#else - setWindowFlags( - Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint); - QBoxLayout *l = new QBoxLayout(QBoxLayout::TopToBottom); - l->setContentsMargins(0, 0, 0, 0); - l->setSpacing(0); - setLayout(l); - l->addWidget(d->DockContainer); -#endif - - DockManager->registerFloatingWidget(this); -} - -//============================================================================ -CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget *DockArea) : - CFloatingDockContainer(DockArea->dockManager()) -{ - d->DockContainer->addDockArea(DockArea); -#ifdef Q_OS_LINUX - d->TitleBar->enableCloseButton(isClosable()); -#endif - auto TopLevelDockWidget = topLevelDockWidget(); - if (TopLevelDockWidget) - { - TopLevelDockWidget->emitTopLevelChanged(true); - } -} - -//============================================================================ -CFloatingDockContainer::CFloatingDockContainer(CDockWidget *DockWidget) : - CFloatingDockContainer(DockWidget->dockManager()) -{ - d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget); -#ifdef Q_OS_LINUX - d->TitleBar->enableCloseButton(isClosable()); -#endif - auto TopLevelDockWidget = topLevelDockWidget(); - if (TopLevelDockWidget) - { - TopLevelDockWidget->emitTopLevelChanged(true); - } -} - -//============================================================================ -CFloatingDockContainer::~CFloatingDockContainer() -{ - ADS_PRINT("~CFloatingDockContainer"); - if (d->DockManager) - { - d->DockManager->removeFloatingWidget(this); - } - delete d; -} - -//============================================================================ -CDockContainerWidget* CFloatingDockContainer::dockContainer() const -{ - return d->DockContainer; -} - -//============================================================================ -void CFloatingDockContainer::changeEvent(QEvent *event) -{ - QWidget::changeEvent(event); - if ((event->type() == QEvent::ActivationChange) && isActiveWindow()) - { - ADS_PRINT("FloatingWidget::changeEvent QEvent::ActivationChange "); - d->zOrderIndex = ++zOrderCounter; - return; - } -} - -//============================================================================ -void CFloatingDockContainer::moveEvent(QMoveEvent *event) -{ - QWidget::moveEvent(event); - switch (d->DraggingState) - { - case DraggingMousePressed: - d->setState(DraggingFloatingWidget); - d->updateDropOverlays(QCursor::pos()); - break; - - case DraggingFloatingWidget: - d->updateDropOverlays(QCursor::pos()); -#ifdef Q_OS_MACOS - // In OSX 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); -#endif - break; - default: - break; - } -} - -//============================================================================ -void CFloatingDockContainer::closeEvent(QCloseEvent *event) -{ - ADS_PRINT("CFloatingDockContainer closeEvent"); - d->setState(DraggingInactive); - event->ignore(); - - if (isClosable()) - { - auto TopLevelDockWidget = topLevelDockWidget(); - if (TopLevelDockWidget && TopLevelDockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose)) - { - if (!TopLevelDockWidget->closeDockWidgetInternal()) - { - return; - } - } - - // In Qt version after 5.9.2 there seems to be a bug that causes the - // QWidget::event() function to not receive any NonClientArea mouse - // events anymore after a close/show cycle. The bug is reported here: - // https://bugreports.qt.io/browse/QTBUG-73295 - // The following code is a workaround for Qt versions > 5.9.2 that seems - // to work - // Starting from Qt version 5.12.2 this seems to work again. But - // now the QEvent::NonClientAreaMouseButtonPress function returns always - // Qt::RightButton even if the left button was pressed - this->hide(); - } -} - -//============================================================================ -void CFloatingDockContainer::hideEvent(QHideEvent *event) -{ - Super::hideEvent(event); - if (event->spontaneous()) - { - return; - } - - // Prevent toogleView() events during restore state - if (d->DockManager->isRestoringState()) - { - return; - } - - for (auto DockArea : d->DockContainer->openedDockAreas()) - { - for (auto DockWidget : DockArea->openedDockWidgets()) - { - DockWidget->toggleView(false); - } - } -} - -//============================================================================ -void CFloatingDockContainer::showEvent(QShowEvent *event) -{ - Super::showEvent(event); -} - -//============================================================================ -bool CFloatingDockContainer::event(QEvent *e) -{ - switch (d->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 (e->type() - == QEvent::NonClientAreaMouseButtonPress /*&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)*/) - { - ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type()); - d->setState(DraggingMousePressed); - } -#else - if (e->type() == QEvent::NonClientAreaMouseButtonPress && QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)) - { - ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type()); - d->setState(DraggingMousePressed); - } -#endif - } - break; - - case DraggingMousePressed: - switch (e->type()) - { - case QEvent::NonClientAreaMouseButtonDblClick: - ADS_PRINT("FloatingWidget::event 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 (e->type() == QEvent::NonClientAreaMouseButtonRelease) - { - ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease"); - d->titleMouseReleaseEvent(); - } - break; - - default: - break; - } - -#if (ADS_DEBUG_LEVEL > 0) - qDebug() << "CFloatingDockContainer::event " << e->type(); -#endif - return QWidget::event(e); -} - - -//============================================================================ -void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos, - const QSize &Size, eDragState DragState, QWidget *MouseEventHandler) -{ -#ifndef Q_OS_LINUX - Q_UNUSED(MouseEventHandler) -#endif - resize(Size); - d->setState(DragState); - d->DragStartMousePosition = DragStartMousePos; -#ifdef Q_OS_LINUX - if (DraggingFloatingWidget == DragState) - { - setAttribute(Qt::WA_X11NetWmWindowTypeDock, true); - d->MouseEventHandler = MouseEventHandler; - if (d->MouseEventHandler) - { - d->MouseEventHandler->grabMouse(); - } - } -#endif - moveFloating(); - show(); -} - -//============================================================================ -void CFloatingDockContainer::moveFloating() -{ - int BorderSize = (frameSize().width() - size().width()) / 2; - const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition - - QPoint(BorderSize, 0); - move(moveToPos); -} - -//============================================================================ -bool CFloatingDockContainer::isClosable() const -{ - return d->DockContainer->features().testFlag( - CDockWidget::DockWidgetClosable); -} - -//============================================================================ -void CFloatingDockContainer::onDockAreasAddedOrRemoved() -{ - ADS_PRINT("CFloatingDockContainer::onDockAreasAddedOrRemoved()"); - auto TopLevelDockArea = d->DockContainer->topLevelDockArea(); - if (TopLevelDockArea) - { - d->SingleDockArea = TopLevelDockArea; - d->setWindowTitle( - d->SingleDockArea->currentDockWidget()->windowTitle()); - connect(d->SingleDockArea, SIGNAL(currentChanged(int)), this, - SLOT(onDockAreaCurrentChanged(int))); - } - else - { - if (d->SingleDockArea) - { - disconnect(d->SingleDockArea, SIGNAL(currentChanged(int)), this, - SLOT(onDockAreaCurrentChanged(int))); - d->SingleDockArea = nullptr; - } - d->setWindowTitle(qApp->applicationDisplayName()); - } -} - -//============================================================================ -void CFloatingDockContainer::updateWindowTitle() -{ - auto TopLevelDockArea = d->DockContainer->topLevelDockArea(); - if (TopLevelDockArea) - { - d->setWindowTitle(TopLevelDockArea->currentDockWidget()->windowTitle()); - } - else - { - d->setWindowTitle(qApp->applicationDisplayName()); - } -} - -//============================================================================ -void CFloatingDockContainer::onDockAreaCurrentChanged(int Index) -{ - Q_UNUSED(Index); - d->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle()); -} - -//============================================================================ -bool CFloatingDockContainer::restoreState(CDockingStateReader &Stream, - bool Testing) -{ - if (!d->DockContainer->restoreState(Stream, Testing)) - { - return false; - } - - onDockAreasAddedOrRemoved(); - return true; -} - -//============================================================================ -bool CFloatingDockContainer::hasTopLevelDockWidget() const -{ - return d->DockContainer->hasTopLevelDockWidget(); -} - -//============================================================================ -CDockWidget* CFloatingDockContainer::topLevelDockWidget() const -{ - return d->DockContainer->topLevelDockWidget(); -} - -//============================================================================ -QList CFloatingDockContainer::dockWidgets() const -{ - return d->DockContainer->dockWidgets(); -} - -//============================================================================ -void CFloatingDockContainer::finishDragging() -{ - ADS_PRINT("CFloatingDockContainer::finishDragging"); -#ifdef Q_OS_LINUX - setAttribute(Qt::WA_X11NetWmWindowTypeDock, false); - setWindowOpacity(1); - activateWindow(); - if (d->MouseEventHandler) - { - d->MouseEventHandler->releaseMouse(); - d->MouseEventHandler = nullptr; - } -#endif - d->titleMouseReleaseEvent(); -} - -} // namespace ads - -//--------------------------------------------------------------------------- -// EOF FloatingDockContainer.cpp diff --git a/src/ui/AdvDock/FloatingDockContainer.h b/src/ui/AdvDock/FloatingDockContainer.h deleted file mode 100644 index c970cc8f..00000000 --- a/src/ui/AdvDock/FloatingDockContainer.h +++ /dev/null @@ -1,244 +0,0 @@ -#ifndef FloatingDockContainerH -#define FloatingDockContainerH -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file FloatingDockContainer.h -/// \author Uwe Kindler -/// \date 01.03.2017 -/// \brief Declaration of CFloatingDockContainer class -//============================================================================ - -//============================================================================ -// INCLUDES -//============================================================================ - -#include - -#ifdef Q_OS_LINUX -#include -#define tFloatingWidgetBase QDockWidget -#else -#include -#define tFloatingWidgetBase QWidget -#endif - -#include "ads_globals.h" - -class CDockingStateReader; - -namespace ads -{ -struct FloatingDockContainerPrivate; -class CDockManager; -struct DockManagerPrivate; -class CDockAreaWidget; -class CDockContainerWidget; -class CDockWidget; -class CDockManager; -class CDockAreaTabBar; -class CDockWidgetTab; -struct DockWidgetTabPrivate; -class CDockAreaTitleBar; -struct DockAreaTitleBarPrivate; -class CFloatingWidgetTitleBar; -class CDockingStateReader; - -/** - * Pure virtual interface for floating widgets. - * This interface is used for opaque and non-opaque undocking. If opaque - * undocking is used, the a real CFloatingDockContainer widget will be created - */ -class IFloatingWidget -{ -public: - /** - * Starts floating. - * This function should get called typically from a mouse press event - * handler - */ - virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size, - eDragState DragState, QWidget* MouseEventHandler) = 0; - - /** - * Moves the widget to a new position relative to the position given when - * startFloating() was called. - * This function should be called from a mouse mouve event handler to - * move the floating widget on mouse move events. - */ - virtual void moveFloating() = 0; - - /** - * Tells the widget that to finish dragging if the mouse is released. - * This function should be called from a mouse release event handler - * to finish the dragging - */ - virtual void finishDragging() = 0; -}; - - -/** - * This implements a floating widget that is a dock container that accepts - * docking of dock widgets like the main window and that can be docked into - * another dock container. - * Every floating window of the docking system is a FloatingDockContainer. - */ -class CFloatingDockContainer : public tFloatingWidgetBase, public IFloatingWidget -{ - Q_OBJECT -private: - FloatingDockContainerPrivate* d; ///< private data (pimpl) - friend struct FloatingDockContainerPrivate; - friend class CDockManager; - friend struct DockManagerPrivate; - friend class CDockAreaTabBar; - friend struct DockWidgetTabPrivate; - friend class CDockWidgetTab; - friend class CDockAreaTitleBar; - friend struct DockAreaTitleBarPrivate; - friend class CDockWidget; - friend class CDockAreaWidget; - friend class CFloatingWidgetTitleBar; - -private slots: - void onDockAreasAddedOrRemoved(); - void onDockAreaCurrentChanged(int Index); - -protected: - /** - * Starts floating at the given global position. - * Use moveToGlobalPos() to move the widget to a new position - * depending on the start position given in Pos parameter - */ - virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size, - eDragState DragState, QWidget* MouseEventHandler) override; - - /** - * Call this function to start dragging the floating widget - */ - void startDragging(const QPoint& DragStartMousePos, const QSize& Size, - QWidget* MouseEventHandler) - { - startFloating(DragStartMousePos, Size, DraggingFloatingWidget, MouseEventHandler); - } - - /** - * Call this function if you explicitly want to signal that dragging has - * finished - */ - virtual void finishDragging() override; - - /** - * Call this function if you just want to initialize the position - * and size of the floating widget - */ - void initFloatingGeometry(const QPoint& DragStartMousePos, const QSize& Size) - { - startFloating(DragStartMousePos, Size, DraggingInactive, nullptr); - } - - /** - * Moves the widget to a new position relative to the position given when - * startFloating() was called - */ - void moveFloating(); - - /** - * Restores the state from given stream. - * If Testing is true, the function only parses the data from the given - * stream but does not restore anything. You can use this check for - * faulty files before you start restoring the state - */ - bool restoreState(CDockingStateReader& Stream, bool Testing); - - /** - * Call this function to update the window title - */ - void updateWindowTitle(); - - -protected: // reimplements QWidget - virtual void changeEvent(QEvent *event) override; - virtual void moveEvent(QMoveEvent *event) override; - virtual bool event(QEvent *e) override; - virtual void closeEvent(QCloseEvent *event) override; - virtual void hideEvent(QHideEvent *event) override; - virtual void showEvent(QShowEvent *event) override; - -public: - using Super = QWidget; - - /** - * Create empty floating widget - required for restore state - */ - CFloatingDockContainer(CDockManager* DockManager); - - /** - * Create floating widget with the given dock area - */ - CFloatingDockContainer(CDockAreaWidget* DockArea); - - /** - * Create floating widget with the given dock widget - */ - CFloatingDockContainer(CDockWidget* DockWidget); - - /** - * Virtual Destructor - */ - virtual ~CFloatingDockContainer(); - - /** - * Access function for the internal dock container - */ - CDockContainerWidget* dockContainer() const; - - /** - * This function returns true, if it can be closed. - * It can be closed, if all dock widgets in all dock areas can be closed - */ - bool isClosable() const; - - /** - * This function returns true, if this floating widget has only one single - * visible dock widget in a single visible dock area. - * The single dock widget is a real top level floating widget because no - * other widgets are docked. - */ - bool hasTopLevelDockWidget() const; - - /** - * This function returns the first dock widget in the first dock area. - * If the function hasSingleDockWidget() returns true, then this function - * returns this single dock widget. - */ - CDockWidget* topLevelDockWidget() const; - - /** - * This function returns a list of all dock widget in this floating widget. - * This is a simple convenience function that simply calls the dockWidgets() - * function of the internal container widget. - */ - QList dockWidgets() const; -}; // class FloatingDockContainer -} - // namespace ads -//----------------------------------------------------------------------------- -#endif // FloatingDockContainerH diff --git a/src/ui/AdvDock/FloatingDragPreview.cpp b/src/ui/AdvDock/FloatingDragPreview.cpp deleted file mode 100644 index aec94490..00000000 --- a/src/ui/AdvDock/FloatingDragPreview.cpp +++ /dev/null @@ -1,405 +0,0 @@ -//============================================================================ -/// \file FloatingDragPreview.cpp -/// \author Uwe Kindler -/// \date 26.11.2019 -/// \brief Implementation of CFloatingDragPreview -//============================================================================ - -//============================================================================ -// INCLUDES -//============================================================================ -#include "FloatingDragPreview.h" -#include - -#include -#include -#include -#include - -#include "DockWidget.h" -#include "DockAreaWidget.h" -#include "DockManager.h" -#include "DockContainerWidget.h" -#include "DockOverlay.h" - -namespace ads -{ - -/** - * Private data class (pimpl) - */ -struct FloatingDragPreviewPrivate -{ - CFloatingDragPreview *_this; - QWidget* Content; - CDockAreaWidget* ContentSourceArea = nullptr; - CDockContainerWidget* ContenSourceContainer = nullptr; - QPoint DragStartMousePosition; - CDockManager* DockManager; - CDockContainerWidget *DropContainer = nullptr; - qreal WindowOpacity; - bool Hidden = false; - QPixmap ContentPreviewPixmap; - - - /** - * Private data constructor - */ - FloatingDragPreviewPrivate(CFloatingDragPreview *_public); - void updateDropOverlays(const QPoint &GlobalPos); - - void setHidden(bool Value) - { - Hidden = Value; - _this->update(); - } - - /** - * Cancel dragging and emit the draggingCanceled event - */ - void cancelDragging() - { - emit _this->draggingCanceled(); - DockManager->containerOverlay()->hideOverlay(); - DockManager->dockAreaOverlay()->hideOverlay(); - _this->close(); - } -}; -// struct LedArrayPanelPrivate - - -//============================================================================ -void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) -{ - if (!_this->isVisible() || !DockManager) - { - return; - } - - auto Containers = DockManager->dockContainers(); - CDockContainerWidget *TopContainer = nullptr; - for (auto ContainerWidget : Containers) - { - if (!ContainerWidget->isVisible()) - { - continue; - } - - /*if (DockContainer == ContainerWidget) - { - continue; - }*/ - - QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos); - if (ContainerWidget->rect().contains(MappedPos)) - { - if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer)) - { - TopContainer = ContainerWidget; - } - } - } - - DropContainer = TopContainer; - auto ContainerOverlay = DockManager->containerOverlay(); - auto DockAreaOverlay = DockManager->dockAreaOverlay(); - auto DockDropArea = DockAreaOverlay->dropAreaUnderCursor(); - auto ContainerDropArea = ContainerOverlay->dropAreaUnderCursor(); - - if (!TopContainer) - { - ContainerOverlay->hideOverlay(); - DockAreaOverlay->hideOverlay(); - if (CDockManager::configFlags().testFlag(CDockManager::DragPreviewIsDynamic)) - { - setHidden(false); - } - return; - } - - int VisibleDockAreas = TopContainer->visibleDockAreaCount(); - ContainerOverlay->setAllowedAreas( - VisibleDockAreas > 1 ? OuterDockAreas : AllDockAreas); - DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer); - ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea); - auto DockArea = TopContainer->dockAreaAt(GlobalPos); - if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0 && DockArea != ContentSourceArea) - { - DockAreaOverlay->enableDropPreview(true); - DockAreaOverlay->setAllowedAreas( - (VisibleDockAreas == 1) ? NoDockWidgetArea : AllDockAreas); - DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea); - - // 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)) - { - DockAreaOverlay->enableDropPreview(false); - ContainerOverlay->enableDropPreview(true); - } - else - { - ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area); - } - } - else - { - DockAreaOverlay->hideOverlay(); - if (DockArea == ContentSourceArea && InvalidDockWidgetArea == ContainerDropArea) - { - DropContainer = nullptr; - } - } - - if (CDockManager::configFlags().testFlag(CDockManager::DragPreviewIsDynamic)) - { - setHidden(DockDropArea != InvalidDockWidgetArea || ContainerDropArea != InvalidDockWidgetArea); - } -} - - -//============================================================================ -FloatingDragPreviewPrivate::FloatingDragPreviewPrivate(CFloatingDragPreview *_public) : - _this(_public) -{ - -} - -//============================================================================ -CFloatingDragPreview::CFloatingDragPreview(QWidget* Content, QWidget* parent) : - QWidget(parent), - d(new FloatingDragPreviewPrivate(this)) -{ - d->Content = Content; - setAttribute(Qt::WA_DeleteOnClose); - if (CDockManager::configFlags().testFlag(CDockManager::DragPreviewHasWindowFrame)) - { - setWindowFlags( - Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint); - } - else - { - setWindowFlags(Qt::Tool | Qt::FramelessWindowHint); - setAttribute(Qt::WA_NoSystemBackground); - setAttribute(Qt::WA_TranslucentBackground); - } - -#ifdef Q_OS_LINUX - auto Flags = windowFlags(); - Flags |= Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint; - setWindowFlags(Flags); -#endif - - setWindowOpacity(0.6); - - // 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 (CDockManager::configFlags().testFlag(CDockManager::DragPreviewShowsContentPixmap)) - { - d->ContentPreviewPixmap = QPixmap(Content->size()); - Content->render(&d->ContentPreviewPixmap); - } - - connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), - SLOT(onApplicationStateChanged(Qt::ApplicationState))); - -#ifdef Q_OS_LINUX - // In Windows this widget directly receives the escape key press events - // in Linux we need to install an event filter for the given Content - // widget to receive the escape key press - Content->installEventFilter(this); -#endif -} - - -//============================================================================ -CFloatingDragPreview::CFloatingDragPreview(CDockWidget* Content) - : CFloatingDragPreview((QWidget*)Content, Content->dockManager()) -{ - d->DockManager = Content->dockManager(); - if (Content->dockAreaWidget()->openDockWidgetsCount() == 1) - { - d->ContentSourceArea = Content->dockAreaWidget(); - d->ContenSourceContainer = Content->dockContainer(); - } - setWindowTitle(Content->windowTitle()); -} - - -//============================================================================ -CFloatingDragPreview::CFloatingDragPreview(CDockAreaWidget* Content) - : CFloatingDragPreview((QWidget*)Content, Content->dockManager()) -{ - d->DockManager = Content->dockManager(); - d->ContentSourceArea = Content; - d->ContenSourceContainer = Content->dockContainer(); - setWindowTitle(Content->currentDockWidget()->windowTitle()); -} - - -//============================================================================ -CFloatingDragPreview::~CFloatingDragPreview() -{ - delete d; -} - - -//============================================================================ -void CFloatingDragPreview::moveFloating() -{ - int BorderSize = (frameSize().width() - size().width()) / 2; - const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition - - QPoint(BorderSize, 0); - move(moveToPos); -} - - -//============================================================================ -void CFloatingDragPreview::startFloating(const QPoint &DragStartMousePos, - const QSize &Size, eDragState DragState, QWidget *MouseEventHandler) -{ - Q_UNUSED(MouseEventHandler) - Q_UNUSED(DragState) - resize(Size); - d->DragStartMousePosition = DragStartMousePos; - moveFloating(); - show(); - -} - - -//============================================================================ -void CFloatingDragPreview::moveEvent(QMoveEvent *event) -{ - QWidget::moveEvent(event); - d->updateDropOverlays(QCursor::pos()); -} - - -//============================================================================ -void CFloatingDragPreview::finishDragging() -{ - ADS_PRINT("CFloatingDragPreview::finishDragging"); - auto DockDropArea = d->DockManager->dockAreaOverlay()->dropAreaUnderCursor(); - auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor(); - bool DropPossible = (DockDropArea != InvalidDockWidgetArea) || (ContainerDropArea != InvalidDockWidgetArea); - if (d->DropContainer && DropPossible) - { - d->DropContainer->dropWidget(d->Content, QCursor::pos()); - } - else - { - CDockWidget* DockWidget = qobject_cast(d->Content); - CFloatingDockContainer* FloatingWidget; - if (DockWidget) - { - FloatingWidget = new CFloatingDockContainer(DockWidget); - } - else - { - CDockAreaWidget* DockArea = qobject_cast(d->Content); - FloatingWidget = new CFloatingDockContainer(DockArea); - } - FloatingWidget->setGeometry(this->geometry()); - FloatingWidget->show(); - if (!CDockManager::configFlags().testFlag(CDockManager::DragPreviewHasWindowFrame)) - { - QApplication::processEvents(); - int FrameHeight = FloatingWidget->frameGeometry().height() - FloatingWidget->geometry().height(); - QRect FixedGeometry = this->geometry(); - FixedGeometry.adjust(0, FrameHeight, 0, 0); - FloatingWidget->setGeometry(FixedGeometry); - } - } - - this->close(); - d->DockManager->containerOverlay()->hideOverlay(); - d->DockManager->dockAreaOverlay()->hideOverlay(); -} - - -//============================================================================ -void CFloatingDragPreview::paintEvent(QPaintEvent* event) -{ - Q_UNUSED(event); - if (d->Hidden) - { - return; - } - - QPainter painter(this); - if (CDockManager::configFlags().testFlag(CDockManager::DragPreviewShowsContentPixmap)) - { - painter.drawPixmap(QPoint(0, 0), d->ContentPreviewPixmap); - } - - // If we do not have a window frame then we paint a QRubberBand like - // frameless window - if (!CDockManager::configFlags().testFlag(CDockManager::DragPreviewHasWindowFrame)) - { - QColor Color = palette().color(QPalette::Active, QPalette::Highlight); - QPen Pen = painter.pen(); - Pen.setColor(Color.darker(120)); - Pen.setStyle(Qt::SolidLine); - Pen.setWidth(1); - Pen.setCosmetic(true); - painter.setPen(Pen); - Color = Color.lighter(130); - Color.setAlpha(64); - painter.setBrush(Color); - painter.drawRect(rect().adjusted(0, 0, -1, -1)); - } -} - - -//============================================================================ -void CFloatingDragPreview::keyPressEvent(QKeyEvent *event) -{ - Super::keyPressEvent(event); - if (event->key() == Qt::Key_Escape) - { - d->cancelDragging(); - } -} - - -//============================================================================ -void CFloatingDragPreview::onApplicationStateChanged(Qt::ApplicationState state) -{ - if (state != Qt::ApplicationActive) - { - disconnect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), - this, SLOT(onApplicationStateChanged(Qt::ApplicationState))); - d->cancelDragging(); - } -} - - -//============================================================================ -bool CFloatingDragPreview::eventFilter(QObject *watched, QEvent *event) -{ - Q_UNUSED(watched); - if (event->type() == QEvent::KeyPress) - { - QKeyEvent* e = static_cast(event); - if (e->key() == Qt::Key_Escape) - { - d->Content->removeEventFilter(this); - d->cancelDragging(); - } - } - - return false; -} - - - - -} // namespace ads - -//--------------------------------------------------------------------------- -// EOF FloatingDragPreview.cpp diff --git a/src/ui/AdvDock/FloatingDragPreview.h b/src/ui/AdvDock/FloatingDragPreview.h deleted file mode 100644 index cfcb3591..00000000 --- a/src/ui/AdvDock/FloatingDragPreview.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef FloatingDragPreviewH -#define FloatingDragPreviewH -//============================================================================ -/// \file FloatingDragPreview.h -/// \author Uwe Kindler -/// \date 26.11.2019 -/// \brief Declaration of CFloatingDragPreview -//============================================================================ - -//============================================================================ -// INCLUDES -//============================================================================ -#include -#include "FloatingDockContainer.h" - -namespace ads -{ -class CDockWidget; -class CDockAreaWidget; -struct FloatingDragPreviewPrivate; - -/** - * A floating overlay is a temporary floating widget that is just used to - * indicate the floating widget movement. - * This widget is used as a placeholder for drag operations for non-opaque - * docking - */ -class CFloatingDragPreview : public QWidget, public IFloatingWidget -{ - Q_OBJECT -private: - FloatingDragPreviewPrivate* d; - friend struct FloatingDragPreviewPrivate; - -private slots: - /** - * Cancel non opaque undocking if application becomes inactive - */ - void onApplicationStateChanged(Qt::ApplicationState state); - -protected: - /** - * Updates the drop overlays - */ - virtual void moveEvent(QMoveEvent *event) override; - - /** - * Cares about painting the - */ - virtual void paintEvent(QPaintEvent *e) override; - - /** - * Cancel non opaque undocking with escape key - */ - virtual void keyPressEvent(QKeyEvent *event) override; - - /** - * The content is a DockArea or a DockWidget - */ - CFloatingDragPreview(QWidget* Content, QWidget* parent); - -public: - using Super = QWidget; - - /** - * Creates an instance for undocking the DockWidget in Content parameter - */ - CFloatingDragPreview(CDockWidget* Content); - - /** - * Creates an instance for undocking the DockArea given in Content - * parameters - */ - CFloatingDragPreview(CDockAreaWidget* Content); - - /** - * Delete private data - */ - ~CFloatingDragPreview(); - - /** - * We filter the events of the assigned content widget to receive - * escape key presses for canceling the drag operation - */ - virtual bool eventFilter(QObject *watched, QEvent *event) override; - - -public: // implements IFloatingWidget ----------------------------------------- - virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size, - eDragState DragState, QWidget* MouseEventHandler) override; - - /** - * Moves the widget to a new position relative to the position given when - * startFloating() was called - */ - virtual void moveFloating() override; - - /** - * Finishes dragging. - * Hides the dock overlays and executes the real undocking and docking - * of the assigned Content widget - */ - virtual void finishDragging() override; - -signals: - /** - * This signal is emitted, if dragging has been canceled by escape key - * or by active application switching via task manager - */ - void draggingCanceled(); -}; - - -} // namespace ads - -//--------------------------------------------------------------------------- -#endif // FloatingDragPreviewH - diff --git a/src/ui/AdvDock/IconProvider.cpp b/src/ui/AdvDock/IconProvider.cpp deleted file mode 100644 index 25e7be19..00000000 --- a/src/ui/AdvDock/IconProvider.cpp +++ /dev/null @@ -1,73 +0,0 @@ -//============================================================================ -/// \file IconProvider.cpp -/// \author Uwe Kindler -/// \date 18.10.2019 -/// \brief Implementation of CIconProvider -//============================================================================ - -//============================================================================ -// INCLUDES -//============================================================================ -#include "IconProvider.h" -#include - -namespace ads -{ -/** - * Private data class (pimpl) - */ -struct IconProviderPrivate -{ - CIconProvider *_this; - QVector UserIcons{IconCount, QIcon()}; - - /** - * Private data constructor - */ - IconProviderPrivate(CIconProvider *_public); -}; -// struct LedArrayPanelPrivate - -//============================================================================ -IconProviderPrivate::IconProviderPrivate(CIconProvider *_public) : - _this(_public) -{ - -} - -//============================================================================ -CIconProvider::CIconProvider() : - d(new IconProviderPrivate(this)) -{ - -} - -//============================================================================ -CIconProvider::~CIconProvider() -{ - delete d; -} - - -//============================================================================ -QIcon CIconProvider::customIcon(eIcon IconId) const -{ - Q_ASSERT(IconId < d->UserIcons.size()); - return d->UserIcons[IconId]; -} - - -//============================================================================ -void CIconProvider::registerCustomIcon(eIcon IconId, const QIcon &icon) -{ - Q_ASSERT(IconId < d->UserIcons.size()); - d->UserIcons[IconId] = icon; -} - -} // namespace ads - - - - -//--------------------------------------------------------------------------- -// EOF IconProvider.cpp diff --git a/src/ui/AdvDock/IconProvider.h b/src/ui/AdvDock/IconProvider.h deleted file mode 100644 index d300d90a..00000000 --- a/src/ui/AdvDock/IconProvider.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef IconProviderH -#define IconProviderH -//============================================================================ -/// \file IconProvider.h -/// \author Uwe Kindler -/// \date 18.10.2019 -/// \brief Declaration of CIconProvider -//============================================================================ - -//============================================================================ -// INCLUDES -//============================================================================ -#include - -#include "ads_globals.h" - -namespace ads -{ - -struct IconProviderPrivate; - -/** - * This object provides all icons that are required by the advanced docking - * system. - * The IconProvider enables the user to register custom icons in case using - * stylesheets is not an option. - */ -class CIconProvider -{ -private: - IconProviderPrivate* d; ///< private data (pimpl) - friend struct IconProviderPrivate; - -public: - /** - * Default Constructor - */ - CIconProvider(); - - /** - * Virtual Destructor - */ - virtual ~CIconProvider(); - - /** - * The function returns a custom icon if one is registered and a null Icon - * if no custom icon is registered - */ - QIcon customIcon(eIcon IconId) const; - - /** - * Registers a custom icon for the given IconId - */ - void registerCustomIcon(eIcon IconId, const QIcon &icon); -}; // class IconProvider - -} // namespace ads - - -//--------------------------------------------------------------------------- -#endif // IconProviderH diff --git a/src/ui/AdvDock/ads_globals.cpp b/src/ui/AdvDock/ads_globals.cpp deleted file mode 100644 index 2c6f17ea..00000000 --- a/src/ui/AdvDock/ads_globals.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file ads_globals.cpp -/// \author Uwe Kindler -/// \date 24.02.2017 -/// \brief Implementation of -//============================================================================ - - -//============================================================================ -// INCLUDES -//============================================================================ -#include -#include - -#include "DockSplitter.h" -#include "ads_globals.h" - - -namespace ads -{ - -namespace internal -{ -//============================================================================ -void replaceSplitterWidget(QSplitter* Splitter, QWidget* From, QWidget* To) -{ - int index = Splitter->indexOf(From); - From->setParent(nullptr); - Splitter->insertWidget(index, To); -} - -//============================================================================ -CDockInsertParam dockAreaInsertParameters(DockWidgetArea Area) -{ - switch (Area) - { - case TopDockWidgetArea: return CDockInsertParam(Qt::Vertical, false); - case RightDockWidgetArea: return CDockInsertParam(Qt::Horizontal, true); - case CenterDockWidgetArea: - case BottomDockWidgetArea: return CDockInsertParam(Qt::Vertical, true); - case LeftDockWidgetArea: return CDockInsertParam(Qt::Horizontal, false); - default: CDockInsertParam(Qt::Vertical, false); - } // switch (Area) - - return CDockInsertParam(Qt::Vertical, false); -} - - -//============================================================================ -QPixmap createTransparentPixmap(const QPixmap& Source, qreal Opacity) -{ - QPixmap TransparentPixmap(Source.size()); - TransparentPixmap.fill(Qt::transparent); - QPainter p(&TransparentPixmap); - p.setOpacity(Opacity); - p.drawPixmap(0, 0, Source); - return TransparentPixmap; -} - - -//============================================================================ -void hideEmptyParentSplitters(CDockSplitter* Splitter) -{ - while (Splitter && Splitter->isVisible()) - { - if (!Splitter->hasVisibleContent()) - { - Splitter->hide(); - } - Splitter = internal::findParent(Splitter); - } -} - -} // namespace internal -} // namespace ads - - - -//--------------------------------------------------------------------------- -// EOF ads_globals.cpp diff --git a/src/ui/AdvDock/ads_globals.h b/src/ui/AdvDock/ads_globals.h deleted file mode 100644 index feb4f2a5..00000000 --- a/src/ui/AdvDock/ads_globals.h +++ /dev/null @@ -1,223 +0,0 @@ -#ifndef ads_globalsH -#define ads_globalsH -/******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - - -//============================================================================ -/// \file ads_globals.h -/// \author Uwe Kindler -/// \date 24.02.2017 -/// \brief Declaration of -//============================================================================ - - -//============================================================================ -// INCLUDES -//============================================================================ -#include -#include -#include -#include -#include - -#ifndef ADS_STATIC -#ifdef ADS_SHARED_EXPORT -#define ADS_EXPORT Q_DECL_EXPORT -#else -#define ADS_EXPORT Q_DECL_IMPORT -#endif -#else -#define ADS_EXPORT -#endif - -// Define ADS_DEBUG_PRINT to enable a lot of debug output -#ifdef ADS_DEBUG_PRINT -#define ADS_PRINT(s) qDebug() << s -#else -#define ADS_PRINT(s) -#endif - -// Set ADS_DEBUG_LEVEL to enable additional debug output and to enable layout -// dumps to qDebug and std::cout after layout changes -#define ADS_DEBUG_LEVEL 0 - -class QSplitter; - -namespace ads -{ -enum eStateFileVersion -{ - InitialVerison = 0, - Version1 = 1, - CurrentVersion = Version1 -}; - -class CDockSplitter; - -enum DockWidgetArea -{ - NoDockWidgetArea = 0x00, - LeftDockWidgetArea = 0x01, - RightDockWidgetArea = 0x02, - TopDockWidgetArea = 0x04, - BottomDockWidgetArea = 0x08, - CenterDockWidgetArea = 0x10, - - InvalidDockWidgetArea = NoDockWidgetArea, - OuterDockAreas = TopDockWidgetArea | LeftDockWidgetArea | RightDockWidgetArea | BottomDockWidgetArea, - AllDockAreas = OuterDockAreas | CenterDockWidgetArea -}; -Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea) - - -enum TitleBarButton -{ - TitleBarButtonTabsMenu, - TitleBarButtonUndock, - TitleBarButtonClose -}; - -/** - * The different dragging states - */ -enum eDragState -{ - DraggingInactive, //!< DraggingInactive - DraggingMousePressed, //!< DraggingMousePressed - DraggingTab, //!< DraggingTab - DraggingFloatingWidget//!< DraggingFloatingWidget -}; - -/** - * The different icons used in the UI - */ -enum eIcon -{ - TabCloseIcon, //!< TabCloseIcon - DockAreaMenuIcon, //!< DockAreaMenuIcon - DockAreaUndockIcon,//!< DockAreaUndockIcon - DockAreaCloseIcon, //!< DockAreaCloseIcon - - IconCount, //!< just a delimiter for range checks -}; - -/** - * For bitwise combination of dock wdget features - */ -enum eBitwiseOperator -{ - BitwiseAnd, - BitwiseOr -}; - -namespace internal -{ -static const bool RestoreTesting = true; -static const bool Restore = false; -static const char* const ClosedProperty = "close"; -static const char* const DirtyProperty = "dirty"; - -/** - * Replace the from widget in the given splitter with the To widget - */ -void replaceSplitterWidget(QSplitter* Splitter, QWidget* From, QWidget* To); - -/** - * This function walks the splitter tree upwards to hides all splitters - * that do not have visible content - */ -void hideEmptyParentSplitters(CDockSplitter* FirstParentSplitter); - -/** - * Convenience class for QPair to provide better naming than first and - * second - */ -class CDockInsertParam : public QPair -{ -public: - //using QPair::QPair; - CDockInsertParam(Qt::Orientation o, bool b) : QPair(o, b) {} - Qt::Orientation orientation() const {return this->first;} - bool append() const {return this->second;} - int insertOffset() const {return append() ? 1 : 0;} -}; - -/** - * Returns the insertion parameters for the given dock area - */ -CDockInsertParam dockAreaInsertParameters(DockWidgetArea Area); - -/** - * Searches for the parent widget of the given type. - * Returns the parent widget of the given widget or 0 if the widget is not - * child of any widget of type T - * - * It is not safe to use this function in in CDockWidget because only - * the current dock widget has a parent. All dock widgets that are not the - * current dock widget in a dock area have no parent. - */ -template -T findParent(const QWidget* w) -{ - QWidget* parentWidget = w->parentWidget(); - while (parentWidget) - { - T ParentImpl = qobject_cast(parentWidget); - if (ParentImpl) - { - return ParentImpl; - } - parentWidget = parentWidget->parentWidget(); - } - return 0; -} - -/** - * Creates a semi transparent pixmap from the given pixmap Source. - * The Opacity parameter defines the opacity from completely transparent (0.0) - * to completely opaque (1.0) - */ -QPixmap createTransparentPixmap(const QPixmap& Source, qreal Opacity); - - -/** - * Helper function for settings flags in a QFlags instance. - */ -template -void setFlag(T& Flags, typename T::enum_type flag, bool on = true) -{ -#if QT_VERSION >= 0x050700 - Flags.setFlag(flag, on); -#else - if(on) - { - Flags |= flag; - } - else - { - Flags &= ~flag; - } -#endif -} - -} // namespace internal -} // namespace ads - -//--------------------------------------------------------------------------- -#endif // ads_globalsH diff --git a/src/ui/DockTitleBar.cpp b/src/ui/DockTitleBar.cpp index 89b061a6..1271d3d7 100644 --- a/src/ui/DockTitleBar.cpp +++ b/src/ui/DockTitleBar.cpp @@ -20,10 +20,10 @@ DockTitleBar::~DockTitleBar() { delete ui; } -QSize DockTitleBar::minimumSizeHint() const { - QSize s = size(); - return s; -} +//QSize DockTitleBar::minimumSizeHint() const { +// QSize s = size(); +// return s; +//} void DockTitleBar::SetTitle(const QString& title) { ui->sys_title->setText(title); diff --git a/src/ui/DockTitleBar.h b/src/ui/DockTitleBar.h index 19476342..1441eae0 100644 --- a/src/ui/DockTitleBar.h +++ b/src/ui/DockTitleBar.h @@ -13,7 +13,7 @@ public: DockTitleBar(QWidget* parent = 0); ~DockTitleBar() override; - QSize minimumSizeHint() const override; + //QSize minimumSizeHint() const override; void SetTitle(const QString& title) override; diff --git a/src/ui/DockWidget.cpp b/src/ui/DockWidget.cpp index a25abd89..88c36d05 100644 --- a/src/ui/DockWidget.cpp +++ b/src/ui/DockWidget.cpp @@ -16,14 +16,14 @@ DockWidgetTitleBar::~DockWidgetTitleBar() { } -QSize DockWidgetTitleBar::minimumSizeHint() const { - QDockWidget* dw = qobject_cast(parentWidget()); - Q_ASSERT(dw); - QSize result(0, 90); - if (dw->features() & QDockWidget::DockWidgetVerticalTitleBar) - result.transpose(); - return result; -} +//QSize DockWidgetTitleBar::minimumSizeHint() const { +// QDockWidget* dw = qobject_cast(parentWidget()); +// Q_ASSERT(dw); +// QSize result(0, 90); +// if (dw->features() & QDockWidget::DockWidgetVerticalTitleBar) +// result.transpose(); +// return result; +//} DockWidget::DockWidget(const QString& title, QWidget* parent) diff --git a/src/ui/DockWidget.h b/src/ui/DockWidget.h index 19f76f21..d1d51a18 100644 --- a/src/ui/DockWidget.h +++ b/src/ui/DockWidget.h @@ -14,10 +14,10 @@ public: virtual void SetTitle(const QString& title) {} - QSize sizeHint() const override { - return minimumSizeHint(); - } - QSize minimumSizeHint() const override; + //QSize sizeHint() const override { + // return QSize(270, 900); + //} + //QSize minimumSizeHint() const override; Q_SIGNALS: void signalClose();