/*******************************************************************************
** 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
#include
#include "FloatingDockContainer.h"
#include "DockOverlay.h"
#include "DockWidget.h"
#include "ads_globals.h"
#include "DockAreaWidget.h"
#include "IconProvider.h"
#include "DockingStateReader.h"
#include "DockAreaTitleBar.h"
#ifdef Q_OS_LINUX
#include "linux/FloatingWidgetTitleBar.h"
#endif
/**
* Initializes the resources specified by the .qrc file with the specified base
* name. Normally, when resources are built as part of the application, the
* resources are loaded automatically at startup. The Q_INIT_RESOURCE() macro
* is necessary on some platforms for resources stored in a static library.
* Because GCC causes a linker error if we put Q_INIT_RESOURCE into the
* loadStyleSheet() function, we place it into a function outside of the ads
* namespace
*/
static void initResource()
{
Q_INIT_RESOURCE(ads);
}
namespace ads
{
/**
* Internal file version in case the structure changes internally
*/
enum eStateFileVersion
{
InitialVersion = 0, //!< InitialVersion
Version1 = 1, //!< Version1
CurrentVersion = Version1//!< CurrentVersion
};
static CDockManager::ConfigFlags StaticConfigFlags = CDockManager::DefaultNonOpaqueConfig;
/**
* 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;
QPointer FocusedDockWidget = nullptr;
QPointer FocusedArea = nullptr;
QPointer FloatingWidget = nullptr;
/**
* 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);
/**
* This function updates the focus style of the given dock widget and
* the dock area that it belongs to
*/
void updateDockWidgetFocus(CDockWidget* DockWidget);
};
// struct DockManagerPrivate
//============================================================================
DockManagerPrivate::DockManagerPrivate(CDockManager* _public) :
_this(_public)
{
}
//============================================================================
void DockManagerPrivate::loadStylesheet()
{
initResource();
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() != "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;
}
ADS_PRINT(s.attributes().value("UserVersion"));
// Older files do not support UserVersion but we still want to load them so
// we first test if the attribute exists
if (!s.attributes().value("UserVersion").isEmpty())
{
v = s.attributes().value("UserVersion").toInt(&ok);
if (!ok || v != version)
{
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() == "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);
}
}
//===========================================================================
void updateDockWidgetFocusStyle(CDockWidget* DockWidget, bool Focused)
{
DockWidget->setProperty("focused", Focused);
DockWidget->tabWidget()->setProperty("focused", Focused);
DockWidget->tabWidget()->updateStyle();
internal::repolishStyle(DockWidget);
}
//===========================================================================
void updateDockAreaFocusStyle(CDockAreaWidget* DockArea, bool Focused)
{
DockArea->setProperty("focused", Focused);
internal::repolishStyle(DockArea);
internal::repolishStyle(DockArea->titleBar());
}
//===========================================================================
void updateFloatingWidgetFocusStyle(CFloatingDockContainer* FloatingWidget, bool Focused)
{
#ifdef Q_OS_LINUX
auto TitleBar = qobject_cast(FloatingWidget->titleBarWidget());
if (!TitleBar)
{
return;
}
TitleBar->setProperty("focused", Focused);
TitleBar->updateStyle();
#else
Q_UNUSED(FloatingWidget)
Q_UNUSED(Focused)
#endif
}
//============================================================================
void DockManagerPrivate::updateDockWidgetFocus(CDockWidget* DockWidget)
{
CDockAreaWidget* NewFocusedDockArea = nullptr;
if (FocusedDockWidget)
{
updateDockWidgetFocusStyle(FocusedDockWidget, false);
}
if (DockWidget != FocusedDockWidget)
{
std::cout << "!!!!!!!!!!!! focusedDockWidgetChanged " << (FocusedDockWidget ? FocusedDockWidget->objectName().toStdString() : "-")
<< " -> " << (DockWidget ? DockWidget->objectName().toStdString() : "-") << std::endl;
}
FocusedDockWidget = DockWidget;
updateDockWidgetFocusStyle(FocusedDockWidget, true);
NewFocusedDockArea = FocusedDockWidget->dockAreaWidget();
if (NewFocusedDockArea && (FocusedArea != NewFocusedDockArea))
{
if (FocusedArea)
{
std::cout << "FocusedArea" << std::endl;
QObject::disconnect(FocusedArea, SIGNAL(viewToggled(bool)), _this, SLOT(onFocusedDockAreaViewToggled(bool)));
updateDockAreaFocusStyle(FocusedArea, false);
}
FocusedArea = NewFocusedDockArea;
updateDockAreaFocusStyle(FocusedArea, true);
QObject::connect(FocusedArea, SIGNAL(viewToggled(bool)), _this, SLOT(onFocusedDockAreaViewToggled(bool)));
}
auto NewFloatingWidget = FocusedDockWidget->dockContainer()->floatingWidget();
if (NewFloatingWidget)
{
NewFloatingWidget->setProperty("FocusedDockWidget", QVariant::fromValue(DockWidget));
}
#ifdef Q_OS_LINUX
// This code is required for styling the floating widget titlebar for linux
// depending on the current focus state
if (FloatingWidget == NewFloatingWidget)
{
return;
}
if (FloatingWidget)
{
updateFloatingWidgetFocusStyle(FloatingWidget, false);
}
FloatingWidget = NewFloatingWidget;
if (FloatingWidget)
{
updateFloatingWidgetFocusStyle(FloatingWidget, true);
}
#endif
}
//============================================================================
CDockManager::CDockManager(QWidget *parent) :
CDockContainerWidget(this, parent),
d(new DockManagerPrivate(this))
{
createRootSplitter();
QMainWindow* MainWindow = qobject_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();
if (CDockManager::configFlags().testFlag(CDockManager::FocusStyling))
{
connect(QApplication::instance(), SIGNAL(focusChanged(QWidget*, QWidget*)),
this, SLOT(onApplicationFocusChanged(QWidget*, QWidget*)));
}
}
//============================================================================
CDockManager::~CDockManager()
{
auto FloatingWidgets = d->FloatingWidgets;
for (auto FloatingWidget : FloatingWidgets)
{
delete FloatingWidget;
}
delete d;
}
//============================================================================
void CDockManager::registerFloatingWidget(CFloatingDockContainer* FloatingWidget)
{
d->FloatingWidgets.append(FloatingWidget);
emit floatingWidgetCreated(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(CurrentVersion));
s.writeAttribute("UserVersion", 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);
}
else if (GroupMenu->icon().isNull() && !GroupIcon.isNull())
{
GroupMenu->setIcon(GroupIcon);
}
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);
}
//===========================================================================
bool CDockManager::testConfigFlag(eConfigFlag Flag)
{
return configFlags().testFlag(Flag);
}
//===========================================================================
CIconProvider& CDockManager::iconProvider()
{
static CIconProvider Instance;
return Instance;
}
//===========================================================================
void CDockManager::onApplicationFocusChanged(QWidget* focusedOld, QWidget* focusedNow)
{
std::cout << "CDockManager::onFocusChanged" << std::endl;
Q_UNUSED(focusedOld)
if (!focusedNow)
{
return;
}
CDockWidget* DockWidget = nullptr;
auto DockWidgetTab = qobject_cast(focusedNow);
std::cout << "FocuseNow " << focusedNow->metaObject()->className() << std::endl;
if (DockWidgetTab)
{
DockWidget = DockWidgetTab->dockWidget();
}
else
{
DockWidget = internal::findParent(focusedNow);
}
#ifdef Q_OS_LINUX
if (!DockWidget)
{
return;
}
#else
if (!DockWidget || DockWidget->tabWidget()->isHidden())
{
std::cout << "!DockWidget || !DockWidget->tabWidget()->isVisible() " << (DockWidget ? DockWidget->objectName().toStdString() : "0") << std::endl;
std::cout << "DockWidget->tabWidget()->isHidden() " << (DockWidget ? DockWidget->tabWidget()->isHidden() : false) << std::endl;
return;
}
#endif
std::cout << "CDockManager::onFocusChanged " << DockWidget->tabWidget()->text().toStdString() << std::endl;
d->updateDockWidgetFocus(DockWidget);
}
//===========================================================================
void CDockManager::onFocusedDockAreaViewToggled(bool Open)
{
CDockAreaWidget* DockArea = qobject_cast(sender());
if (!DockArea || Open)
{
return;
}
auto Container = DockArea->dockContainer();
auto OpenedDockAreas = Container->openedDockAreas();
if (OpenedDockAreas.isEmpty())
{
return;
}
CDockManager::setWidgetFocus(OpenedDockAreas[0]->currentDockWidget()->tabWidget());
}
//===========================================================================
void CDockManager::notifyWidgetDrop(QWidget* DroppedWidget)
{
std::cout << "\n\nCDockManager::notifyWidgetDrop" << std::endl;
CDockWidget* DockWidget = qobject_cast(DroppedWidget);
if (DockWidget)
{
std::cout << "CDockManager::setWidgetFocus " << DockWidget->objectName().toStdString() << std::endl;
CDockManager::setWidgetFocus(DockWidget->tabWidget());
emit dockWidgetDropped(DockWidget);
return;
}
CDockAreaWidget* DockArea = qobject_cast(DroppedWidget);
if (!DockArea)
{
return;
}
DockWidget = DockArea->currentDockWidget();
CDockManager::setWidgetFocus(DockWidget->tabWidget());
std::cout << "\n\n" << std::endl;
}
//===========================================================================
void CDockManager::notifyFloatingWidgetDrop(CFloatingDockContainer* FloatingWidget)
{
std::cout << "\n\nCDockManager::notifyFloatingWidgetDrop" << std::endl;
if (!FloatingWidget)
{
return;
}
auto vDockWidget = FloatingWidget->property("FocusedDockWidget");
if (!vDockWidget.isValid())
{
return;
}
std::cout << "vDockWidget.isValid()" << std::endl;
auto DockWidget = vDockWidget.value();
if (DockWidget)
{
std::cout << "Dropped focus dock widget " << DockWidget->objectName().toStdString() << std::endl;
DockWidget->dockAreaWidget()->setCurrentDockWidget(DockWidget);
CDockManager::setWidgetFocus(DockWidget->tabWidget());
}
std::cout << "\n\n" << std::endl;
}
} // namespace ads
//---------------------------------------------------------------------------
// EOF DockManager.cpp