2026-04-06 00:20:51 -05:00

170 lines
4.7 KiB
C++

/*
This file is part of KDDockWidgets.
SPDX-FileCopyrightText: 2020 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.
*/
/**
* @file Helper class so dockwidgets can be restored to their previous position.
*
* @author Sérgio Martins \<sergio.martins@kdab.com\>
*/
#ifndef KDDOCKWIDGETS_POSITION_P_H
#define KDDOCKWIDGETS_POSITION_P_H
#include "kddockwidgets/docks_export.h"
#include "kddockwidgets/LayoutSaver.h"
#include "ObjectGuard_p.h"
#include <kdbindings/signal.h>
#include <memory>
#include <unordered_map>
namespace KDDockWidgets {
namespace Core {
class Item;
class DockWidget;
class Group;
class Layout;
class LayoutingHost;
}
/**
* @internal
* @brief Represents the DockWidget's last positions.
*
* DockWidgets know where they were in the main window even after they're closed, so that
* showing them again puts them in their previous place.
*
* This class is called Positions since the window might also have a floating position memorized.
*
* This class is not directly related to LayoutSaver which saves/restores in bulk. It's more
* for redocking back when you double-click a floating dock widget title-bar for example.
*/
class DOCKS_EXPORT_FOR_UNIT_TESTS Positions
{
KDDW_DELETE_COPY_CTOR(Positions)
public:
typedef std::shared_ptr<Positions> Ptr;
Positions() = default;
~Positions();
void deserialize(const LayoutSaver::Position &);
LayoutSaver::Position serialize() const;
///@brief The tab index in case the dock widget was in a TabWidget, -1 otherwise.
int m_tabIndex = -1;
///@brief true if the DockWidget was floating when it was closed
bool m_wasFloating = false;
///@brief Adds the last layout item where the dock widget was (or is)
/// This is called at the moment the dock widget is added into any layout
void addPlaceholderItem(Core::Item *placeholder);
bool containsPlaceholder(Core::Item *) const;
void removePlaceholders();
///@brief Removes the placeholders that belong to this multisplitter
void removePlaceholders(const Core::LayoutingHost *);
///@brief Removes the placeholders that reference a FloatingWindow
void removeNonMainWindowPlaceholders();
///@brief Removes the placeholders that reference a MainWindow
void removeMainWindowPlaceholders();
///@brief removes the Item @p placeholder
void removePlaceholder(Core::Item *placeholder);
/// The amount of placeholders we know about
/// this will be either:
/// 0 - if dock widget hasn't been docked
/// 1 - if it has been docked
/// 2 - if it has been docked to main window and to a floating window
/// We don't support memorizing more than 1 main window or more than 1 floating window
int placeholderCount() const;
void saveTabIndex(int tabIndex, bool isFloating)
{
m_tabIndex = tabIndex;
m_wasFloating = isFloating;
}
void setLastFloatingGeometry(Rect geo)
{
m_lastFloatingGeometry = geo;
}
bool wasFloating() const
{
return m_wasFloating;
}
Rect lastFloatingGeometry() const
{
return m_lastFloatingGeometry;
}
/// Returns the placeholder Item where the dock widget *was*
/// Pass current to exclude the current layout Item where it's living
Core::Item *lastItem(Core::Item *current = nullptr) const;
/// convenience overload
Core::Item *lastItem(const Core::DockWidget *current) const;
int lastTabIndex() const
{
return m_tabIndex;
}
Rect lastOverlayedGeometry(SideBarLocation loc) const
{
auto it = m_lastOverlayedGeometries.find(loc);
return it == m_lastOverlayedGeometries.cend() ? Rect() : it->second;
}
void setLastOverlayedGeometry(SideBarLocation loc, Rect rect)
{
m_lastOverlayedGeometries[loc] = rect;
}
private:
/// A RAII class so we don't forget to unref
struct ItemRef
{
explicit ItemRef(KDBindings::ConnectionHandle conn, Core::Item *);
~ItemRef();
bool isInMainWindow() const;
Core::ObjectGuard<Core::Item> item;
KDBindings::ConnectionHandle connection;
private:
KDDW_DELETE_COPY_CTOR(ItemRef)
};
bool itemIsBeingDestroyed(Core::Item *) const;
// The last places where this dock widget was (or is), so it can be restored when
// setFloating(false) or show() is called.
std::vector<std::unique_ptr<ItemRef>> m_placeholders;
Rect m_lastFloatingGeometry;
std::unordered_map<SideBarLocation, Rect> m_lastOverlayedGeometries;
bool m_clearing = false; // to prevent re-entrancy
};
}
#endif