364 lines
12 KiB
C++
364 lines
12 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.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "DockWidget.h"
|
|
#include "kddockwidgets/KDDockWidgets.h"
|
|
#include "kddockwidgets/LayoutSaver.h"
|
|
#include "kddockwidgets/QtCompat_p.h"
|
|
#include "kddockwidgets/core/Controller.h"
|
|
#include "kddockwidgets/core/FocusScope.h"
|
|
#include "kddockwidgets/docks_export.h"
|
|
|
|
class TestDocks;
|
|
|
|
namespace KDDockWidgets {
|
|
class WidgetResizeHandler;
|
|
}
|
|
|
|
namespace KDDockWidgets::Core {
|
|
|
|
class LayoutingGuest;
|
|
class DropArea;
|
|
class MDILayout;
|
|
class DockWidget;
|
|
class FloatingWindow;
|
|
class MainWindow;
|
|
class Stack;
|
|
class TabBar;
|
|
class TitleBar;
|
|
class Item;
|
|
|
|
class DOCKS_EXPORT Group : public Controller, public FocusScope
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
typedef Vector<Group *> List;
|
|
|
|
explicit Group(View *parent = nullptr, FrameOptions = FrameOption_None,
|
|
int userType = 0);
|
|
~Group() override;
|
|
|
|
static Group *deserialize(const LayoutSaver::Group &);
|
|
LayoutSaver::Group serialize() const;
|
|
|
|
///@brief Adds a widget into the Group's Stack
|
|
void addTab(DockWidget *, const InitialOption & = {});
|
|
///@overload
|
|
void addTab(Group *, const InitialOption & = {});
|
|
///@overload
|
|
void addTab(FloatingWindow *floatingWindow, const InitialOption & = {});
|
|
|
|
///@brief Inserts a widget into the Group's TabWidget at @p index
|
|
void insertWidget(DockWidget *, int index, const InitialOption & = {});
|
|
|
|
///@brief removes a dockwidget from the group
|
|
void removeWidget(DockWidget *);
|
|
|
|
///@brief detaches this dock widget
|
|
FloatingWindow *detachTab(DockWidget *);
|
|
|
|
///@brief returns the index of the specified dock widget
|
|
int indexOfDockWidget(const DockWidget *);
|
|
|
|
///@brief returns the index of the current tab
|
|
int currentIndex() const;
|
|
|
|
///@brief sets the current tab index
|
|
void setCurrentTabIndex(int index);
|
|
|
|
///@brief Sets the specified dock widget to be the current tab
|
|
void setCurrentDockWidget(DockWidget *);
|
|
|
|
///@brief Inserts a dock widget into the specified index
|
|
void insertDockWidget(DockWidget *, int index);
|
|
|
|
/// @brief Returns the dock widget at @p index
|
|
DockWidget *dockWidgetAt(int index) const;
|
|
|
|
///@brief Returns the current dock widget
|
|
DockWidget *currentDockWidget() const;
|
|
|
|
/// @brief returns the number of dock widgets inside the group
|
|
int dockWidgetCount() const;
|
|
|
|
/// @brief returns the tab widget
|
|
Core::Stack *stack() const;
|
|
Core::TabBar *tabBar() const;
|
|
|
|
void updateTitleAndIcon();
|
|
void onDockWidgetTitleChanged(DockWidget *);
|
|
void updateTitleBarVisibility();
|
|
void updateFloatingActions();
|
|
bool containsMouse(Point globalPos) const;
|
|
Core::TitleBar *titleBar() const;
|
|
Core::TitleBar *actualTitleBar() const;
|
|
QString title() const;
|
|
Icon icon() const;
|
|
Vector<DockWidget *> dockWidgets() const;
|
|
|
|
bool isTheOnlyGroup() const;
|
|
|
|
///@brief Returns whether this group is overlayed on top of the MainWindow (auto-hide feature);
|
|
bool isOverlayed() const;
|
|
|
|
///@brief clears the FrameOption_IsOverlayed flag.
|
|
/// For example, if you drag a side-bar overlay, then it becomes a normal floating window
|
|
void unoverlay();
|
|
|
|
/**
|
|
* @brief Returns whether this group is floating. A floating group isn't attached to any other
|
|
* MainWindow, and if it's attached to a FloatingWindow then it's considered floating if it's
|
|
* the only group in that Window. A floating group can have multiple dock widgets (tabbed), in
|
|
* which case each DockWidget::isFloating() returns false, in which case you can use
|
|
* isInFloatingWindow() which would still return true
|
|
*/
|
|
bool isFloating() const;
|
|
|
|
/**
|
|
* @brief Returns whether this group is in a FloatingWindow, as opposed to MainWindow.
|
|
*
|
|
* After setup it's equivalent to !isInMainWindow().
|
|
*/
|
|
bool isInFloatingWindow() const;
|
|
|
|
/**
|
|
* @brief Returns whether this group is docked inside a MainWindow.
|
|
*/
|
|
bool isInMainWindow() const;
|
|
|
|
/**
|
|
* @brief returns if this widget is the central group
|
|
* MainWindow supports a mode where the middle group is persistent even if no dock widget is
|
|
* there.
|
|
*
|
|
* @return whether this widget is the central group in a main window
|
|
*/
|
|
bool isCentralGroup() const;
|
|
|
|
/// @brief Returns whether you can DND dock widgets over this group and tab into it
|
|
bool isDockable() const;
|
|
|
|
/**
|
|
* @brief whether the tab widget will always show tabs, even if there's only 1 dock widget
|
|
*
|
|
* While technically a non-floating dock widget is always tabbed, the user won't see the tabs
|
|
* as in most cases there's only 1 widget tabbed. But for the main window central group it's
|
|
* often wanted to see tabs even if there's only 1 widget, where each widget represents a
|
|
* "document".
|
|
*
|
|
* @return whether the tab widget will always show tabs, even if there's only 1 dock widget
|
|
*/
|
|
bool alwaysShowsTabs() const;
|
|
|
|
/// @brief returns whether the dockwidget @p w is inside this group
|
|
bool containsDockWidget(DockWidget *w) const;
|
|
|
|
///@brief returns the FloatingWindow this group is in, if any
|
|
FloatingWindow *floatingWindow() const;
|
|
|
|
/**
|
|
* @brief Returns the main window this group is in.
|
|
* nullptr if not inside a main window.
|
|
*/
|
|
MainWindow *mainWindow() const;
|
|
|
|
/**
|
|
* @brief Puts the Group back in its previous main window position
|
|
*
|
|
* Usually DockWidget::Private::restoreToPreviousPosition() is used, but
|
|
* when we have a floating group with tabs we just reuse the group instead of
|
|
* moving the tabbed dock widgets one by one.
|
|
*/
|
|
void restoreToPreviousPosition();
|
|
|
|
int currentTabIndex() const;
|
|
FrameOptions options() const;
|
|
bool anyNonClosable() const;
|
|
bool anyNonDockable() const;
|
|
|
|
///@brief returns whether there's 0 dock widgets. If not persistent then the Frame will delete
|
|
/// itself.
|
|
bool isEmpty() const
|
|
{
|
|
return dockWidgetCount() == 0;
|
|
}
|
|
|
|
///@brief returns whether there's only 1 dock widget.
|
|
bool hasSingleDockWidget() const
|
|
{
|
|
return dockWidgetCount() == 1;
|
|
}
|
|
|
|
///@brief returns the layout item that either contains this Frame in the layout or is a
|
|
/// placeholder
|
|
Core::Item *layoutItem() const;
|
|
|
|
///@brief For tests-only. Returns the number of Frame instances in the whole application.
|
|
static int dbg_numFrames();
|
|
|
|
/**
|
|
* @brief Returns whether a deleteLater has already been issued
|
|
*/
|
|
bool beingDeletedLater() const;
|
|
|
|
/**
|
|
* @brief returns true if tabs are visible
|
|
*
|
|
* @sa hasTabsVisibleChanged()
|
|
**/
|
|
bool hasTabsVisible() const;
|
|
|
|
Vector<QString> affinities() const;
|
|
|
|
///@brief sets the layout item that either contains this Group in the layout or is a placeholder
|
|
void setLayoutItem(Core::Item *item);
|
|
|
|
/**
|
|
* Returns the drag rect in global coordinates. This is usually the title bar rect.
|
|
* However, when using Config::Flag_HideTitleBarWhenTabsVisible it will be the tab bar
|
|
* background. Returns global coordinates.
|
|
*/
|
|
virtual Rect dragRect() const;
|
|
|
|
///@brief Returns whether all dock widgets have the specified option set
|
|
bool allDockWidgetsHave(DockWidgetOption) const;
|
|
|
|
///@brief Returns whether at least one dock widget has the specified option set
|
|
bool anyDockWidgetsHas(DockWidgetOption) const;
|
|
|
|
///@brief Returns whether all dock widgets have the specified layout saver option set
|
|
bool allDockWidgetsHave(LayoutSaverOption) const;
|
|
|
|
///@brief Returns whether at least one dock widget has the specified layout saver option set
|
|
bool anyDockWidgetsHas(LayoutSaverOption) const;
|
|
|
|
/// @brief To allow resizing the overlayed dock widget (auto-hide feature)
|
|
void setAllowedResizeSides(CursorPositions sides);
|
|
|
|
/// @brief Returns whether this group is in a MDI layout
|
|
/// Usually no, unless you're using an MDI main window
|
|
bool isMDI() const;
|
|
|
|
/// @brief Returns whether this group was created automatically just for the purpose of
|
|
/// supporting DockWidgetOption_MDINestable
|
|
bool isMDIWrapper() const;
|
|
|
|
/// @brief If this is an MDI wrapper group, return the DockWidget MDI wrapper
|
|
/// @sa isMDIWrapper
|
|
DockWidget *mdiDockWidgetWrapper() const;
|
|
|
|
/// @brief If this is an MDI wrapper group, return the DropArea MDI wrapper
|
|
/// @sa isMDIWrapper
|
|
DropArea *mdiDropAreaWrapper() const;
|
|
|
|
/// @brief If this group is an MDI wrapper, returns the MDI group. That is the group you
|
|
/// actually drag inside the MDI area
|
|
Group *mdiFrame() const;
|
|
|
|
/// @brief Returns the MDI layout. Or nullptr if this group isn't in a MDI layout
|
|
MDILayout *mdiLayout() const;
|
|
|
|
/// @brief If this group is a MDI group (isMDI() == true), returns whether it contains nested
|
|
/// dock widgets (DockWidgetOption_MDINestable)
|
|
/// @sa isMDI()
|
|
bool hasNestedMDIDockWidgets() const;
|
|
|
|
/// @brief See Core::DockWidget::userType()
|
|
int userType() const;
|
|
|
|
/// @brief Returns the resize handler. Used mostly in MDI mode.
|
|
WidgetResizeHandler *resizeHandler() const;
|
|
|
|
void renameTab(int index, const QString &);
|
|
void changeTabIcon(int index, const Icon &);
|
|
/// @brief Sets the Layout which this group is in
|
|
void setLayout(Layout *);
|
|
|
|
void onDockWidgetCountChanged();
|
|
|
|
/// @brief User requested floating window flags for when this group floats
|
|
FloatingWindowFlags requestedFloatingWindowFlags() const;
|
|
|
|
LayoutingGuest *asLayoutingGuest() const;
|
|
|
|
/// Convenience that just calls close() on all its dock widgets
|
|
/// Returns whether all dock widgets accepted the close
|
|
bool close() const;
|
|
|
|
/// Returns the group that's in the specified item
|
|
static Core::Group *fromItem(const Core::Item *);
|
|
|
|
static Core::Item *s_inFloatHack;
|
|
|
|
protected:
|
|
void isFocusedChangedCallback() override;
|
|
void focusedWidgetChangedCallback() override;
|
|
void setParentView_impl(View *parent) override;
|
|
|
|
public:
|
|
/**
|
|
* @brief Returns the minimum size of the dock widgets.
|
|
* This might be slightly smaller than Frame::minSize() due to the QTabWidget having some
|
|
* margins and tab bar.
|
|
*/
|
|
Size dockWidgetsMinSize() const;
|
|
|
|
/**
|
|
* @brief Returns the biggest combined maxSize of all dock widgets.
|
|
*
|
|
* Example:
|
|
* dock 1, max=2000x1000
|
|
* dock 2, max=3000x400
|
|
* dock3, max=
|
|
* result=3000,1000
|
|
*
|
|
* Any widget having 16777215x16777215 is ignored (represents not having a max-size,
|
|
* QWIDGETSIZE_MAX)
|
|
*/
|
|
Size biggestDockWidgetMaxSize() const;
|
|
int nonContentsHeight() const;
|
|
|
|
class Private;
|
|
Private *dptr() const;
|
|
|
|
private:
|
|
Private *const d;
|
|
bool m_inCtor = true; // Needs to be initialized early, as pointed out by UBSAN
|
|
protected:
|
|
bool m_inDtor = false;
|
|
|
|
Core::Stack *const m_stack;
|
|
Core::TabBar *const m_tabBar;
|
|
Core::TitleBar *const m_titleBar;
|
|
|
|
#ifdef DOCKS_DEVELOPER_MODE
|
|
public:
|
|
#else
|
|
private:
|
|
#endif
|
|
KDDW_DELETE_COPY_CTOR(Group)
|
|
friend class ::TestDocks;
|
|
friend class KDDockWidgets::Core::Stack;
|
|
|
|
void scheduleDeleteLater();
|
|
void createMDIResizeHandler();
|
|
void onCloseEvent(CloseEvent *);
|
|
|
|
Layout *m_layout = nullptr;
|
|
WidgetResizeHandler *m_resizeHandler = nullptr;
|
|
bool m_updatingTitleBar = false;
|
|
bool m_beingDeleted = false;
|
|
};
|
|
|
|
}
|