Add a Stack view interface

So that stack controller doesn't depend on QtWidgets
This commit is contained in:
Sergio Martins
2022-04-02 19:36:25 +01:00
parent aab3de29e1
commit 5681a5a231
8 changed files with 134 additions and 99 deletions

View File

@@ -41,8 +41,7 @@ Q_NAMESPACE
class MultiSplitter;
class DropArea;
enum Location
{
enum Location {
Location_None,
Location_OnLeft, ///> Left docking location
Location_OnTop, ///> Top docking location
@@ -51,8 +50,7 @@ enum Location
};
Q_ENUM_NS(Location)
enum MainWindowOption
{
enum MainWindowOption {
MainWindowOption_None = 0, ///> No option set
MainWindowOption_HasCentralFrame = 1, ///> Makes the MainWindow always have a central frame, for tabbing documents
MainWindowOption_MDI = 2, ///> The layout will be MDI. DockWidgets can have arbitrary positions, not restricted by any layout
@@ -64,7 +62,7 @@ Q_ENUM_NS(MainWindowOptions)
///@internal
///@brief Describes some sizing strategies for the layouting engine.
///This is internal. The public API for dealing with sizing is InitialOption.
/// This is internal. The public API for dealing with sizing is InitialOption.
///@sa InitialOption
enum class DefaultSizeMode
{
@@ -76,9 +74,8 @@ enum class DefaultSizeMode
Q_ENUM_NS(DefaultSizeMode)
///@brief Only here for source-compat with v1.2. Do not use.
///Use InitialVisibilityOption instead.
enum AddingOption
{
/// Use InitialVisibilityOption instead.
enum AddingOption {
AddingOption_None = 0,
AddingOption_StartHidden
};
@@ -92,15 +89,15 @@ enum class InitialVisibilityOption
Q_ENUM_NS(InitialVisibilityOption)
/**
* @brief Struct describing the preferred dock widget size and visibility when adding it to a layout
*
* You can pass this to MainWindowBase::addDockWidget() to give an hint of your preferred size
* and visibility.
*
* See below the documentation for InitialOption::visibility and InitialOption::preferredSize.
*
* @sa MainWindowBase::addDockWidget()
*/
* @brief Struct describing the preferred dock widget size and visibility when adding it to a layout
*
* You can pass this to MainWindowBase::addDockWidget() to give an hint of your preferred size
* and visibility.
*
* See below the documentation for InitialOption::visibility and InitialOption::preferredSize.
*
* @sa MainWindowBase::addDockWidget()
*/
struct InitialOption
{
// Implicit ctors for convenience:
@@ -147,22 +144,22 @@ struct InitialOption
}
/**
* @brief Allows a dock widget to be docked as hidden.
*
* Next time you call DockWidget::show() it will be shown at that place. This avoids
* flickering, as no show()/hide() workarounds are needed.
*/
* @brief Allows a dock widget to be docked as hidden.
*
* Next time you call DockWidget::show() it will be shown at that place. This avoids
* flickering, as no show()/hide() workarounds are needed.
*/
InitialVisibilityOption visibility = InitialVisibilityOption::StartVisible;
/**
* @brief Allows to control the size a dock widget should get when docked.
*
* If an invalid or empty size is passed then KDDW's default heuristics are applied.
*
* Note that usually only the width or the height will be honoured: For example, when adding a
* dock widget to the left then only the preferred width will be taken into account, as the
* height will simply fill the whole layout.
*/
* @brief Allows to control the size a dock widget should get when docked.
*
* If an invalid or empty size is passed then KDDW's default heuristics are applied.
*
* Note that usually only the width or the height will be honoured: For example, when adding a
* dock widget to the left then only the preferred width will be taken into account, as the
* height will simply fill the whole layout.
*/
QSize preferredSize;
private:
@@ -179,11 +176,10 @@ private:
DefaultSizeMode sizeMode = DefaultSizeMode::Fair;
};
enum RestoreOption
{
enum RestoreOption {
RestoreOption_None = 0,
RestoreOption_RelativeToMainWindow = 1, ///< Skips restoring the main window geometry and the restored dock widgets will use relative sizing.
///< Loading layouts won't change the main window geometry and just use whatever the user has at the moment.
///< Loading layouts won't change the main window geometry and just use whatever the user has at the moment.
};
Q_DECLARE_FLAGS(RestoreOptions, RestoreOption)
Q_ENUM_NS(RestoreOptions)
@@ -197,8 +193,7 @@ enum class DropIndicatorType
Q_ENUM_NS(DropIndicatorType)
///@internal
enum SuggestedGeometryHint
{
enum SuggestedGeometryHint {
SuggestedGeometryHint_None,
SuggestedGeometryHint_PreserveCenter = 1,
SuggestedGeometryHint_GeometryIsFromDocked = 2
@@ -230,8 +225,7 @@ enum class TitleBarButtonType
Q_ENUM_NS(TitleBarButtonType)
///@brief Enum describing the different drop indicator types
enum DropLocation
{
enum DropLocation {
DropLocation_None = 0,
DropLocation_Left = 1,
DropLocation_Top = 2,
@@ -254,8 +248,7 @@ inline Qt5Qt6Compat::qhashtype qHash(SideBarLocation loc, Qt5Qt6Compat::qhashtyp
}
///@internal
enum CursorPosition
{
enum CursorPosition {
CursorPosition_Undefined = 0,
CursorPosition_Left = 1,
CursorPosition_Right = 2,
@@ -274,8 +267,7 @@ Q_ENUM_NS(CursorPosition)
///@internal
enum FrameOption
{
enum FrameOption {
FrameOption_None = 0,
FrameOption_AlwaysShowsTabs = 1,
FrameOption_IsCentralFrame = 2,
@@ -286,13 +278,12 @@ Q_DECLARE_FLAGS(FrameOptions, FrameOption)
Q_ENUM_NS(FrameOptions)
///@internal
enum TabWidgetOption
{
TabWidgetOption_None = 0,
TabWidgetOption_DocumentMode = 1 ///> Enables QTabWidget::documentMode()
enum StackOption {
StackOption_None = 0,
StackOption_DocumentMode = 1 ///> Enables QTabWidget::documentMode()
};
Q_DECLARE_FLAGS(TabWidgetOptions, TabWidgetOption)
Q_ENUM_NS(TabWidgetOptions)
Q_DECLARE_FLAGS(StackOptions, StackOption)
Q_ENUM_NS(StackOptions)
///@internal
inline QString locationStr(Location loc)

View File

@@ -55,14 +55,14 @@ static FrameOptions actualOptions(FrameOptions options)
return options;
}
static TabWidgetOptions tabWidgetOptions(FrameOptions options)
static StackOptions tabWidgetOptions(FrameOptions options)
{
if (options & FrameOption_NonDockable) {
/// If we can't tab things into this Frame then let's not draw the QTabWidget frame either
return TabWidgetOption_DocumentMode;
return StackOption_DocumentMode;
}
return TabWidgetOption_None;
return StackOption_None;
}
}

View File

@@ -11,26 +11,24 @@
#include "Stack.h"
#include "Config.h"
#include "views_qtwidgets/Stack_qtwidgets.h"
#include "kddockwidgets/FrameworkWidgetFactory.h"
#include "private/Logging_p.h"
#include "private/Utils_p.h"
#include "private/WindowBeingDragged_p.h"
#include "DockWidget_p.h"
#include "views/Stack.h"
#include "controllers/TabBar.h"
#include "controllers/Frame.h"
#include "controllers/FloatingWindow.h"
#include <QDebug>
#include <QTabBar> // TODO Remove
#include <qobject.h>
using namespace KDDockWidgets;
using namespace KDDockWidgets::Controllers;
Stack::Stack(Frame *frame, TabWidgetOptions options)
: Controller(Type::Frame, Config::self().frameworkWidgetFactory()->createTabWidget(this, frame))
Stack::Stack(Frame *frame, StackOptions options)
: Controller(Type::Stack, Config::self().frameworkWidgetFactory()->createTabWidget(this, frame))
, Draggable(view(), Config::self().flags() & (Config::Flag_HideTitleBarWhenTabsVisible | Config::Flag_AlwaysShowTabs))
, m_tabBar(new TabBar(this))
, m_frame(frame)
@@ -44,7 +42,7 @@ Stack::~Stack()
delete m_tabBar;
}
TabWidgetOptions Stack::options() const
StackOptions Stack::options() const
{
return m_options;
}
@@ -54,15 +52,9 @@ void Stack::setCurrentDockWidget(DockWidget *dw)
setCurrentDockWidget(indexOfDockWidget(dw));
}
bool Stack::isPositionDraggable(QPoint p) const // TODO: Move to view
bool Stack::isPositionDraggable(QPoint p) const
{
auto view = qobject_cast<Views::Stack_qtwidgets *>(this->view()->asQWidget()); // TODO
if (view->tabPosition() != QTabWidget::North) { // TODO
qWarning() << Q_FUNC_INFO << "Not implemented yet. Only North is supported";
return false;
}
return p.y() >= 0 && p.y() <= view->tabBar()->height();
return dynamic_cast<Views::Stack *>(view())->isPositionDraggable(p);
}
DockWidgetBase *Stack::currentDockWidget() const
@@ -211,14 +203,12 @@ bool Stack::onMouseDoubleClick(QPoint localPos)
void Stack::setTabBarAutoHide(bool is)
{
// TODO
qobject_cast<Views::Stack_qtwidgets *>(view()->asQWidget())->setTabBarAutoHide(is);
dynamic_cast<Views::Stack *>(view())->setTabBarAutoHide(is);
}
void Stack::renameTab(int index, const QString &text)
{
// TODO
qobject_cast<Views::Stack_qtwidgets *>(view()->asQWidget())->renameTab(index, text);
dynamic_cast<Views::Stack *>(view())->renameTab(index, text);
}
Controllers::TabBar *Stack::tabBar() const
@@ -228,45 +218,40 @@ Controllers::TabBar *Stack::tabBar() const
int Stack::currentIndex() const
{
// TODO
return qobject_cast<Views::Stack_qtwidgets *>(view()->asQWidget())->currentIndex();
return dynamic_cast<Views::Stack *>(view())->currentIndex();
}
int Stack::numDockWidgets() const
{
// TODO
return qobject_cast<Views::Stack_qtwidgets *>(view()->asQWidget())->numDockWidgets();
return dynamic_cast<Views::Stack *>(view())->numDockWidgets();
}
void Stack::changeTabIcon(int index, const QIcon &icon)
{
// TODO
qobject_cast<Views::Stack_qtwidgets *>(view()->asQWidget())->changeTabIcon(index, icon);
dynamic_cast<Views::Stack *>(view())->changeTabIcon(index, icon);
}
DockWidgetBase *Stack::dockwidgetAt(int index) const
{
// TODO
return qobject_cast<Views::Stack_qtwidgets *>(view()->asQWidget())->dockwidgetAt(index);
return dynamic_cast<Views::Stack *>(view())->dockwidgetAt(index);
}
int Stack::indexOfDockWidget(const DockWidget *dw) const
{
// TODO
return qobject_cast<Views::Stack_qtwidgets *>(view()->asQWidget())->indexOfDockWidget(dw);
return dynamic_cast<Views::Stack *>(view())->indexOfDockWidget(dw);
}
void Stack::removeDockWidget(DockWidget *dw)
{
qobject_cast<Views::Stack_qtwidgets *>(view()->asQWidget())->removeDockWidget(dw);
dynamic_cast<Views::Stack *>(view())->removeDockWidget(dw);
}
bool Stack::insertDockWidget(int index, DockWidget *dw, const QIcon &icon, const QString &title)
{
return qobject_cast<Views::Stack_qtwidgets *>(view()->asQWidget())->insertDockWidget(index, dw, icon, title);
return dynamic_cast<Views::Stack *>(view())->insertDockWidget(index, dw, icon, title);
}
void Stack::setCurrentDockWidget(int index)
{
return qobject_cast<Views::Stack_qtwidgets *>(view()->asQWidget())->setCurrentDockWidget(index);
dynamic_cast<Views::Stack *>(view())->setCurrentDockWidget(index);
}

View File

@@ -27,7 +27,7 @@ class DOCKS_EXPORT Stack : public Controller, public Draggable
{
Q_OBJECT
public:
explicit Stack(Frame *frame, TabWidgetOptions); // TODO: Rename TabWidgetOptions
explicit Stack(Frame *frame, StackOptions);
virtual ~Stack() override;
/**
@@ -105,7 +105,7 @@ public:
bool isMDI() const override;
bool isPositionDraggable(QPoint p) const override;
TabWidgetOptions options() const;
StackOptions options() const;
Q_SIGNALS:
void currentTabChanged(int index);
@@ -121,7 +121,7 @@ public: // TODO
private:
TabBar *const m_tabBar;
Frame *const m_frame;
const TabWidgetOptions m_options;
const StackOptions m_options;
Q_DISABLE_COPY(Stack)
};

47
src/views/Stack.h Normal file
View File

@@ -0,0 +1,47 @@
/*
This file is part of KDDockWidgets.
SPDX-FileCopyrightText: 2020-2022 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
class QPoint;
class QIcon;
class QString;
namespace KDDockWidgets {
namespace Controllers {
class DockWidget;
}
namespace Views {
/// @brief The interface that Stack views should implement
class Stack
{
public:
virtual bool isPositionDraggable(QPoint p) const = 0;
virtual void setTabBarAutoHide(bool is) = 0;
virtual void renameTab(int index, const QString &) = 0;
virtual int currentIndex() const = 0;
virtual int numDockWidgets() const = 0;
virtual void changeTabIcon(int index, const QIcon &icon) = 0;
virtual Controllers::DockWidget *dockwidgetAt(int index) const = 0;
virtual int indexOfDockWidget(const Controllers::DockWidget *dw) const = 0;
virtual void removeDockWidget(Controllers::DockWidget *dw) = 0;
virtual bool insertDockWidget(int index, Controllers::DockWidget *dw,
const QIcon &icon, const QString &title) = 0;
virtual void setCurrentDockWidget(int index) = 0;
};
}
}

View File

@@ -17,7 +17,7 @@ namespace KDDockWidgets {
namespace Views {
/// Brief The interface that title bar views should implement
/// @brief The interface that TitleBar views should implement
class TitleBar
{
public:

View File

@@ -64,7 +64,7 @@ void Stack_qtwidgets::init()
setupTabBarButtons();
setDocumentMode(m_stack->options() & TabWidgetOption_DocumentMode);
setDocumentMode(m_stack->options() & StackOption_DocumentMode);
}
int Stack_qtwidgets::numDockWidgets() const
@@ -232,3 +232,13 @@ Controllers::Stack *Stack_qtwidgets::stack() const
{
return m_stack;
}
bool Stack_qtwidgets::isPositionDraggable(QPoint p) const
{
if (tabPosition() != QTabWidget::North) {
qWarning() << Q_FUNC_INFO << "Not implemented yet. Only North is supported";
return false;
}
return p.y() >= 0 && p.y() <= tabBar()->height();
}

View File

@@ -13,6 +13,7 @@
#pragma once
#include "View_qtwidgets.h"
#include "views/Stack.h"
#include <QTabWidget>
@@ -29,7 +30,7 @@ class Frame;
namespace KDDockWidgets {
namespace Views {
class DOCKS_EXPORT Stack_qtwidgets : public View_qtwidgets<QTabWidget>
class DOCKS_EXPORT Stack_qtwidgets : public View_qtwidgets<QTabWidget>, public Stack
{
Q_OBJECT
public:
@@ -39,24 +40,25 @@ public:
Controllers::Stack *stack() const;
QTabBar *tabBar() const;
int numDockWidgets() const;
void removeDockWidget(Controllers::DockWidget *);
int indexOfDockWidget(const Controllers::DockWidget *) const;
int numDockWidgets() const override;
void removeDockWidget(Controllers::DockWidget *) override;
int indexOfDockWidget(const Controllers::DockWidget *) const override;
bool isPositionDraggable(QPoint p) const override;
void init() override;
public: // TODO: make protected
void mouseDoubleClickEvent(QMouseEvent *) override;
void mousePressEvent(QMouseEvent *) override;
void tabInserted(int index) override;
void tabRemoved(int index) override;
void setCurrentDockWidget(int index);
bool insertDockWidget(int index, Controllers::DockWidget *, const QIcon &, const QString &title);
void setTabBarAutoHide(bool);
void renameTab(int index, const QString &);
void changeTabIcon(int index, const QIcon &);
void init() override;
Controllers::DockWidget *dockwidgetAt(int index) const;
int currentIndex() const;
void setCurrentDockWidget(int index) override;
bool insertDockWidget(int index, Controllers::DockWidget *, const QIcon &, const QString &title) override;
void setTabBarAutoHide(bool) override;
void renameTab(int index, const QString &) override;
void changeTabIcon(int index, const QIcon &) override;
Controllers::DockWidget *dockwidgetAt(int index) const override;
int currentIndex() const override;
/// @brief Shows the context menu. Override to implement your own context menu.
/// By default it's used to honour Config::Flag_AllowSwitchingTabsViaMenu