290 lines
11 KiB
C++
290 lines
11 KiB
C++
/*
|
|
This file is part of KDDockWidgets.
|
|
|
|
SPDX-FileCopyrightText: 2019 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
|
|
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
|
*/
|
|
|
|
#ifndef KD_DOCKREGISTRY_P_H
|
|
#define KD_DOCKREGISTRY_P_H
|
|
|
|
#include "kddockwidgets/KDDockWidgets.h"
|
|
#include "kddockwidgets/core/View.h"
|
|
#include "kddockwidgets/core/DockWidget.h"
|
|
#include "kddockwidgets/core/MainWindow.h"
|
|
#include "kddockwidgets/QtCompat_p.h"
|
|
#include "kddockwidgets/core/EventFilterInterface.h"
|
|
|
|
#include <QVector>
|
|
#include <QObject>
|
|
|
|
#include <map>
|
|
#include <memory>
|
|
|
|
/**
|
|
* DockRegistry is a singleton that knows about all DockWidgets.
|
|
* It's used so we can restore layouts.
|
|
* It's a private implementation detail.
|
|
*/
|
|
namespace KDDockWidgets {
|
|
|
|
|
|
namespace Core {
|
|
class FloatingWindow;
|
|
class Layout;
|
|
class SideBar;
|
|
class SideBarGroupings;
|
|
class MainWindow;
|
|
class DockWidget;
|
|
class Group;
|
|
class MainWindowMDIViewInterface;
|
|
class MainWindowViewInterface;
|
|
class FocusScope;
|
|
struct WindowBeingDragged;
|
|
}
|
|
|
|
class MainWindowMDI;
|
|
|
|
class DOCKS_EXPORT DockRegistry : public QObject, public Core::EventFilterInterface
|
|
{
|
|
Q_OBJECT
|
|
QML_ELEMENT
|
|
QML_UNCREATABLE("Created by the framework only.")
|
|
public:
|
|
enum class DockByNameFlag {
|
|
None = 0,
|
|
ConsultRemapping = 1,
|
|
CreateIfNotFound =
|
|
2, ///< Creates the dock widget via the user's widget factory in case it doesn't exist
|
|
SilentIfNotFound = 4 ///< don't print errors if not found, it will be created later
|
|
};
|
|
Q_DECLARE_FLAGS(DockByNameFlags, DockByNameFlag)
|
|
|
|
static DockRegistry *self();
|
|
static bool isInitialized();
|
|
|
|
~DockRegistry() override;
|
|
void registerDockWidget(Core::DockWidget *);
|
|
void unregisterDockWidget(Core::DockWidget *);
|
|
|
|
void registerMainWindow(Core::MainWindow *);
|
|
void unregisterMainWindow(Core::MainWindow *);
|
|
|
|
void registerFloatingWindow(Core::FloatingWindow *);
|
|
void unregisterFloatingWindow(Core::FloatingWindow *);
|
|
|
|
void registerGroup(Core::Group *);
|
|
void unregisterGroup(Core::Group *);
|
|
|
|
void registerLayoutSaver();
|
|
void unregisterLayoutSaver();
|
|
|
|
/// Returns the dock widget that contains the widget with active focus
|
|
/// Doesn't necessarily mean that this DockWidget has QWidget::focus, but that it contains
|
|
/// the QApplication::focusObject() widget.
|
|
Q_INVOKABLE KDDockWidgets::Core::DockWidget *focusedDockWidget() const;
|
|
|
|
Q_INVOKABLE bool containsDockWidget(const QString &uniqueName) const;
|
|
Q_INVOKABLE bool containsMainWindow(const QString &uniqueName) const;
|
|
|
|
Q_INVOKABLE KDDockWidgets::Core::DockWidget *
|
|
dockByName(const QString &, KDDockWidgets::DockRegistry::DockByNameFlags = {}) const;
|
|
Q_INVOKABLE KDDockWidgets::Core::MainWindow *mainWindowByName(const QString &) const;
|
|
|
|
bool isSane() const;
|
|
|
|
///@brief returns all DockWidget instances
|
|
QVector<Core::DockWidget *> dockwidgets() const;
|
|
|
|
///@brief overload returning only the ones with the specified names
|
|
QVector<Core::DockWidget *> dockWidgets(const QVector<QString> &names);
|
|
|
|
///@brief returns all closed DockWidget instances
|
|
/// @param honourSkipped If true, won't include dock widgets with LayoutSaverOption::Skip
|
|
QVector<Core::DockWidget *> closedDockwidgets(bool honourSkipped) const;
|
|
|
|
///@brief returns all MainWindow instances
|
|
QVector<Core::MainWindow *> mainwindows() const;
|
|
|
|
/// @brief returns all MainWindow instances
|
|
/// Like mainwindows(), but with better suited for QtQuick and better terminology
|
|
/// as we're phasing out the "MainWindow" name there
|
|
QVector<Core::MainWindowViewInterface *> mainDockingAreas() const;
|
|
|
|
///@brief overload returning only the ones with the specified names
|
|
QVector<Core::MainWindow *> mainWindows(const QVector<QString> &names);
|
|
|
|
///@brief returns a list of all Frame instances
|
|
QVector<Core::Group *> groups() const;
|
|
|
|
///@brief returns all FloatingWindow instances. Not necessarily all floating dock widgets,
|
|
/// As there might be DockWidgets which weren't morphed yet.
|
|
QVector<Core::FloatingWindow *>
|
|
floatingWindows(bool includeBeingDeleted = false, bool honourSkipped = false) const;
|
|
|
|
///@brief overload that returns list of QWindow. This is more friendly for supporting both
|
|
/// QtWidgets and QtQuick
|
|
QVector<std::shared_ptr<Core::Window>> floatingQWindows() const;
|
|
|
|
///@brief returns whether if there's at least one floating window
|
|
Q_INVOKABLE bool hasFloatingWindows() const;
|
|
|
|
///@brief returns the FloatingWindow with handle @p windowHandle
|
|
Core::FloatingWindow *
|
|
floatingWindowForHandle(std::shared_ptr<Core::Window> windowHandle) const;
|
|
|
|
///@brief returns the FloatingWindow with handle @p hwnd
|
|
Core::FloatingWindow *floatingWindowForHandle(Core::WId hwnd) const;
|
|
|
|
///@brief returns the MainWindow with handle @p windowHandle
|
|
Core::MainWindow *mainWindowForHandle(std::shared_ptr<Core::Window> windowHandle) const;
|
|
|
|
///@brief Returns the list with all visiblye top-level parents of our FloatingWindow and
|
|
/// MainWindow instances.
|
|
///
|
|
/// Typically these are the FloatingWindows and MainWindows themselves. However, since a
|
|
/// MainWindow can be embedded into another widget (for whatever reason, like a QWinWidget),
|
|
/// it means that a top-level can be something else.
|
|
///
|
|
/// Every returned widget is either a FloatingWindow, MainWindow, or something that contains a
|
|
/// MainWindow.
|
|
///
|
|
/// If @p excludeFloatingDocks is true then FloatingWindow won't be returned
|
|
QVector<std::shared_ptr<Core::Window>> topLevels(bool excludeFloatingDocks = false) const;
|
|
|
|
/**
|
|
* @brief Closes all dock widgets, and destroys all FloatingWindows
|
|
* This is called before restoring a layout.
|
|
* @param affinities if specified only closes dock widgets and main windows with the specified
|
|
* affinities
|
|
*/
|
|
Q_INVOKABLE void clear(const QVector<QString> &affinities = {});
|
|
|
|
/**
|
|
* @brief clear Overload that only clears the specified dockWidgets and main windows.
|
|
*/
|
|
void clear(const QVector<Core::DockWidget *> &dockWidgets,
|
|
const QVector<Core::MainWindow *> &mainWindows,
|
|
const QVector<QString> &affinities);
|
|
|
|
/**
|
|
* @brief Ensures that all floating DockWidgets have a FloatingWindow as a window.
|
|
*
|
|
* This is to simplify things before saving a layout. So we don't have to care about the case
|
|
* where the window is a DockWidget.
|
|
*/
|
|
void ensureAllFloatingWidgetsAreMorphed();
|
|
|
|
/**
|
|
* @brief returns true if there's 0 dockwidgets, 0 main windows
|
|
*
|
|
* @param excludeBeingDeleted if true, any window currently being deleted won't count
|
|
*/
|
|
bool isEmpty(bool excludeBeingDeleted = false) const;
|
|
|
|
/**
|
|
* @brief Returns all main windows which match at least one of the @p affinities
|
|
*/
|
|
QVector<Core::MainWindow *> mainWindowsWithAffinity(const QVector<QString> &affinities) const;
|
|
|
|
/// @brief Returns the Layout where the specified item is in
|
|
Core::Layout *layoutForItem(const Core::Item *) const;
|
|
|
|
/// @brief Returns whether the item is in a main window.
|
|
/// Nesting is honoured. (MDIArea inside DropArea inside MainWindow, for example)
|
|
bool itemIsInMainWindow(const Core::Item *) const;
|
|
|
|
bool affinitiesMatch(const QVector<QString> &affinities1, const QVector<QString> &affinities2) const;
|
|
|
|
/// @brief Returns a list of all known main window unique names
|
|
QVector<QString> mainWindowsNames() const;
|
|
|
|
/// @brief Returns a list of all known dock widget unique names
|
|
QVector<QString> dockWidgetNames() const;
|
|
|
|
/// @brief returns if the specified window has some other window on top (with higher Z)
|
|
/// This is an approximation, as we don't have ways to compare Z, so we mostly intersect
|
|
/// geometries.
|
|
/// @param target The window which we want to know if it's probably obscured
|
|
/// @param exclude This window should not be counted as an obscurer. (It's being dragged).
|
|
bool isProbablyObscured(std::shared_ptr<Core::Window> target,
|
|
Core::FloatingWindow *exclude) const;
|
|
|
|
/// @overload
|
|
bool isProbablyObscured(std::shared_ptr<Core::Window> target, Core::WindowBeingDragged *exclude) const;
|
|
|
|
///@brief Returns whether the specified dock widget is in a side bar, and which.
|
|
/// SideBarLocation::None is returned if it's not in a sidebar.
|
|
/// This is only relevant when using the auto-hide and side-bar feature.
|
|
SideBarLocation sideBarLocationForDockWidget(const Core::DockWidget *) const;
|
|
|
|
///@brief Overload that returns the SideBar itself
|
|
Core::SideBar *sideBarForDockWidget(const Core::DockWidget *) const;
|
|
|
|
///@brief Returns the Group which is being resized in a MDI layout. nullptr if none
|
|
Core::Group *groupInMDIResize() const;
|
|
|
|
void setCurrentCloseReason(CloseReason);
|
|
CloseReason currentCloseReason();
|
|
|
|
class Private;
|
|
Private *dptr() const;
|
|
|
|
private:
|
|
friend class Core::FocusScope;
|
|
friend class Core::TitleBar;
|
|
|
|
static DockRegistry *self(bool create);
|
|
|
|
explicit DockRegistry(Core::Object *parent = nullptr);
|
|
bool onDockWidgetPressed(Core::DockWidget *dw, MouseEvent *);
|
|
void onFocusedViewChanged(std::shared_ptr<Core::View> view);
|
|
void maybeDelete();
|
|
void setFocusedDockWidget(Core::DockWidget *);
|
|
|
|
// EventFilterInterface:
|
|
bool onExposeEvent(std::shared_ptr<Core::Window>) override;
|
|
bool onMouseButtonPress(Core::View *, MouseEvent *) override;
|
|
|
|
// To honour Config::Flag_AutoHideAsTabGroups:
|
|
void addSideBarGrouping(const QVector<Core::DockWidget *> &);
|
|
void removeSideBarGrouping(const QVector<Core::DockWidget *> &);
|
|
QVector<Core::DockWidget *> sideBarGroupingFor(Core::DockWidget *) const;
|
|
|
|
Private *const d;
|
|
|
|
QVector<Core::DockWidget *> m_dockWidgets;
|
|
QVector<Core::MainWindow *> m_mainWindows;
|
|
QVector<Core::Group *> m_groups;
|
|
QVector<Core::FloatingWindow *> m_floatingWindows;
|
|
|
|
///@brief Dock widget id remapping, used by LayoutSaver
|
|
///
|
|
/// When LayoutSaver is trying to restore dock widget "foo", but it doesn't exist, it will
|
|
/// attempt to call a user provided factory function. That function can however return a dock
|
|
/// widget with another ID, such as "bar". When that happens this map gets a "foo" : "bar"
|
|
/// entry
|
|
mutable std::map<QString, QString> m_dockWidgetIdRemapping;
|
|
|
|
// To honour Config::Flag_AutoHideAsTabGroups
|
|
Core::SideBarGroupings *const m_sideBarGroupings;
|
|
};
|
|
|
|
struct CloseReasonSetter
|
|
{
|
|
CloseReasonSetter(CloseReason);
|
|
~CloseReasonSetter();
|
|
|
|
private:
|
|
CloseReasonSetter(CloseReasonSetter &) = delete;
|
|
CloseReasonSetter &operator=(CloseReason &) = delete;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|