312 lines
9.9 KiB
C++
312 lines
9.9 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_DOCKWIDGET_P_H
|
|
#define KD_DOCKWIDGET_P_H
|
|
|
|
#include "DockWidget.h"
|
|
#include "DockRegistry.h"
|
|
#include "core/Position_p.h"
|
|
#include "Action.h"
|
|
#include "core/View_p.h"
|
|
#include "QtCompat_p.h"
|
|
|
|
namespace KDDockWidgets {
|
|
|
|
namespace Core {
|
|
class SideBar;
|
|
|
|
class DOCKS_EXPORT_FOR_UNIT_TESTS DockWidget::Private
|
|
{
|
|
public:
|
|
/// RAII class to help updating actions exactly once, otherwise they can be triggered in the
|
|
/// middle of operations during reparenting
|
|
struct UpdateActions
|
|
{
|
|
explicit UpdateActions(Core::DockWidget *dock)
|
|
: dw(dock)
|
|
{
|
|
dw->d->m_willUpdateActions++;
|
|
}
|
|
|
|
~UpdateActions()
|
|
{
|
|
dw->d->m_willUpdateActions--;
|
|
|
|
// only the last one (the outer one, updates actions, in case of nesting)
|
|
if (dw->d->m_willUpdateActions == 0) {
|
|
dw->d->updateFloatAction();
|
|
if (dw->isOpen() != dw->toggleAction()->isChecked())
|
|
dw->d->updateToggleAction();
|
|
}
|
|
}
|
|
|
|
private:
|
|
KDDW_DELETE_COPY_CTOR(UpdateActions)
|
|
Core::DockWidget *const dw;
|
|
};
|
|
|
|
Private(const QString &dockName, DockWidgetOptions options_,
|
|
LayoutSaverOptions layoutSaverOptions_, DockWidget *qq);
|
|
|
|
~Private();
|
|
|
|
void init()
|
|
{
|
|
updateTitle();
|
|
q->view()->d->closeRequested.connect([this](CloseEvent *ev) { onCloseEvent(ev); });
|
|
}
|
|
|
|
/**
|
|
* @brief returns the FloatingWindow this dock widget is in. If nullptr then it's in a
|
|
* MainWindow.
|
|
*
|
|
* Note: Being in a FloatingWindow doesn't necessarily mean @ref isFloating() returns true, as
|
|
* the dock widget might be in a floating window with other dock widgets side by side.
|
|
*/
|
|
Core::FloatingWindow *floatingWindow() const
|
|
{
|
|
if (auto fw = q->view()->rootView()->asFloatingWindowController())
|
|
return fw;
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
MainWindow *mainWindow() const
|
|
{
|
|
if (q->view()->isRootView())
|
|
return nullptr;
|
|
|
|
// Note: Don't simply use window(), as the MainWindow might be embedded into something else
|
|
auto p = q->view()->parentView();
|
|
while (p) {
|
|
if (auto mw = p->asMainWindowController())
|
|
return mw;
|
|
|
|
if (p->isRootView())
|
|
return nullptr;
|
|
|
|
p = p->parentView();
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
Core::SideBar *sideBar() const
|
|
{
|
|
return DockRegistry::self()->sideBarForDockWidget(q);
|
|
}
|
|
|
|
///@brief adds the current layout item containing this dock widget
|
|
void addPlaceholderItem(Core::Item *);
|
|
|
|
///@brief returns the last position, just for tests.
|
|
Positions::Ptr &lastPosition();
|
|
|
|
void forceClose();
|
|
Point defaultCenterPosForFloating();
|
|
|
|
void onWindowActivated(std::shared_ptr<View> rootView);
|
|
void onWindowDeactivated(std::shared_ptr<View> rootView);
|
|
|
|
void updateTitle();
|
|
void toggle(bool enabled);
|
|
void updateToggleAction();
|
|
void updateFloatAction();
|
|
void close();
|
|
bool restoreToPreviousPosition();
|
|
void maybeRestoreToPreviousPosition();
|
|
int currentTabIndex() const;
|
|
void onCloseEvent(CloseEvent *);
|
|
void onParentChanged();
|
|
|
|
/**
|
|
* @brief Serializes this dock widget into an intermediate form
|
|
*/
|
|
std::shared_ptr<LayoutSaver::DockWidget> serialize() const;
|
|
|
|
/**
|
|
* @brief the Group which contains this dock widgets.
|
|
*
|
|
* A group wraps a docked DockWidget, giving it a TabWidget so it can accept other dock widgets.
|
|
* Frame is also the actual class that goes into a Layout.
|
|
*
|
|
* It's nullptr immediately after creation.
|
|
*/
|
|
Core::Group *group() const;
|
|
|
|
/**
|
|
* Returns the Layout Item this DockWidget is in.
|
|
* Can be nullptr.
|
|
*/
|
|
Core::Item *item() const;
|
|
|
|
///@brief If this dock widget is floating, then it saves its geometry
|
|
void saveLastFloatingGeometry();
|
|
|
|
/**
|
|
* Before floating a dock widget we save its position. So it can be restored when calling
|
|
* DockWidget::setFloating(false)
|
|
*/
|
|
void saveTabIndex();
|
|
|
|
/**
|
|
* @brief Creates a FloatingWindow and adds itself into it
|
|
* @return the created FloatingWindow
|
|
*/
|
|
Core::FloatingWindow *morphIntoFloatingWindow();
|
|
|
|
/// @brief calls morphIntoFloatingWindow() if the dock widget is visible and is a top-level
|
|
/// This is called delayed whenever we show a floating dock widget, so we get a FloatingWindow
|
|
void maybeMorphIntoFloatingWindow();
|
|
|
|
/// @brief Returns the mdi layout this dock widget is in, if any.
|
|
MDILayout *mdiLayout() const;
|
|
|
|
/// @brief Returns if this is an helper DockWidget created automatically to host a drop area
|
|
/// inside MDI This is only used by the DockWidgetOption_MDINestable feature
|
|
bool isMDIWrapper() const;
|
|
|
|
/// @brief If this dock widget is an MDI wrapper (isMDIWrapper()), then returns the wrapper drop
|
|
/// area
|
|
DropArea *mdiDropAreaWrapper() const;
|
|
|
|
/// @brief If this dock widget is inside a drop area nested in MDI then returns the wrapper dock
|
|
/// widget This goes up the hierarchy, while mdiDropAreaWrapper goes down.
|
|
DockWidget *mdiDockWidgetWrapper() const;
|
|
|
|
void setIsOpen(bool);
|
|
|
|
///@brief signal emitted when the icon changed
|
|
KDBindings::Signal<> iconChanged;
|
|
|
|
///@brief signal emitted when the title changed
|
|
///@param title the new title
|
|
KDBindings::Signal<QString> titleChanged;
|
|
|
|
/// @brief emitted when the hosted guest widget changed
|
|
KDBindings::Signal<> guestViewChanged;
|
|
|
|
///@brief emitted when the options change
|
|
///@sa setOptions(), options()
|
|
///@param options
|
|
KDBindings::Signal<KDDockWidgets::DockWidgetOptions> optionsChanged;
|
|
|
|
///@brief emitted when isFocused changes
|
|
///@sa isFocused
|
|
///@param isFocused
|
|
KDBindings::Signal<bool> isFocusedChanged;
|
|
|
|
///@brief emitted when isOverlayed changes
|
|
///@sa isOverlayed
|
|
///@param isOverlayed
|
|
KDBindings::Signal<bool> isOverlayedChanged;
|
|
|
|
///@brief emitted when isFloating changes
|
|
///@param isFloating
|
|
KDBindings::Signal<bool> isFloatingChanged;
|
|
|
|
/// Emitted when userData changes
|
|
KDBindings::Signal<> userDataChanged;
|
|
|
|
///@brief emitted when this dock widget is removed from a side-bar.
|
|
/// Only relevant for the auto-hide/sidebar feature
|
|
KDBindings::Signal<> removedFromSideBar;
|
|
|
|
///@brief Emitted when the top-level window this dock widget is in is activated or deactivated
|
|
/// This is convenience to replace tracking dockWidget->window(), since the window changes when
|
|
/// docking and undocking
|
|
///
|
|
/// It's called 'aboutTo' because it's done in an event filter and the target window doesn't
|
|
/// have it's 'activeWindow' property updated yet at this point.
|
|
/// @param activated
|
|
KDBindings::Signal<bool> windowActiveAboutToChange;
|
|
|
|
///@brief Emitted when the title bar that serves this dock widget changes
|
|
KDBindings::Signal<> actualTitleBarChanged;
|
|
|
|
/// @brief Emitted when this dock widget is about to be deleted due to Option_DeleteOnClose
|
|
KDBindings::Signal<> aboutToDeleteOnClose;
|
|
|
|
/// @brief Emitted when this dock widget is about to be deleted
|
|
/// @param dockWidget
|
|
KDBindings::Signal<KDDockWidgets::Core::DockWidget *> aboutToDelete;
|
|
|
|
/// @brief Emitted when a dock widget is closed
|
|
/// This is equivalent to the openedChanged(false) signal
|
|
KDBindings::Signal<> closed;
|
|
|
|
/// @brief Emitted when a dock widget is opened or closed
|
|
/// For the false case, closed() is also emitted
|
|
/// @param isOpen
|
|
KDBindings::Signal<bool> isOpenChanged;
|
|
|
|
/// @brief Emitted when a dock widget becomes current or not in its tab group
|
|
/// @param isCurrent true if it became current
|
|
KDBindings::Signal<bool> isCurrentTabChanged;
|
|
|
|
/// Each dock widget has a unique name which is used for layout save/restore
|
|
QString uniqueName() const;
|
|
|
|
/// Sets the dock widget unique name.
|
|
/// DockWidgets have their name set once (passed in ctor), therefore this method doesn't need
|
|
/// to be called, unless you know what you're doing (like reusing dock widgets during restore)
|
|
void setUniqueName(const QString &);
|
|
|
|
private:
|
|
// Go through the setter
|
|
QString m_uniqueName;
|
|
|
|
public:
|
|
Vector<QString> affinities;
|
|
QString title;
|
|
Icon titleBarIcon;
|
|
Icon tabBarIcon;
|
|
std::shared_ptr<View> guest;
|
|
DockWidget *const q;
|
|
DockWidgetOptions options;
|
|
FloatingWindowFlags m_flags = FloatingWindowFlag::FromGlobalConfig;
|
|
const LayoutSaverOptions layoutSaverOptions;
|
|
Action *const toggleAction;
|
|
Action *const floatAction;
|
|
Positions::Ptr m_lastPositions = std::make_shared<Positions>();
|
|
bool m_isPersistentCentralDockWidget = false;
|
|
bool m_processingToggleAction = false;
|
|
bool m_updatingToggleAction = false;
|
|
bool m_updatingFloatAction = false;
|
|
bool m_isForceClosing = false;
|
|
bool m_isMovingToSideBar = false;
|
|
bool m_isSettingCurrent = false;
|
|
bool m_isOpen = false;
|
|
bool m_inOpenSetter = false;
|
|
bool m_inClose = false;
|
|
bool m_inCloseEvent = false;
|
|
bool m_removingFromOverlay = false;
|
|
bool m_wasRestored = false;
|
|
Size m_lastOverlayedSize = Size(0, 0);
|
|
int m_userType = 0;
|
|
int m_willUpdateActions = 0;
|
|
KDBindings::ScopedConnection m_windowActivatedConnection;
|
|
KDBindings::ScopedConnection m_windowDeactivatedConnection;
|
|
KDBindings::ScopedConnection m_toggleActionConnection;
|
|
KDBindings::ScopedConnection m_floatActionConnection;
|
|
CloseReason m_lastCloseReason = CloseReason::Unspecified;
|
|
#if defined(KDDW_FRONTEND_QT) && QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
QVariantMap m_userData;
|
|
#endif
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|