1
0
Fork 0
This commit is contained in:
Duncan Ogilvie 2019-11-22 04:30:52 +01:00
parent 824100eea8
commit 4ab268209d
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
30 changed files with 3122 additions and 10 deletions

2
deps

@ -1 +1 @@
Subproject commit be0d812e919272f86be3a819c986db03f1c78859
Subproject commit c395eb027c2b3b58969e60da2c40de469d167641

View File

@ -6,6 +6,7 @@
#include <QFileDialog>
#include <QMimeData>
#include <QDesktopServices>
#include <kddockwidgets/DockWidget.h>
#include "Configuration.h"
#include "SettingsDialog.h"
#include "AppearanceDialog.h"
@ -56,7 +57,7 @@
QString MainWindow::windowTitle = "";
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent),
: KDDockWidgets::MainWindow("x64dbg_MainWindow", KDDockWidgets::MainWindowOption_None, parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
@ -217,7 +218,7 @@ MainWindow::MainWindow(QWidget* parent)
// Add all widgets to the list
mWidgetList.push_back(WidgetInfo(mCpuWidget, "CPUTab"));
mWidgetList.push_back(WidgetInfo(mGraphView, "GraphTab"));
/*mWidgetList.push_back(WidgetInfo(mGraphView, "GraphTab"));
mWidgetList.push_back(WidgetInfo(mLogView, "LogTab"));
mWidgetList.push_back(WidgetInfo(mNotesManager, "NotesTab"));
mWidgetList.push_back(WidgetInfo(mBreakpointsView, "BreakpointsTab"));
@ -230,15 +231,32 @@ MainWindow::MainWindow(QWidget* parent)
mWidgetList.push_back(WidgetInfo(mReferenceManager, "ReferencesTab"));
mWidgetList.push_back(WidgetInfo(mThreadView, "ThreadsTab"));
mWidgetList.push_back(WidgetInfo(mHandlesView, "HandlesTab"));
mWidgetList.push_back(WidgetInfo(mTraceBrowser, "TraceTab"));
mWidgetList.push_back(WidgetInfo(mTraceBrowser, "TraceTab"));*/
{
KDDockWidgets::DockWidget::List dockwidgets;
for(WidgetInfo & info : mWidgetList)
{
auto dock = new KDDockWidgets::DockWidget(info.nativeName);
dock->setWidget(info.widget);
dock->setTitle(info.widget->windowTitle());
dock->show();
dockwidgets << dock;
info.widget->show();
}
addDockWidget(dockwidgets[0], KDDockWidgets::Location_None);
/*for(int i = 1; i < dockwidgets.size(); i++)
dockwidgets[i - 1]->addDockWidgetAsTab(dockwidgets[i]);*/
}
/*
// If LoadSaveTabOrder disabled, load tabs in default order
if(!ConfigBool("Gui", "LoadSaveTabOrder"))
loadTabDefaultOrder();
else
loadTabSavedOrder();
setCentralWidget(mTabWidget);
setCentralWidget(mTabWidget);*/
// Setup the command and status bars
setupCommandBar();
@ -348,7 +366,7 @@ MainWindow::MainWindow(QWidget* parent)
connect(mCpuWidget->getStackWidget(), SIGNAL(displayReferencesWidget()), this, SLOT(displayReferencesWidget()));
connect(mTabWidget, SIGNAL(tabMovedTabWidget(int, int)), this, SLOT(tabMovedSlot(int, int)));
//connect(mTabWidget, SIGNAL(tabMovedTabWidget(int, int)), this, SLOT(tabMovedSlot(int, int)));
connect(Config(), SIGNAL(shortcutsUpdated()), this, SLOT(refreshShortcuts()));
// Setup favourite tools menu
@ -378,7 +396,7 @@ MainWindow::MainWindow(QWidget* parent)
mCpuWidget->setDisasmFocus();
QTimer::singleShot(0, this, SLOT(loadWindowSettings()));
//QTimer::singleShot(0, this, SLOT(loadWindowSettings()));
}
MainWindow::~MainWindow()
@ -498,7 +516,7 @@ void MainWindow::closeEvent(QCloseEvent* event)
duint noClose = 0;
if(bCanClose)
{
saveWindowSettings();
//saveWindowSettings();
}
if(BridgeSettingGetUint("Gui", "NoCloseDialog", &noClose) && noClose)
mCloseDialog->hide();
@ -527,6 +545,7 @@ void MainWindow::closeEvent(QCloseEvent* event)
void MainWindow::setTab(QWidget* widget)
{
return; //TODO
// shown tabs
for(int i = 0; i < mTabWidget->count(); i++)
{
@ -947,7 +966,7 @@ void MainWindow::dropEvent(QDropEvent* pEvent)
bool MainWindow::event(QEvent* event)
{
// just make sure mTabWidget take current view as the latest
if(event->type() == QEvent::WindowActivate && this->isActiveWindow())
if(false && event->type() == QEvent::WindowActivate && this->isActiveWindow())
{
mTabWidget->setCurrentIndex(mTabWidget->currentIndex());
}
@ -1665,6 +1684,7 @@ void MainWindow::showQWidgetTab(QWidget* qWidget)
void MainWindow::closeQWidgetTab(QWidget* qWidget)
{
return;
for(int i = 0; i < mTabWidget->count(); i++)
{
if(mTabWidget->widget(i) == qWidget)
@ -1682,6 +1702,7 @@ void MainWindow::executeOnGuiThread(void* cbGuiThread, void* userdata)
void MainWindow::tabMovedSlot(int from, int to)
{
return;
for(int i = 0; i < mTabWidget->count(); i++)
{
// Remove space in widget name and append Tab to get config settings (CPUTab, MemoryMapTab, etc...)

View File

@ -2,6 +2,7 @@
#define MAINWINDOW_H
#include <QMainWindow>
#include <kddockwidgets/MainWindow.h>
#include "Imports.h"
class QDragEnterEvent;
@ -40,7 +41,7 @@ namespace Ui
class MainWindow;
}
class MainWindow : public QMainWindow
class MainWindow : public KDDockWidgets::MainWindow
{
Q_OBJECT

View File

@ -0,0 +1,144 @@
/*
This file is part of KDDockWidgets.
Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
Author: Sérgio Martins <sergio.martins@kdab.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Application-wide config to tune certain behaviours of the framework.
*
* @author Sérgio Martins \<sergio.martins@kdab.com\>
*/
#ifndef KD_DOCKWIDGETS_CONFIG_H
#define KD_DOCKWIDGETS_CONFIG_H
#include "docks_export.h"
class QQmlEngine;
namespace KDDockWidgets
{
class DockWidgetBase;
class FrameworkWidgetFactory;
typedef KDDockWidgets::DockWidgetBase* (*DockWidgetFactoryFunc)(const QString & name);
/**
* @brief Singleton to allow to choose certain behaviours of the framework.
*
* The setters should only be used before creating any DockWidget or MainWindow,
* preferably right after creating the QApplication.
*/
class DOCKS_EXPORT Config
{
public:
///@brief returns the singleton Config instance
static Config & self();
///@brief destructor, called at shutdown
~Config();
///@brief Flag enum to tune certain behaviours, the defaults are Flag_Default
enum Flag
{
Flag_None = 0, ///> No option set
Flag_NativeTitleBar = 1, ///> Enables the Native OS title bar on OSes that support it (Windows 10, macOS), ignored otherwise. This is mutually exclusive with Flag_AeroSnap
Flag_AeroSnapWithClientDecos = 2, ///> Enables AeroSnap even if we're not using the native title bar. Only supported on Windows 10.
Flag_HideTitleBarWhenTabsVisible = 8, ///> Hides the title bar if there's tabs visible. The empty space in the tab bar becomes draggable.
Flag_AlwaysShowTabs = 16, ///> Always show tabs, even if there's only one
Flag_Default = Flag_AeroSnapWithClientDecos ///> The defaults
};
Q_DECLARE_FLAGS(Flags, Flag)
///@brief returns the chosen flags
Flags flags() const;
///@brief setter for the flags
///@param flags the flags to set
///Not all flags are guaranteed to be set, as the OS might not supported them
///Call @ref flags() after the setter if you need to know what was really set
void setFlags(Flags flags);
/**
* @brief Registers a DockWidgetFactoryFunc.
*
* This is optional, the default is nullptr.
*
* A DockWidgetFactoryFunc is a function that receives a dock widget name
* and returns a DockWidget instance.
*
* While restoring, @ref LayoutSaver requires all dock widgets to exist.
* If a DockWidget doesn't exist then a DockWidgetFactoryFunc function is
* required, so the layout saver can ask to create the DockWidget and then
* restore it.
*/
void setDockWidgetFactoryFunc(DockWidgetFactoryFunc);
///@brief Returns the DockWidgetFactoryFunc.
///nullptr by default
DockWidgetFactoryFunc dockWidgetFactoryFunc() const;
/**
* @brief Sets the WidgetFactory.
*
* By default DefaultWidgetFactory is used, which gives you FrameWidget, TitleBarWidget,
* TabBarWidget, TabWidgetWidget etc. You can set your own factory, to supply your own variants
* of those classes, for the purposes of changing GUI appearance and such.
*
* Also potentially useful to return QtQuick classes instead of the QtWidget based ones.
* Ownership is taken.
*/
void setFrameworkWidgetFactory(FrameworkWidgetFactory*);
///@brief getter for the framework widget factory
FrameworkWidgetFactory* frameworkWidgetFactory() const;
/**
* @brief Returns the thickness of the separator.
*
* Returns the width if the separator is vertical, otherwise the height.
* If @p staticSeparator is true, then returns for the static separators.
* The static separators are the ones at the edges of the window (top, left, bottom, right).
*
* Default is 0px for static separators and 5px for normal separators.
*/
int separatorThickness(bool staticSeparator) const;
///@brief setter for @ref separatorThickness
///Note: Only use this function at startup before creating any DockWidget or MainWindow.
void setSeparatorThickness(int value, bool staticSeparator);
///@brief Sets the QQmlEngine to use. Applicable only when using QtQuick.
void setQmlEngine(QQmlEngine*);
QQmlEngine* qmlEngine() const;
private:
Q_DISABLE_COPY(Config)
Config();
class Private;
Private* const d;
};
}
Q_DECLARE_OPERATORS_FOR_FLAGS(KDDockWidgets::Config::Flags)
#endif

View File

@ -0,0 +1,74 @@
/*
This file is part of KDDockWidgets.
Copyright (C) 2018-2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
Author: Sérgio Martins <sergio.martins@kdab.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Represents a dock widget.
*
* @author Sérgio Martins \<sergio.martins@kdab.com\>
*/
#ifndef KD_DOCKWIDGET_H
#define KD_DOCKWIDGET_H
#include "DockWidgetBase.h"
class QCloseEvent;
namespace KDDockWidgets
{
/**
* @brief Represents a dock widget.
*
* Most of the interface lives in DockWidgetBase, to facilitate sharing with QtQuick.
*/
class DOCKS_EXPORT DockWidget : public DockWidgetBase
{
Q_OBJECT
public:
/**
* @brief constructs a new DockWidget
* @param uniqueName Mandatory name that should be unique between all DockWidget instances.
* This name won't be user visible and just used internally for the save/restore.
* Use setTitle() for user visible text.
* @param options optional options controlling behaviour
*
* There's no parent argument. The DockWidget is either parented to FloatingWindow or MainWindow
* when visible, or stays without a parent when hidden. This allows to support docking
* to different main windows.
*/
explicit DockWidget(const QString & uniqueName, Options options = {});
///@brief destructor
~DockWidget() override;
protected:
bool event(QEvent*) override;
void closeEvent(QCloseEvent*) override;
private:
class Private;
Private* const d;
};
}
#endif

View File

@ -0,0 +1,314 @@
/*
This file is part of KDDockWidgets.
Copyright (C) 2018-2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
Author: Sérgio Martins <sergio.martins@kdab.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief The DockWidget base-class that's shared between QtWidgets and QtQuick stack.
*
* @author Sérgio Martins \<sergio.martins@kdab.com\>
*/
#ifndef KD_DOCKWIDGET_BASE_H
#define KD_DOCKWIDGET_BASE_H
#include "docks_export.h"
#include "KDDockWidgets.h"
#include "QWidgetAdapter.h"
#include "LayoutSaver_p.h"
#include <QVector>
#include <QWidget>
class QAction;
namespace KDDockWidgets
{
class Frame;
class FloatingWindow;
class DragController;
class Item;
class LastPosition;
class DockRegistry;
class LayoutSaver;
class TabWidget;
class TitleBar;
/**
* @brief The DockWidget base-class. DockWidget and DockWidgetBase are only
* split in two so we can share some code with the QtQuick implementation,
* which also derives from DockWidgetBase.
*
* Do not use instantiate directly in user code. Use DockWidget instead.
*/
class DOCKS_EXPORT DockWidgetBase : public QWidgetOrQuick
{
Q_OBJECT
public:
typedef QVector<DockWidgetBase*> List;
///@brief DockWidget options to pass at construction time
enum Option
{
Option_None = 0, ///< No option, the default
Option_NotClosable = 1 /// The DockWidget can't be closed on the [x], only programatically
};
Q_DECLARE_FLAGS(Options, Option)
/**
* @brief constructs a new DockWidget
* @param name the name of the dockwidget, should be unique. Use title for user visible text.
* @param options optional options controlling behaviour
*
* There's no parent argument. The DockWidget is either parented to FloatingWindow or MainWindow
* when visible, or stays without a parent when hidden.
*/
explicit DockWidgetBase(const QString & uniqueName, Options options = {});
///@brief destructor
~DockWidgetBase() override;
/**
* @param Constructs a dock widget from its serialized form.
* @internal
*/
static DockWidgetBase* deserialize(const LayoutSaver::DockWidget::Ptr &);
/**
* @param Serializes this dock widget into an intermediate form
*/
LayoutSaver::DockWidget::Ptr serialize() const;
/**
* @brief docks @p other widget into this one. Tabs will be shown if not already.
* @param other The other dock widget to dock into this one.
* @sa MainWindow::addDockWidget(), DockWidget::addDockWidgetToContainingWindow()
*/
void addDockWidgetAsTab(DockWidgetBase* other);
/**
* @brief docks @p other widget into the window that contains this one.
* Equivalent to @ref MainWindow::addDockWidge() with the difference
* that it also supports the case where the top-level window is a
* @ref FloatingWindow instead of @ref MainWindow.
*
* @param other The other dock widget to dock into the window.
* @param location The location to dock.
* @param relativeTo The dock widget that the @p location is relative to. If null then the window is considered.
* @sa MainWindow::addDockWidget(), DockWidget::addDockWidgetAsTab()
*/
void addDockWidgetToContainingWindow(DockWidgetBase* other, KDDockWidgets::Location location,
DockWidgetBase* relativeTo = nullptr);
/**
* @brief sets the widget which this dock widget hosts.
* @param widget to show inside this dock widget
*/
void setWidget(QWidget* widget);
/**
* @brief returns the widget which this dock widget hosts
*/
QWidget* widget() const;
/**
* @brief Returns whether the dock widget is floating.
* Floating means it's not docked and has a window of its own.
* Note that if you dock a floating dock widget into another floating one
* then they don't count as floating anymore, as they are
* side-by-side (or tabbed).
*/
bool isFloating() const;
/**
* @brief setter to make the dock widget float or dock.
* @param floats If true makes the dock widget float, otherwise docks it.
*/
void setFloating(bool floats);
/**
* @brief Returns the QAction that allows to hide/show the dock widget
* Useful to put in menus.
*/
QAction* toggleAction() const;
/**
* @brief the dock widget's unique name.
* @internal
*/
QString uniqueName() const;
/**
* @brief Returns the dock widget's title.
* This title is visible in title bars and tab bars.
* @sa setTitle
*/
QString title() const;
/**
* @brief setter for the dock widget's title
* @param title the dock widget's new title
* @sa setTitle
*/
void setTitle(const QString & title);
/**
* @brief Returns the dock widget's options which control behaviour
* These options were passed at construction time and are immutable.
*/
Options options() const;
/**
* @brief returns if this dock widget is tabbed into another
*
* Technically a docked DockWidget always lives in a tab widget, but from the user's prespective
* it's not tabbed when there's only 1 dock widget, as there are no tabs displayed. Unless
* the frame is using Option_AlwaysShowsTabs, in which case this method will return true regardless
* if being the single one.
*/
bool isTabbed() const;
/**
* @brief Returns true if this dock widget is the current one in the tab
* widget that contains it. If the dock widget is alone then true is
* returned, as in this case there will also be a tab widget even
* though it's invisible.
*/
bool isCurrentTab() const;
/**
* @brief Makes this dock widget current in its tab group.
*/
void setAsCurrentTab();
/**
* @brief Sets an icon to show on title bars and tab bars.
* By default none is shown.
*/
void setIcon(const QIcon & icon);
/**
* @brief Returns the dock widget's icon.
*/
QIcon icon() const;
/**
* @brief Like QWidget::close() but the hosted widget won't be asked if we
* should close.
*/
void forceClose();
/**
* @brief Returns this dock widget's title bar.
*
* Note that several dock widgets can have the same title bar, in case they are tabbed together.
* Hidden dock widgets have no associated title bar.
*/
TitleBar* titleBar() const;
Q_SIGNALS:
///@brief signal emitted when the parent changed
void parentChanged();
///@brief signal emitted when the DockWidget is shown. As in QEvent::Show.
void shown();
///@brief signal emitted when the DockWidget is hidden. As in QEvent::Hide.
void hidden();
///@brief signal emitted when the icon changed
void iconChanged();
///@brief signal emitted when the title changed
void titleChanged();
///@brief emitted when the hosted widget changed
void widgetChanged(QWidget*);
protected:
void onParentChanged();
void onShown(bool spontaneous);
void onHidden(bool spontaneous);
void onClosed(QCloseEvent* e);
#if defined(DOCKS_DEVELOPER_MODE)
public Q_SLOTS:
#else
private Q_SLOTS:
#endif
/**
* @brief Creates a FloatingWindow and adds itself into it
* @return the created FloatingWindow
*/
KDDockWidgets::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();
#if defined(DOCKS_DEVELOPER_MODE)
public:
#else
private:
#endif
Q_DISABLE_COPY(DockWidgetBase)
friend class MultiSplitterLayout;
friend class Frame;
friend class DropArea;
friend class TestDocks;
friend class Item;
friend class KDDockWidgets::TabWidget;
friend class KDDockWidgets::TitleBar;
friend class KDDockWidgets::DragController;
friend class KDDockWidgets::Item;
friend class KDDockWidgets::DockRegistry;
friend class KDDockWidgets::LayoutSaver;
/**
* @brief the Frame which contains this dock widgets.
*
* A frame 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 MultiSplitter.
*
* It's nullptr immediately after creation.
*/
Frame* frame() const;
/**
* @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.
*/
FloatingWindow* floatingWindow() const;
///@brief adds the current layout item containing this dock widget
void addPlaceholderItem(Item*);
///@brief returns the last position, just for tests. TODO Make tests just use the d-pointer.
LastPosition* lastPosition() const;
class Private;
Private* const d;
};
}
#endif

View File

@ -0,0 +1,147 @@
/*
This file is part of KDDockWidgets.
Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
Author: Sérgio Martins <sergio.martins@kdab.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KDDOCKWIDGETS_FRAMEWORKWIDGETFACTORY_H
#define KDDOCKWIDGETS_FRAMEWORKWIDGETFACTORY_H
#include "docks_export.h"
#include "KDDockWidgets.h"
#include "QWidgetAdapter.h"
/**
* @file
* @brief A factory class for allowing the user to customize some internal widgets.
*
* @author Sérgio Martins \<sergio.martins@kdab.com\>
*/
namespace KDDockWidgets
{
class DropIndicatorOverlayInterface;
class Separator;
class FloatingWindow;
class TabWidget;
class TitleBar;
class Frame;
class DropArea;
class Anchor;
class TabBar;
/**
* @brief A factory class for allowing the user to customize some internal widgets.
* This is optional, and if not provided, a default one will be used, @ref DefaultWidgetFactory.
*
* Deriving from @ref DefaultWidgetFactory is recommended, unless you need to override
* all methods.
*
* Sub-classing FrameworkWidgetFactory allows for fine-grained customization and
* styling of some non-public widgets, such as titlebars, dock widget frame and
* tab widgets.
*
* To set your own factory see Config::setFrameworkWidgetFactory()
*
* Will also be useful to provide a QtQuickWidget factory in the future.
*
* @sa Config::setFrameworkWidgetFactory()
*/
class DOCKS_EXPORT FrameworkWidgetFactory
{
public:
///@brief Destructor.Don't delete FrameworkWidgetFactory directly, it's owned
/// by the framework.
virtual ~FrameworkWidgetFactory();
///@brief Called internally by the framework to create a Frame class
//// Override to provide your own Frame sub-class. A frame is the
/// widget that holds the titlebar and tab-widget which holds the
/// DockWidgets.
///@param parent just forward to Frame's constructor
///@param options just forward to Frame's constructor
virtual Frame* createFrame(QWidgetOrQuick* parent = nullptr, FrameOptions = FrameOption_None) const = 0;
///@brief Called internally by the framework to create a TitleBar
/// Override to provide your own TitleBar sub-class. If overridden then
/// you also need to override the overload below.
///@param frame Just forward to TitleBar's constructor.
virtual TitleBar* createTitleBar(Frame* frame) const = 0;
///@brief Called internally by the framework to create a TitleBar
/// Override to provide your own TitleBar sub-class. If overridden then
/// you also need to override the overload above.
///@param floatingWindow Just forward to TitleBar's constructor.
virtual TitleBar* createTitleBar(FloatingWindow* floatingWindow) const = 0;
///@brief Called internally by the framework to create a TabBar
/// Override to provide your own TabBar sub-class.
///@param parent Just forward to TabBar's's constructor.
virtual TabBar* createTabBar(TabWidget* parent = nullptr) const = 0;
///@brief Called internally by the framework to create a TabWidget
/// Override to provide your own TabWidget sub-class.
///@param parent Just forward to TabWidget's constructor.
virtual TabWidget* createTabWidget(Frame* parent) const = 0;
///@brief Called internally by the framework to create a Separator
/// Override to provide your own Separator sub-class. The Separator allows
/// the user to resize nested dock widgets.
///@param anchor Just forward to Sepataror's constructor.
///@param parent Just forward to Separator's constructor.
virtual Separator* createSeparator(Anchor* anchor, QWidgetAdapter* parent = nullptr) const = 0;
///@brief Called internally by the framework to create a FloatingWindow
/// Override to provide your own FloatingWindow sub-class. If overridden then
/// you also need to override the overloads below.
///@param parent Just forward to FloatingWindow's constructor.
virtual FloatingWindow* createFloatingWindow(QWidgetOrQuick* parent = nullptr) const = 0;
///@brief Called internally by the framework to create a FloatingWindow
/// Override to provide your own FloatingWindow sub-class. If overridden then
/// you also need to override the overloads above.
///@param frame Just forward to FloatingWindow's constructor.
///@param parent Just forward to FloatingWindow's constructor.
virtual FloatingWindow* createFloatingWindow(Frame* frame, QWidgetOrQuick* parent = nullptr) const = 0;
///@brief Called internally by the framework to create a DropIndicatorOverlayInterface
/// Override to provide your own DropIndicatorOverlayInterface sub-class.
///@param dropArea Just forward to DropIndicatorOverlayInterface's constructor.
virtual DropIndicatorOverlayInterface* createDropIndicatorOverlay(DropArea* dropArea) const = 0;
};
/**
* @brief The FrameworkWidgetFactory that's used if none is specified.
*/
class DOCKS_EXPORT DefaultWidgetFactory : public FrameworkWidgetFactory
{
public:
Frame* createFrame(QWidgetOrQuick* parent, FrameOptions) const override;
TitleBar* createTitleBar(Frame*) const override;
TitleBar* createTitleBar(FloatingWindow*) const override;
TabBar* createTabBar(TabWidget* parent) const override;
TabWidget* createTabWidget(Frame* parent) const override;
Separator* createSeparator(Anchor* anchor, QWidgetAdapter* parent = nullptr) const override;
FloatingWindow* createFloatingWindow(QWidgetOrQuick* parent = nullptr) const override;
FloatingWindow* createFloatingWindow(Frame* frame, QWidgetOrQuick* parent = nullptr) const override;
DropIndicatorOverlayInterface* createDropIndicatorOverlay(DropArea*) const override;
};
}
#endif

View File

@ -0,0 +1,128 @@
/*
This file is part of KDDockWidgets.
Copyright (C) 2018-2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
Author: Sérgio Martins <sergio.martins@kdab.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief File with KDDockWidgets namespace-level enums and methods.
*
* @author Sérgio Martins \<sergio.martins@kdab.com\>
*/
#ifndef KD_KDDOCKWIDGETS_H
#define KD_KDDOCKWIDGETS_H
#include <QObject>
namespace KDDockWidgets
{
enum Location
{
Location_None,
Location_OnLeft, ///> Left docking location
Location_OnTop, ///> Top docking location
Location_OnRight, ///> Right docking location
Location_OnBottom ///> Bottom docking location
};
enum MainWindowOption
{
MainWindowOption_None = 0, ///> No option set
MainWindowOption_HasCentralFrame = 1 ///> Makes the MainWindow always have a central frame, for tabbing documents
};
Q_DECLARE_FLAGS(MainWindowOptions, MainWindowOption)
enum AddingOption
{
AddingOption_None = 0, ///> No option set
AddingOption_StartHidden ///< Don't show the dock widget when adding it
};
///@internal
enum FrameOption
{
FrameOption_None = 0,
FrameOption_AlwaysShowsTabs = 1,
FrameOption_IsCentralFrame = 2
};
Q_DECLARE_FLAGS(FrameOptions, FrameOption)
///@internal
inline Location oppositeLocation(Location loc)
{
switch(loc)
{
case Location_OnLeft:
return Location_OnRight;
case Location_OnTop:
return Location_OnBottom;
case Location_OnRight:
return Location_OnLeft;
case Location_OnBottom:
return Location_OnTop;
default:
Q_ASSERT(false);
return Location_None;
}
}
///@internal
inline Location adjacentLocation(Location loc)
{
switch(loc)
{
case Location_OnLeft:
return Location_OnTop;
case Location_OnTop:
return Location_OnRight;
case Location_OnRight:
return Location_OnBottom;
case Location_OnBottom:
return Location_OnLeft;
default:
Q_ASSERT(false);
return Location_None;
}
}
///@internal
inline QString locationStr(Location loc)
{
switch(loc)
{
case KDDockWidgets::Location_None:
return QStringLiteral("none");
case KDDockWidgets::Location_OnLeft:
return QStringLiteral("left");
case KDDockWidgets::Location_OnTop:
return QStringLiteral("top");
case KDDockWidgets::Location_OnRight:
return QStringLiteral("right");
case KDDockWidgets::Location_OnBottom:
return QStringLiteral("bottom");
}
return QString();
}
}
Q_DECLARE_METATYPE(KDDockWidgets::Location)
Q_DECLARE_OPERATORS_FOR_FLAGS(KDDockWidgets::FrameOptions)
#endif

View File

@ -0,0 +1,109 @@
/*
This file is part of KDDockWidgets.
Copyright (C) 2018-2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
Author: Sérgio Martins <sergio.martins@kdab.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KD_LAYOUTSAVER_H
#define KD_LAYOUTSAVER_H
/**
* @file
* @brief Class to save and restore dockwidget layouts.
*
* @author Sérgio Martins \<sergio.martins@kdab.com\>
*/
#include "docks_export.h"
class QByteArray;
namespace KDDockWidgets
{
class DockWidgetBase;
class DOCKS_EXPORT LayoutSaver
{
public:
///@brief Constructor. Construction on the stack is suggested.
LayoutSaver();
///@brief Destructor.
~LayoutSaver();
///@brief returns whether a restore (@ref restoreLayout) is in progress
static bool restoreInProgress();
/**
* @brief saves the layout to disk using QSettings
*/
bool saveToDisk();
/**
* @brief restores the layout from disk using QSettings.
* @return true on success
*/
bool restoreFromDisk();
/**
* @brief saves the layout into a byte array
*/
QByteArray serializeLayout() const;
/**
* @brief restores the layout from a byte array
* All MainWindows and DockWidgets should have been created before calling
* this function.
*
* If not all DockWidgets can be created beforehand then make sure to set
* a DockWidget factory via Config::setDockWidgetFactoryFunc()
*
* @sa Config::setDockWidgetFactoryFunc()
*
* @return true on success
*/
bool restoreLayout(const QByteArray &);
/**
* @brief returns a list of dock widgets which were restored since the last
* @ref restoreLayout() or @ref restoreFromDisk()
*
* Useful since some dock widgets can be new, and hence not be included in the last saved layout.
*/
QVector<DockWidgetBase*> restoredDockWidgets() const;
struct Layout;
struct MainWindow;
struct FloatingWindow;
struct DockWidget;
struct LastPosition;
struct MultiSplitterLayout;
struct Item;
struct Anchor;
struct Frame;
struct Placeholder;
private:
friend class TestDocks;
class Private;
Private* const d;
};
}
#endif

View File

@ -0,0 +1,548 @@
/*
This file is part of KDDockWidgets.
Copyright (C) 2018-2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
Author: Sérgio Martins <sergio.martins@kdab.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KD_LAYOUTSAVER_P_H
#define KD_LAYOUTSAVER_P_H
#include "LayoutSaver.h"
#include "KDDockWidgets.h"
#include <QRect>
#include <QDataStream>
#include <QDebug>
#include <memory>
#define ANCHOR_MAGIC_MARKER "e520c60e-cf5d-4a30-b1a7-588d2c569851"
#define MULTISPLITTER_LAYOUT_MAGIC_MARKER "bac9948e-5f1b-4271-acc5-07f1708e2611"
#define KDDOCKWIDGETS_SERIALIZATION_VERSION 1
namespace KDDockWidgets
{
struct LayoutSaver::Placeholder
{
typedef QVector<LayoutSaver::Placeholder> List;
bool isFloatingWindow;
int indexOfFloatingWindow;
int itemIndex;
QString mainWindowUniqueName;
};
struct LayoutSaver::LastPosition
{
QRect lastFloatingGeometry;
int tabIndex;
bool wasFloating;
LayoutSaver::Placeholder::List placeholders;
};
struct DOCKS_EXPORT LayoutSaver::DockWidget
{
// Using shared ptr, as we need to modify shared instances
typedef std::shared_ptr<LayoutSaver::DockWidget> Ptr;
typedef QVector<Ptr> List;
static QHash<QString, Ptr> s_dockWidgets;
bool isValid() const;
static Ptr dockWidgetForName(const QString & name)
{
auto dw = s_dockWidgets.value(name);
if(dw)
return dw;
dw = Ptr(new LayoutSaver::DockWidget);
dw->uniqueName = name;
return dw;
}
QString uniqueName;
LayoutSaver::LastPosition lastPosition;
private:
DockWidget() {}
};
struct LayoutSaver::Frame
{
bool isValid() const;
bool isNull = true;
QString objectName;
QRect geometry;
int options;
int currentTabIndex;
LayoutSaver::DockWidget::List dockWidgets;
};
struct LayoutSaver::Item
{
typedef QVector<LayoutSaver::Item> List;
bool isValid(const MultiSplitterLayout &) const;
QString objectName;
bool isPlaceholder;
QRect geometry;
QSize minSize;
int indexOfLeftAnchor;
int indexOfTopAnchor;
int indexOfRightAnchor;
int indexOfBottomAnchor;
LayoutSaver::Frame frame;
};
struct LayoutSaver::Anchor
{
typedef QVector<LayoutSaver::Anchor> List;
bool isValid(const LayoutSaver::MultiSplitterLayout & layout) const;
QString objectName;
QRect geometry;
int orientation;
int type;
int indexOfFrom;
int indexOfTo;
int indexOfFollowee;
QVector<int> side1Items;
QVector<int> side2Items;
};
struct LayoutSaver::MultiSplitterLayout
{
bool isValid() const;
LayoutSaver::Anchor::List anchors;
LayoutSaver::Item::List items;
QSize minSize;
QSize size;
};
struct LayoutSaver::FloatingWindow
{
typedef QVector<LayoutSaver::FloatingWindow> List;
bool isValid() const;
LayoutSaver::MultiSplitterLayout multiSplitterLayout;
int parentIndex = -1;
QRect geometry;
bool isVisible = true;
};
struct LayoutSaver::MainWindow
{
public:
typedef QVector<LayoutSaver::MainWindow> List;
bool isValid() const;
KDDockWidgets::MainWindowOptions options;
LayoutSaver::MultiSplitterLayout multiSplitterLayout;
QString uniqueName;
QRect geometry;
bool isVisible;
};
struct LayoutSaver::Layout
{
public:
bool isValid() const;
bool fillFrom(const QByteArray & serialized);
int serializationVersion = KDDOCKWIDGETS_SERIALIZATION_VERSION;
LayoutSaver::MainWindow::List mainWindows;
LayoutSaver::FloatingWindow::List floatingWindows;
LayoutSaver::DockWidget::List closedDockWidgets;
LayoutSaver::DockWidget::List allDockWidgets;
};
inline QDataStream & operator<<(QDataStream & ds, LayoutSaver::Placeholder* p)
{
ds << p->isFloatingWindow;
if(p->isFloatingWindow)
ds << p->indexOfFloatingWindow;
else
ds << p->mainWindowUniqueName;
ds << p->itemIndex;
return ds;
}
inline QDataStream & operator>>(QDataStream & ds, LayoutSaver::Placeholder* p)
{
ds >> p->isFloatingWindow;
if(p->isFloatingWindow)
ds >> p->indexOfFloatingWindow;
else
ds >> p->mainWindowUniqueName;
ds >> p->itemIndex;
return ds;
}
inline QDataStream & operator<<(QDataStream & ds, LayoutSaver::Anchor* a)
{
ds << QStringLiteral(ANCHOR_MAGIC_MARKER);
ds << a->objectName;
ds << a->geometry;
ds << a->orientation;
ds << a->type;
ds << a->indexOfFrom;
ds << a->indexOfTo;
ds << a->indexOfFollowee;
ds << a->side1Items;
ds << a->side2Items;
return ds;
}
inline QDataStream & operator>>(QDataStream & ds, LayoutSaver::Anchor* a)
{
QString marker;
ds >> marker;
if(marker != QLatin1String(ANCHOR_MAGIC_MARKER))
qWarning() << Q_FUNC_INFO << "Corrupt stream";
ds >> a->objectName;
ds >> a->geometry;
ds >> a->orientation;
ds >> a->type;
ds >> a->indexOfFrom;
ds >> a->indexOfTo;
ds >> a->indexOfFollowee;
ds >> a->side1Items;
ds >> a->side2Items;
return ds;
}
inline QDataStream & operator<<(QDataStream & ds, LayoutSaver::Frame* frame)
{
ds << frame->objectName;
ds << frame->geometry;
ds << frame->options;
ds << frame->currentTabIndex;
ds << frame->dockWidgets.size();
for(auto & dock : frame->dockWidgets)
{
ds << dock->uniqueName;
}
return ds;
}
inline QDataStream & operator>>(QDataStream & ds, LayoutSaver::Frame* frame)
{
int numDockWidgets;
frame->dockWidgets.clear();
frame->isNull = false;
ds >> frame->objectName;
ds >> frame->geometry;
ds >> frame->options;
ds >> frame->currentTabIndex;
ds >> numDockWidgets;
for(int i = 0; i < numDockWidgets; ++i)
{
QString name;
ds >> name;
auto dw = LayoutSaver::DockWidget::dockWidgetForName(name);
frame->dockWidgets.push_back(dw);
}
return ds;
}
inline QDataStream & operator<<(QDataStream & ds, LayoutSaver::Item* item)
{
ds << item->objectName;
ds << item->isPlaceholder;
ds << item->geometry;
ds << item->minSize;
ds << item->indexOfLeftAnchor;
ds << item->indexOfTopAnchor;
ds << item->indexOfRightAnchor;
ds << item->indexOfBottomAnchor;
const bool hasFrame = !item->frame.isNull;
ds << hasFrame;
if(hasFrame)
ds << &item->frame;
return ds;
}
inline QDataStream & operator>>(QDataStream & ds, LayoutSaver::Item* item)
{
ds >> item->objectName;
ds >> item->isPlaceholder;
ds >> item->geometry;
ds >> item->minSize;
ds >> item->indexOfLeftAnchor;
ds >> item->indexOfTopAnchor;
ds >> item->indexOfRightAnchor;
ds >> item->indexOfBottomAnchor;
bool hasFrame;
ds >> hasFrame;
if(hasFrame)
{
ds >> &item->frame;
item->frame.isNull = false;
}
else
{
item->frame.isNull = true;
}
return ds;
}
inline QDataStream & operator<<(QDataStream & ds, LayoutSaver::MultiSplitterLayout* l)
{
ds << QStringLiteral(MULTISPLITTER_LAYOUT_MAGIC_MARKER);
ds << l->size;
ds << l->minSize;
ds << l->items.size();
ds << l->anchors.size();
for(auto & item : l->items)
ds << &item;
for(auto & anchor : l->anchors)
ds << &anchor;
return ds;
}
inline QDataStream & operator>>(QDataStream & ds, LayoutSaver::MultiSplitterLayout* l)
{
int numItems;
int numAnchors;
QString marker;
ds >> marker;
if(marker != QLatin1String(MULTISPLITTER_LAYOUT_MAGIC_MARKER))
qWarning() << Q_FUNC_INFO << "Corrupt stream, invalid magic";
ds >> l->size;
ds >> l->minSize;
ds >> numItems;
ds >> numAnchors;
l->items.clear();
l->anchors.clear();
for(int i = 0 ; i < numItems; ++i)
{
LayoutSaver::Item item;
ds >> &item;
l->items.push_back(item);
}
for(int i = 0 ; i < numAnchors; ++i)
{
LayoutSaver::Anchor a;
ds >> &a;
l->anchors.push_back(a);
}
return ds;
}
inline QDataStream & operator<<(QDataStream & ds, LayoutSaver::LastPosition* lp)
{
ds << lp->placeholders.size();
for(auto & p : lp->placeholders)
{
ds << &p;
}
ds << lp->lastFloatingGeometry;
ds << lp->tabIndex;
ds << lp->wasFloating;
return ds;
}
inline QDataStream & operator>>(QDataStream & ds, LayoutSaver::LastPosition* lp)
{
int numPlaceholders;
ds >> numPlaceholders;
lp->placeholders.clear();
for(int i = 0 ; i < numPlaceholders; ++i)
{
LayoutSaver::Placeholder p;