Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72ee4a53df | ||
|
|
0b963d1540 | ||
|
|
9cd2584de5 | ||
|
|
3f40c997e5 | ||
|
|
6b93ae9c39 | ||
|
|
f5b3c0556d | ||
|
|
5b3841a038 | ||
|
|
9d00a278e6 | ||
|
|
b470dd5f99 | ||
|
|
7b4a19b943 | ||
|
|
8eceed9aa3 | ||
|
|
4188d69356 | ||
|
|
3fc7c195c3 | ||
|
|
f823b67a4a | ||
|
|
064cab405a | ||
|
|
75ad302d21 | ||
|
|
18a4f17fbf | ||
|
|
6266cd3290 | ||
|
|
8a401ebd68 | ||
|
|
805e97946e | ||
|
|
e878bb47ed | ||
|
|
dae852d9f9 | ||
|
|
8a014a6c2d | ||
|
|
9676eeb1bf | ||
|
|
412f13e1c4 | ||
|
|
11a30806f6 | ||
|
|
b9257bbe93 |
14
.astylerc
14
.astylerc
@@ -1,14 +0,0 @@
|
||||
--style=allman
|
||||
|
||||
--indent=force-tab=4
|
||||
|
||||
--align-pointer=type
|
||||
--align-reference=type
|
||||
|
||||
--pad-oper
|
||||
--pad-header
|
||||
--unpad-paren
|
||||
|
||||
--remove-comment-prefix
|
||||
|
||||
--mode=c
|
||||
10
.cproject
10
.cproject
@@ -24,6 +24,8 @@
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/QtAdvancedDockingSystem/demo}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/QtAdvancedDockingSystem/src}""/>
|
||||
<listOptionValue builtIn="false" value=""${QTDIR}/include""/>
|
||||
<listOptionValue builtIn="false" value=""${QTDIR}/include/QtCore""/>
|
||||
<listOptionValue builtIn="false" value=""${QTDIR}/include/QtWidgets""/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1249325593" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||
</tool>
|
||||
@@ -33,8 +35,10 @@
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/QtAdvancedDockingSystem/src}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/QtAdvancedDockingSystem/demo}""/>
|
||||
<listOptionValue builtIn="false" value=""${QTDIR}/include""/>
|
||||
<listOptionValue builtIn="false" value=""${QTDIR}/include/QtCore""/>
|
||||
<listOptionValue builtIn="false" value=""${QTDIR}/include/QtWidgets""/>
|
||||
</option>
|
||||
<option id="gnu.cpp.compiler.option.preprocessor.def.56223209" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols"/>
|
||||
<option id="gnu.cpp.compiler.option.preprocessor.def.56223209" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false"/>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1318830536" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.c.compiler.mingw.base.389117097" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.mingw.base">
|
||||
@@ -42,8 +46,10 @@
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/QtAdvancedDockingSystem/demo}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/QtAdvancedDockingSystem/src}""/>
|
||||
<listOptionValue builtIn="false" value=""${QTDIR}/include""/>
|
||||
<listOptionValue builtIn="false" value=""${QTDIR}/include/QtCore""/>
|
||||
<listOptionValue builtIn="false" value=""${QTDIR}/include/QtWidgets""/>
|
||||
</option>
|
||||
<option id="gnu.c.compiler.option.preprocessor.def.symbols.806805509" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols"/>
|
||||
<option id="gnu.c.compiler.option.preprocessor.def.symbols.806805509" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false"/>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1568363924" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.c.linker.mingw.base.1734874312" name="MinGW C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.mingw.base"/>
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
<project>
|
||||
<configuration id="cdt.managedbuild.toolchain.gnu.mingw.base.1119687795" name="Default">
|
||||
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
||||
<provider class="org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorMinGW" console="false" env-hash="-445604897520096165" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetectorMinGW" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings MinGW" parameter="${COMMAND} ${FLAGS} -E -P -v -dD -std=c++14 "${INPUTS}"" prefer-non-shared="true">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetectorMinGW" ref="shared-provider"/>
|
||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuildCommandParser" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser" keep-relative-paths="false" name="CDT GCC Build Output Parser" parameter="(g?cc)|([gc]\+\+)|(clang)" prefer-non-shared="true"/>
|
||||
|
||||
24
.travis.yml
24
.travis.yml
@@ -1,24 +0,0 @@
|
||||
language:
|
||||
- cpp
|
||||
|
||||
compiler:
|
||||
- g++
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-sdk-team
|
||||
packages:
|
||||
- qt5-qmake
|
||||
- qtbase5-dev
|
||||
- qtdeclarative5-dev
|
||||
- libqt5webkit5-dev
|
||||
- libsqlite3-dev
|
||||
|
||||
script:
|
||||
- qmake -qt=qt5 -v
|
||||
- qmake -qt=qt5 -r build.pro
|
||||
- make
|
||||
|
||||
#- sudo apt-get install -qq qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev
|
||||
#- sudo apt-get install -qq qt5-default qttools5-dev-tools
|
||||
Binary file not shown.
BIN
MainWindow.dat
BIN
MainWindow.dat
Binary file not shown.
@@ -36,6 +36,14 @@ a floating widget or from one dock area to another one.
|
||||
|
||||

|
||||
|
||||
### Perspectives for fast switching of the complete main window layout
|
||||
A perspective defines the set and layout of dock windows in the main
|
||||
window. You can save the current layout of the dockmanager into a named
|
||||
perspective to make your own custom perspective. Later you can simply
|
||||
select a perspective from the perspective list to quickly switch the complete
|
||||
main window layout.
|
||||
|
||||

|
||||
|
||||
## Tested Compatible Environments
|
||||
- Windows 10
|
||||
|
||||
327
demo/MainWindow.cpp
Normal file
327
demo/MainWindow.cpp
Normal file
@@ -0,0 +1,327 @@
|
||||
|
||||
/*******************************************************************************
|
||||
** Qt Advanced Docking System
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU Lesser General Public
|
||||
** License as published by the Free Software Foundation; either
|
||||
** version 2.1 of the License, or (at your option) any later version.
|
||||
**
|
||||
** This library 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
|
||||
** Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser General Public
|
||||
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
//============================================================================
|
||||
/// \file MainWindow.cpp
|
||||
/// \author Uwe Kindler
|
||||
/// \date 13.02.2018
|
||||
/// \brief Implementation of CMainWindow demo class
|
||||
//============================================================================
|
||||
|
||||
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include <MainWindow.h>
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QTime>
|
||||
#include <QLabel>
|
||||
#include <QTextEdit>
|
||||
#include <QCalendarWidget>
|
||||
#include <QFrame>
|
||||
#include <QTreeView>
|
||||
#include <QFileSystemModel>
|
||||
#include <QBoxLayout>
|
||||
#include <QSettings>
|
||||
#include <QDockWidget>
|
||||
#include <QDebug>
|
||||
#include <QResizeEvent>
|
||||
#include <QAction>
|
||||
#include <QWidgetAction>
|
||||
#include <QComboBox>
|
||||
#include <QInputDialog>
|
||||
|
||||
#include <QMap>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
#include "DockManager.h"
|
||||
#include "DockWidget.h"
|
||||
#include "DockAreaWidget.h"
|
||||
|
||||
|
||||
//============================================================================
|
||||
static ads::CDockWidget* createLongTextLabelDockWidget(QMenu* ViewMenu)
|
||||
{
|
||||
static int LabelCount = 0;
|
||||
QLabel* l = new QLabel();
|
||||
l->setWordWrap(true);
|
||||
l->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
||||
l->setText(QString("Label %1 %2 - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. "
|
||||
"Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque "
|
||||
"penatibus et magnis dis parturient montes, nascetur ridiculus mus. "
|
||||
"Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. "
|
||||
"Nulla consequat massa quis enim. Donec pede justo, fringilla vel, "
|
||||
"aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, "
|
||||
"imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede "
|
||||
"mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum "
|
||||
"semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, "
|
||||
"porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, "
|
||||
"dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla "
|
||||
"ut metus varius laoreet.")
|
||||
.arg(LabelCount)
|
||||
.arg(QTime::currentTime().toString("hh:mm:ss:zzz")));
|
||||
|
||||
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Label %1").arg(LabelCount++));
|
||||
DockWidget->setWidget(l);
|
||||
ViewMenu->addAction(DockWidget->toggleViewAction());
|
||||
return DockWidget;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
static ads::CDockWidget* createCalendarDockWidget(QMenu* ViewMenu)
|
||||
{
|
||||
static int CalendarCount = 0;
|
||||
QCalendarWidget* w = new QCalendarWidget();
|
||||
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Calendar %1").arg(CalendarCount++));
|
||||
DockWidget->setWidget(w);
|
||||
DockWidget->setToggleViewActionMode(ads::CDockWidget::ActionModeShow);
|
||||
ViewMenu->addAction(DockWidget->toggleViewAction());
|
||||
return DockWidget;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
static ads::CDockWidget* createFileSystemTreeDockWidget(QMenu* ViewMenu)
|
||||
{
|
||||
static int FileSystemCount = 0;
|
||||
QTreeView* w = new QTreeView();
|
||||
w->setFrameShape(QFrame::NoFrame);
|
||||
QFileSystemModel* m = new QFileSystemModel(w);
|
||||
m->setRootPath(QDir::currentPath());
|
||||
w->setModel(m);
|
||||
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Filesystem %1").arg(FileSystemCount++));
|
||||
DockWidget->setWidget(w);
|
||||
ViewMenu->addAction(DockWidget->toggleViewAction());
|
||||
return DockWidget;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
/**
|
||||
* Private data class pimpl
|
||||
*/
|
||||
struct MainWindowPrivate
|
||||
{
|
||||
CMainWindow* _this;
|
||||
Ui::MainWindow ui;
|
||||
QAction* SavePerspectiveAction = nullptr;
|
||||
QWidgetAction* PerspectiveListAction = nullptr;
|
||||
QComboBox* PerspectiveComboBox = nullptr;;
|
||||
ads::CDockManager* DockManager = nullptr;
|
||||
|
||||
MainWindowPrivate(CMainWindow* _public) : _this(_public) {}
|
||||
|
||||
/**
|
||||
* Creates the toolbar actions
|
||||
*/
|
||||
void createActions();
|
||||
|
||||
/**
|
||||
* Fill the dock manager with dock widgets
|
||||
*/
|
||||
void createContent();
|
||||
|
||||
/**
|
||||
* Saves the dock manager state and the main window geometry
|
||||
*/
|
||||
void saveState();
|
||||
|
||||
/**
|
||||
* Save the list of perspectives
|
||||
*/
|
||||
void savePerspectives();
|
||||
|
||||
/**
|
||||
* Restores the dock manager state
|
||||
*/
|
||||
void restoreState();
|
||||
|
||||
/**
|
||||
* Restore the perspective listo of the dock manager
|
||||
*/
|
||||
void restorePerspectives();
|
||||
};
|
||||
|
||||
|
||||
//============================================================================
|
||||
void MainWindowPrivate::createContent()
|
||||
{
|
||||
// Test container docking
|
||||
QMenu* ViewMenu = ui.menuView;
|
||||
auto DockWidget = createCalendarDockWidget(ViewMenu);
|
||||
DockWidget->setIcon(_this->style()->standardIcon(QStyle::SP_DialogOpenButton));
|
||||
DockWidget->setFeature(ads::CDockWidget::DockWidgetClosable, false);
|
||||
DockManager->addDockWidget(ads::LeftDockWidgetArea, DockWidget);
|
||||
DockManager->addDockWidget(ads::LeftDockWidgetArea, createLongTextLabelDockWidget(ViewMenu));
|
||||
DockManager->addDockWidget(ads::BottomDockWidgetArea, createFileSystemTreeDockWidget(ViewMenu));
|
||||
|
||||
auto FileSystemWidget = createFileSystemTreeDockWidget(ViewMenu);
|
||||
FileSystemWidget->setFeature(ads::CDockWidget::DockWidgetMovable, false);
|
||||
auto TopDockArea = DockManager->addDockWidget(ads::TopDockWidgetArea, FileSystemWidget);
|
||||
DockWidget = createCalendarDockWidget(ViewMenu);
|
||||
DockWidget->setFeature(ads::CDockWidget::DockWidgetClosable, false);
|
||||
DockManager->addDockWidget(ads::CenterDockWidgetArea, DockWidget, TopDockArea);
|
||||
|
||||
// Test dock area docking
|
||||
auto RighDockArea = DockManager->addDockWidget(ads::RightDockWidgetArea, createLongTextLabelDockWidget(ViewMenu), TopDockArea);
|
||||
DockManager->addDockWidget(ads::TopDockWidgetArea, createLongTextLabelDockWidget(ViewMenu), RighDockArea);
|
||||
auto BottomDockArea = DockManager->addDockWidget(ads::BottomDockWidgetArea, createLongTextLabelDockWidget(ViewMenu), RighDockArea);
|
||||
DockManager->addDockWidget(ads::RightDockWidgetArea, createLongTextLabelDockWidget(ViewMenu), RighDockArea);
|
||||
DockManager->addDockWidget(ads::CenterDockWidgetArea, createLongTextLabelDockWidget(ViewMenu), BottomDockArea);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void MainWindowPrivate::createActions()
|
||||
{
|
||||
ui.toolBar->addAction(ui.actionSaveState);
|
||||
ui.actionSaveState->setIcon(_this->style()->standardIcon(QStyle::SP_DialogSaveButton));
|
||||
ui.toolBar->addAction(ui.actionRestoreState);
|
||||
ui.actionRestoreState->setIcon(_this->style()->standardIcon(QStyle::SP_DialogOpenButton));
|
||||
|
||||
SavePerspectiveAction = new QAction("Save Perspective", _this);
|
||||
_this->connect(SavePerspectiveAction, SIGNAL(triggered()), SLOT(savePerspective()));
|
||||
PerspectiveListAction = new QWidgetAction(_this);
|
||||
PerspectiveComboBox = new QComboBox(_this);
|
||||
PerspectiveComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
PerspectiveComboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
PerspectiveListAction->setDefaultWidget(PerspectiveComboBox);
|
||||
ui.toolBar->addSeparator();
|
||||
ui.toolBar->addAction(PerspectiveListAction);
|
||||
ui.toolBar->addAction(SavePerspectiveAction);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void MainWindowPrivate::saveState()
|
||||
{
|
||||
QSettings Settings("Settings.ini", QSettings::IniFormat);
|
||||
Settings.setValue("mainWindow/Geometry", _this->saveGeometry());
|
||||
Settings.setValue("mainWindow/State", _this->saveState());
|
||||
Settings.setValue("mainWindow/DockingState", DockManager->saveState());
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void MainWindowPrivate::restoreState()
|
||||
{
|
||||
QSettings Settings("Settings.ini", QSettings::IniFormat);
|
||||
_this->restoreGeometry(Settings.value("mainWindow/Geometry").toByteArray());
|
||||
_this->restoreState(Settings.value("mainWindow/State").toByteArray());
|
||||
DockManager->restoreState(Settings.value("mainWindow/DockingState").toByteArray());
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============================================================================
|
||||
void MainWindowPrivate::savePerspectives()
|
||||
{
|
||||
QSettings Settings("Settings.ini", QSettings::IniFormat);
|
||||
DockManager->savePerspectives(Settings);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============================================================================
|
||||
void MainWindowPrivate::restorePerspectives()
|
||||
{
|
||||
QSettings Settings("Settings.ini", QSettings::IniFormat);
|
||||
DockManager->loadPerspectives(Settings);
|
||||
PerspectiveComboBox->clear();
|
||||
PerspectiveComboBox->addItems(DockManager->perspectiveNames());
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
CMainWindow::CMainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
d(new MainWindowPrivate(this))
|
||||
{
|
||||
d->ui.setupUi(this);
|
||||
d->createActions();
|
||||
|
||||
// Now create the dock manager and its content
|
||||
d->DockManager = new ads::CDockManager(this);
|
||||
connect(d->PerspectiveComboBox, SIGNAL(activated(const QString&)),
|
||||
d->DockManager, SLOT(openPerspective(const QString&)));
|
||||
|
||||
d->createContent();
|
||||
// Default window geometry
|
||||
resize(800, 600);
|
||||
|
||||
d->restoreState();
|
||||
d->restorePerspectives();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
CMainWindow::~CMainWindow()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CMainWindow::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
d->saveState();
|
||||
QMainWindow::closeEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CMainWindow::on_actionSaveState_triggered(bool)
|
||||
{
|
||||
qDebug() << "MainWindow::on_actionSaveState_triggered";
|
||||
d->saveState();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CMainWindow::on_actionRestoreState_triggered(bool)
|
||||
{
|
||||
qDebug() << "MainWindow::on_actionRestoreState_triggered";
|
||||
d->restoreState();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CMainWindow::savePerspective()
|
||||
{
|
||||
std::cout << "savePerspective" << std::endl;
|
||||
QString PerspectiveName = QInputDialog::getText(this, "Save Perspective", "Enter unique name:");
|
||||
if (PerspectiveName.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
d->DockManager->addPerspective(PerspectiveName);
|
||||
QSignalBlocker Blocker(d->PerspectiveComboBox);
|
||||
d->PerspectiveComboBox->clear();
|
||||
d->PerspectiveComboBox->addItems(d->DockManager->perspectiveNames());
|
||||
d->PerspectiveComboBox->setCurrentText(PerspectiveName);
|
||||
|
||||
d->savePerspectives();
|
||||
}
|
||||
|
||||
63
demo/MainWindow.h
Normal file
63
demo/MainWindow.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
/*******************************************************************************
|
||||
** Qt Advanced Docking System
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU Lesser General Public
|
||||
** License as published by the Free Software Foundation; either
|
||||
** version 2.1 of the License, or (at your option) any later version.
|
||||
**
|
||||
** This library 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
|
||||
** Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser General Public
|
||||
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
//============================================================================
|
||||
/// \file MainWindow.h
|
||||
/// \author Uwe Kindler
|
||||
/// \date 13.02.2018
|
||||
/// \brief Declaration of CMainWindow class
|
||||
//============================================================================
|
||||
|
||||
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include <QMainWindow>
|
||||
|
||||
|
||||
|
||||
struct MainWindowPrivate;
|
||||
|
||||
|
||||
/**
|
||||
* Simple main window for demo
|
||||
*/
|
||||
class CMainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
MainWindowPrivate* d;///< private data - pimpl
|
||||
friend struct MainWindowPrivate;
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent* event) override;
|
||||
|
||||
public:
|
||||
explicit CMainWindow(QWidget *parent = 0);
|
||||
virtual ~CMainWindow();
|
||||
|
||||
private slots:
|
||||
void on_actionSaveState_triggered(bool);
|
||||
void on_actionRestoreState_triggered(bool);
|
||||
void savePerspective();
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
@@ -4,24 +4,16 @@ ADS_OUT_ROOT = $${OUT_PWD}/..
|
||||
TARGET = AdvancedDockingSystemDemo
|
||||
DESTDIR = $${ADS_OUT_ROOT}/lib
|
||||
QT += core gui widgets
|
||||
CONFIG *= c++14
|
||||
|
||||
windows {
|
||||
# MinGW
|
||||
*-g++* {
|
||||
QMAKE_CXXFLAGS += -std=c++11
|
||||
}
|
||||
# MSVC
|
||||
*-msvc* {
|
||||
}
|
||||
}
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
mainwindow.cpp
|
||||
MainWindow.cpp
|
||||
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h
|
||||
MainWindow.h
|
||||
|
||||
FORMS += \
|
||||
mainwindow.ui
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <MainWindow.h>
|
||||
#include <QString>
|
||||
#include <QFile>
|
||||
#include <QApplication>
|
||||
@@ -5,7 +6,6 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
|
||||
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
||||
@@ -41,7 +41,7 @@ int main(int argc, char *argv[])
|
||||
qInstallMessageHandler(myMessageOutput);
|
||||
qDebug() << "Message handler test";
|
||||
|
||||
MainWindow mw;
|
||||
CMainWindow mw;
|
||||
mw.show();
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
|
||||
#include <QTime>
|
||||
#include <QLabel>
|
||||
#include <QTextEdit>
|
||||
#include <QCalendarWidget>
|
||||
#include <QFrame>
|
||||
#include <QTreeView>
|
||||
#include <QFileSystemModel>
|
||||
#include <QBoxLayout>
|
||||
#include <QSettings>
|
||||
#include <QDockWidget>
|
||||
#include <QDebug>
|
||||
|
||||
#include "DockManager.h"
|
||||
#include "DockWidget.h"
|
||||
#include "DockAreaWidget.h"
|
||||
|
||||
|
||||
|
||||
|
||||
static ads::CDockWidget* createLongTextLabelDockWidget(QMenu* ViewMenu)
|
||||
{
|
||||
static int LabelCount = 0;
|
||||
QLabel* l = new QLabel();
|
||||
l->setWordWrap(true);
|
||||
l->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
||||
l->setText(QString("Label %1 %2 - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. "
|
||||
"Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque "
|
||||
"penatibus et magnis dis parturient montes, nascetur ridiculus mus. "
|
||||
"Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. "
|
||||
"Nulla consequat massa quis enim. Donec pede justo, fringilla vel, "
|
||||
"aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, "
|
||||
"imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede "
|
||||
"mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum "
|
||||
"semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, "
|
||||
"porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, "
|
||||
"dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla "
|
||||
"ut metus varius laoreet.")
|
||||
.arg(LabelCount)
|
||||
.arg(QTime::currentTime().toString("hh:mm:ss:zzz")));
|
||||
|
||||
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Label %1").arg(LabelCount++));
|
||||
DockWidget->setWidget(l);
|
||||
DockWidget->setObjectName(DockWidget->windowTitle());
|
||||
ViewMenu->addAction(DockWidget->toggleViewAction());
|
||||
return DockWidget;
|
||||
}
|
||||
|
||||
|
||||
static ads::CDockWidget* createCalendarDockWidget(QMenu* ViewMenu)
|
||||
{
|
||||
static int CalendarCount = 0;
|
||||
QCalendarWidget* w = new QCalendarWidget();
|
||||
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Calendar %1").arg(CalendarCount++));
|
||||
DockWidget->setWidget(w);
|
||||
DockWidget->setObjectName(DockWidget->windowTitle());
|
||||
ViewMenu->addAction(DockWidget->toggleViewAction());
|
||||
return DockWidget;
|
||||
}
|
||||
|
||||
static ads::CDockWidget* createFileSystemTreeDockWidget(QMenu* ViewMenu)
|
||||
{
|
||||
static int FileSystemCount = 0;
|
||||
QTreeView* w = new QTreeView();
|
||||
w->setFrameShape(QFrame::NoFrame);
|
||||
QFileSystemModel* m = new QFileSystemModel(w);
|
||||
m->setRootPath(QDir::currentPath());
|
||||
w->setModel(m);
|
||||
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Filesystem %1").arg(FileSystemCount++));
|
||||
DockWidget->setWidget(w);
|
||||
DockWidget->setObjectName(DockWidget->windowTitle());
|
||||
ViewMenu->addAction(DockWidget->toggleViewAction());
|
||||
return DockWidget;
|
||||
}
|
||||
|
||||
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
m_DockManager = new ads::CDockManager(this);
|
||||
createContent();
|
||||
// Default window geometry
|
||||
resize(800, 600);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::createContent()
|
||||
{
|
||||
// Test container docking
|
||||
QMenu* ViewMenu = this->ui->menuView;
|
||||
auto DockWidget = createCalendarDockWidget(ViewMenu);
|
||||
DockWidget->setFeatures(DockWidget->features().setFlag(ads::CDockWidget::DockWidgetClosable, false));
|
||||
m_DockManager->addDockWidget(ads::LeftDockWidgetArea, DockWidget);
|
||||
m_DockManager->addDockWidget(ads::LeftDockWidgetArea, createLongTextLabelDockWidget(ViewMenu));
|
||||
m_DockManager->addDockWidget(ads::BottomDockWidgetArea, createFileSystemTreeDockWidget(ViewMenu));
|
||||
auto TopDockArea = m_DockManager->addDockWidget(ads::TopDockWidgetArea, createFileSystemTreeDockWidget(ViewMenu));
|
||||
DockWidget = createCalendarDockWidget(ViewMenu);
|
||||
DockWidget->setFeatures(DockWidget->features().setFlag(ads::CDockWidget::DockWidgetClosable, false));
|
||||
m_DockManager->addDockWidget(ads::CenterDockWidgetArea, DockWidget, TopDockArea);
|
||||
|
||||
// Test dock area docking
|
||||
auto RighDockArea = m_DockManager->addDockWidget(ads::RightDockWidgetArea, createLongTextLabelDockWidget(ViewMenu), TopDockArea);
|
||||
m_DockManager->addDockWidget(ads::TopDockWidgetArea, createLongTextLabelDockWidget(ViewMenu), RighDockArea);
|
||||
auto BottomDockArea = m_DockManager->addDockWidget(ads::BottomDockWidgetArea, createLongTextLabelDockWidget(ViewMenu), RighDockArea);
|
||||
m_DockManager->addDockWidget(ads::RightDockWidgetArea, createLongTextLabelDockWidget(ViewMenu), RighDockArea);
|
||||
m_DockManager->addDockWidget(ads::CenterDockWidgetArea, createLongTextLabelDockWidget(ViewMenu), BottomDockArea);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
/*QSettings Settings("Settings.ini", QSettings::IniFormat);
|
||||
Settings.setValue("mainWindow/Geometry", saveGeometry());
|
||||
Settings.setValue("mainWindow/DockingState", m_DockManager->saveState());*/
|
||||
QMainWindow::closeEvent(event);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_actionSaveState_triggered(bool)
|
||||
{
|
||||
qDebug() << "MainWindow::on_actionSaveState_triggered";
|
||||
QSettings Settings("Settings.ini", QSettings::IniFormat);
|
||||
Settings.setValue("mainWindow/Geometry", saveGeometry());
|
||||
Settings.setValue("mainWindow/DockingState", m_DockManager->saveState());
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_actionRestoreState_triggered(bool)
|
||||
{
|
||||
qDebug() << "MainWindow::on_actionRestoreState_triggered";
|
||||
QSettings Settings("Settings.ini", QSettings::IniFormat);
|
||||
restoreGeometry(Settings.value("mainWindow/Geometry").toByteArray());
|
||||
m_DockManager->restoreState(Settings.value("mainWindow/DockingState").toByteArray());
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include "DockManager.h"
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent* event) override;
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
virtual ~MainWindow();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
ads::CDockManager* m_DockManager;
|
||||
void createContent();
|
||||
|
||||
private slots:
|
||||
void on_actionSaveState_triggered(bool);
|
||||
void on_actionRestoreState_triggered(bool);
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
@@ -13,6 +13,9 @@
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<property name="dockOptions">
|
||||
<set>QMainWindow::AllowTabbedDocks</set>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget"/>
|
||||
<widget class="QStatusBar" name="statusBar"/>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
@@ -46,6 +49,17 @@
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuAbout"/>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="windowTitle">
|
||||
<string>toolBar</string>
|
||||
</property>
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
<action name="actionExit">
|
||||
<property name="text">
|
||||
<string>Exit</string>
|
||||
|
||||
BIN
perspectives.png
Normal file
BIN
perspectives.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
173
src/DockAreaTabBar.cpp
Normal file
173
src/DockAreaTabBar.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
//============================================================================
|
||||
/// \file DockAreaTabBar.cpp
|
||||
/// \author Uwe Kindler
|
||||
/// \date 24.08.2018
|
||||
/// \brief Implementation of CDockAreaTabBar class
|
||||
//============================================================================
|
||||
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include "DockAreaTabBar.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
#include <QScrollBar>
|
||||
#include <QDebug>
|
||||
|
||||
#include "FloatingDockContainer.h"
|
||||
#include "DockAreaWidget.h"
|
||||
#include "DockOverlay.h"
|
||||
#include "DockManager.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
/**
|
||||
* Private data class of CDockAreaTabBar class (pimpl)
|
||||
*/
|
||||
struct DockAreaTabBarPrivate
|
||||
{
|
||||
CDockAreaTabBar* _this;
|
||||
QPoint DragStartMousePos;
|
||||
CDockAreaWidget* DockArea;
|
||||
CFloatingDockContainer* FloatingWidget = nullptr;
|
||||
|
||||
/**
|
||||
* Private data constructor
|
||||
*/
|
||||
DockAreaTabBarPrivate(CDockAreaTabBar* _public);
|
||||
};
|
||||
// struct DockAreaTabBarPrivate
|
||||
|
||||
//============================================================================
|
||||
DockAreaTabBarPrivate::DockAreaTabBarPrivate(CDockAreaTabBar* _public) :
|
||||
_this(_public)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
CDockAreaTabBar::CDockAreaTabBar(CDockAreaWidget* parent) :
|
||||
QScrollArea(parent),
|
||||
d(new DockAreaTabBarPrivate(this))
|
||||
{
|
||||
d->DockArea = parent;
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
|
||||
setFrameStyle(QFrame::NoFrame);
|
||||
setWidgetResizable(true);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
CDockAreaTabBar::~CDockAreaTabBar()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockAreaTabBar::wheelEvent(QWheelEvent* Event)
|
||||
{
|
||||
Event->accept();
|
||||
const int direction = Event->angleDelta().y();
|
||||
if (direction < 0)
|
||||
{
|
||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + 20);
|
||||
}
|
||||
else
|
||||
{
|
||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - 20);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockAreaTabBar::mousePressEvent(QMouseEvent* ev)
|
||||
{
|
||||
if (ev->button() == Qt::LeftButton)
|
||||
{
|
||||
ev->accept();
|
||||
d->DragStartMousePos = ev->pos();
|
||||
return;
|
||||
}
|
||||
QScrollArea::mousePressEvent(ev);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockAreaTabBar::mouseReleaseEvent(QMouseEvent* ev)
|
||||
{
|
||||
if (ev->button() == Qt::LeftButton)
|
||||
{
|
||||
qDebug() << "CTabsScrollArea::mouseReleaseEvent";
|
||||
ev->accept();
|
||||
d->FloatingWidget = nullptr;
|
||||
d->DragStartMousePos = QPoint();
|
||||
return;
|
||||
}
|
||||
QScrollArea::mouseReleaseEvent(ev);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockAreaTabBar::mouseMoveEvent(QMouseEvent* ev)
|
||||
{
|
||||
QScrollArea::mouseMoveEvent(ev);
|
||||
if (ev->buttons() != Qt::LeftButton)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (d->FloatingWidget)
|
||||
{
|
||||
d->FloatingWidget->moveFloating();
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is the last dock area in a dock container it does not make
|
||||
// sense to move it to a new floating widget and leave this one
|
||||
// empty
|
||||
if (d->DockArea->dockContainer()->isFloating()
|
||||
&& d->DockArea->dockContainer()->visibleDockAreaCount() == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->geometry().contains(ev->pos()))
|
||||
{
|
||||
qDebug() << "CTabsScrollArea::startFloating";
|
||||
startFloating(d->DragStartMousePos);
|
||||
auto Overlay = d->DockArea->dockManager()->containerOverlay();
|
||||
Overlay->setAllowedAreas(OuterDockAreas);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockAreaTabBar::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
// If this is the last dock area in a dock container it does not make
|
||||
// sense to move it to a new floating widget and leave this one
|
||||
// empty
|
||||
if (d->DockArea->dockContainer()->isFloating() && d->DockArea->dockContainer()->dockAreaCount() == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
startFloating(event->pos());
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockAreaTabBar::startFloating(const QPoint& Pos)
|
||||
{
|
||||
QSize Size = d->DockArea->size();
|
||||
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(d->DockArea);
|
||||
FloatingWidget->startFloating(Pos, Size);
|
||||
d->FloatingWidget = FloatingWidget;
|
||||
}
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// EOF DockAreaTabBar.cpp
|
||||
74
src/DockAreaTabBar.h
Normal file
74
src/DockAreaTabBar.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifndef DockAreaTabBarH
|
||||
#define DockAreaTabBarH
|
||||
//============================================================================
|
||||
/// \file DockAreaTabBar.h
|
||||
/// \author Uwe Kindler
|
||||
/// \date 24.08.2018
|
||||
/// \brief Declaration of CDockAreaTabBar class
|
||||
//============================================================================
|
||||
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include <QScrollArea>
|
||||
|
||||
namespace ads
|
||||
{
|
||||
class CDockAreaWidget;
|
||||
struct DockAreaTabBarPrivate;
|
||||
|
||||
/**
|
||||
* Custom tabbar implementation for tab area that is shown on top of a
|
||||
* dock area widget.
|
||||
* The tabbar displays the tab widgets of the contained dock widgets.
|
||||
*/
|
||||
class CDockAreaTabBar : public QScrollArea
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
DockAreaTabBarPrivate* d; ///< private data (pimpl)
|
||||
friend class DockAreaTabBarPrivate;
|
||||
|
||||
protected:
|
||||
virtual void wheelEvent(QWheelEvent* Event) override;
|
||||
/**
|
||||
* Stores mouse position to detect dragging
|
||||
*/
|
||||
virtual void mousePressEvent(QMouseEvent* ev) override;
|
||||
|
||||
/**
|
||||
* Stores mouse position to detect dragging
|
||||
*/
|
||||
virtual void mouseReleaseEvent(QMouseEvent* ev) override;
|
||||
|
||||
/**
|
||||
* Starts floating the complete docking area including all dock widgets,
|
||||
* if it is not the last dock area in a floating widget
|
||||
*/
|
||||
virtual void mouseMoveEvent(QMouseEvent* ev) override;
|
||||
|
||||
/**
|
||||
* Double clicking the title bar also starts floating of the complete area
|
||||
*/
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
|
||||
/**
|
||||
* Starts floating
|
||||
*/
|
||||
void startFloating(const QPoint& Pos);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default Constructor
|
||||
*/
|
||||
CDockAreaTabBar(CDockAreaWidget* parent);
|
||||
|
||||
/**
|
||||
* Virtual Destructor
|
||||
*/
|
||||
virtual ~CDockAreaTabBar();
|
||||
}; // class CDockAreaTabBar
|
||||
} // namespace ads
|
||||
//-----------------------------------------------------------------------------
|
||||
#endif // DockAreaTabBarH
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include <DockWidgetTab.h>
|
||||
#include "DockAreaWidget.h"
|
||||
|
||||
#include <QStackedLayout>
|
||||
@@ -39,14 +40,15 @@
|
||||
#include <QDebug>
|
||||
#include <QMenu>
|
||||
#include <QSplitter>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
|
||||
#include "DockContainerWidget.h"
|
||||
#include "DockWidget.h"
|
||||
#include "DockWidgetTitleBar.h"
|
||||
#include "FloatingDockContainer.h"
|
||||
#include "DockManager.h"
|
||||
#include "DockOverlay.h"
|
||||
#include "DockAreaTabBar.h"
|
||||
|
||||
|
||||
namespace ads
|
||||
@@ -55,140 +57,6 @@ static const char* const INDEX_PROPERTY = "index";
|
||||
static const char* const ACTION_PROPERTY = "action";
|
||||
static const int APPEND = -1;
|
||||
|
||||
/**
|
||||
* Custom scroll bar implementation for dock area tab bar
|
||||
* This scroll area enables floating of a whole dock area including all
|
||||
* dock widgets
|
||||
*/
|
||||
class CTabsScrollArea : public QScrollArea
|
||||
{
|
||||
private:
|
||||
QPoint m_DragStartMousePos;
|
||||
CDockAreaWidget* m_DockArea;
|
||||
CFloatingDockContainer* m_FloatingWidget = nullptr;
|
||||
|
||||
public:
|
||||
CTabsScrollArea(CDockAreaWidget* parent)
|
||||
: QScrollArea(parent),
|
||||
m_DockArea(parent)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
|
||||
setFrameStyle(QFrame::NoFrame);
|
||||
setWidgetResizable(true);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void wheelEvent(QWheelEvent* Event) override
|
||||
{
|
||||
Event->accept();
|
||||
const int direction = Event->angleDelta().y();
|
||||
if (direction < 0)
|
||||
{
|
||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + 20);
|
||||
}
|
||||
else
|
||||
{
|
||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - 20);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores mouse position to detect dragging
|
||||
*/
|
||||
virtual void mousePressEvent(QMouseEvent* ev) override
|
||||
{
|
||||
if (ev->button() == Qt::LeftButton)
|
||||
{
|
||||
ev->accept();
|
||||
m_DragStartMousePos = ev->pos();
|
||||
return;
|
||||
}
|
||||
QScrollArea::mousePressEvent(ev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores mouse position to detect dragging
|
||||
*/
|
||||
virtual void mouseReleaseEvent(QMouseEvent* ev) override
|
||||
{
|
||||
if (ev->button() == Qt::LeftButton)
|
||||
{
|
||||
qDebug() << "CTabsScrollArea::mouseReleaseEvent";
|
||||
ev->accept();
|
||||
m_FloatingWidget = nullptr;
|
||||
m_DragStartMousePos = QPoint();
|
||||
return;
|
||||
}
|
||||
QScrollArea::mouseReleaseEvent(ev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts floating the complete docking area including all dock widgets,
|
||||
* if it is not the last dock area in a floating widget
|
||||
*/
|
||||
virtual void mouseMoveEvent(QMouseEvent* ev) override
|
||||
{
|
||||
QScrollArea::mouseMoveEvent(ev);
|
||||
if (ev->buttons() != Qt::LeftButton)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_FloatingWidget)
|
||||
{
|
||||
m_FloatingWidget->moveFloating();
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is the last dock area in a dock container it does not make
|
||||
// sense to move it to a new floating widget and leave this one
|
||||
// empty
|
||||
if (m_DockArea->dockContainer()->isFloating()
|
||||
&& m_DockArea->dockContainer()->visibleDockAreaCount() == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->geometry().contains(ev->pos()))
|
||||
{
|
||||
qDebug() << "CTabsScrollArea::startFloating";
|
||||
startFloating(m_DragStartMousePos);
|
||||
auto Overlay = m_DockArea->dockManager()->containerOverlay();
|
||||
Overlay->setAllowedAreas(OuterDockAreas);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Double clicking the title bar also starts floating of the complete area
|
||||
*/
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override
|
||||
{
|
||||
// If this is the last dock area in a dock container it does not make
|
||||
// sense to move it to a new floating widget and leave this one
|
||||
// empty
|
||||
if (m_DockArea->dockContainer()->isFloating() && m_DockArea->dockContainer()->dockAreaCount() == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
startFloating(event->pos());
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts floating
|
||||
*/
|
||||
void startFloating(const QPoint& Pos)
|
||||
{
|
||||
QSize Size = m_DockArea->size();
|
||||
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(m_DockArea);
|
||||
FloatingWidget->startFloating(Pos, Size);
|
||||
m_FloatingWidget = FloatingWidget;
|
||||
}
|
||||
}; // class CTabsScrollArea
|
||||
|
||||
|
||||
/**
|
||||
* Private data class of CDockAreaWidget class (pimpl)
|
||||
@@ -200,7 +68,7 @@ struct DockAreaWidgetPrivate
|
||||
QFrame* TitleBar;
|
||||
QBoxLayout* TopLayout;
|
||||
QStackedLayout* ContentsLayout;
|
||||
QScrollArea* TabsScrollArea;
|
||||
CDockAreaTabBar* TabBar;
|
||||
QWidget* TabsContainerWidget;
|
||||
QBoxLayout* TabsLayout;
|
||||
QPushButton* TabsMenuButton;
|
||||
@@ -229,7 +97,7 @@ struct DockAreaWidgetPrivate
|
||||
/**
|
||||
* Convenience function to ease title widget access by index
|
||||
*/
|
||||
CDockWidgetTitleBar* titleWidgetAt(int index)
|
||||
CDockWidgetTab* titleWidgetAt(int index)
|
||||
{
|
||||
return dockWidgetAt(index)->titleBar();
|
||||
}
|
||||
@@ -292,12 +160,12 @@ void DockAreaWidgetPrivate::createTabBar()
|
||||
TitleBar->setLayout(TopLayout);
|
||||
Layout->addWidget(TitleBar);
|
||||
|
||||
TabsScrollArea = new CTabsScrollArea(_this);
|
||||
TopLayout->addWidget(TabsScrollArea, 1);
|
||||
TabBar = new CDockAreaTabBar(_this);
|
||||
TopLayout->addWidget(TabBar, 1);
|
||||
|
||||
TabsContainerWidget = new QWidget();
|
||||
TabsContainerWidget->setObjectName("tabsContainerWidget");
|
||||
TabsScrollArea->setWidget(TabsContainerWidget);
|
||||
TabBar->setWidget(TabsContainerWidget);
|
||||
|
||||
TabsLayout = new QBoxLayout(QBoxLayout::LeftToRight);
|
||||
TabsLayout->setContentsMargins(0, 0, 0, 0);
|
||||
@@ -312,6 +180,7 @@ void DockAreaWidgetPrivate::createTabBar()
|
||||
TabsMenuButton->setMaximumWidth(TabsMenuButton->iconSize().width());
|
||||
TabsMenuButton->setMenu(new QMenu(TabsMenuButton));
|
||||
TopLayout->addWidget(TabsMenuButton, 0);
|
||||
TabsMenuButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
_this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)),
|
||||
SLOT(onTabsMenuActionTriggered(QAction*)));
|
||||
|
||||
@@ -356,12 +225,12 @@ void DockAreaWidgetPrivate::addTabsMenuEntry(CDockWidget* DockWidget,
|
||||
QAction* Action;
|
||||
if (Index >= 0 && Index < menu->actions().count())
|
||||
{
|
||||
Action = new QAction(DockWidget->windowTitle());
|
||||
Action = new QAction(DockWidget->icon(), DockWidget->windowTitle());
|
||||
menu->insertAction(menu->actions().at(Index), Action);
|
||||
}
|
||||
else
|
||||
{
|
||||
Action = menu->addAction(DockWidget->windowTitle());
|
||||
Action = menu->addAction(DockWidget->icon(), DockWidget->windowTitle());
|
||||
}
|
||||
QVariant vAction = QVariant::fromValue(Action);
|
||||
DockWidget->setProperty(ACTION_PROPERTY, vAction);
|
||||
@@ -488,7 +357,7 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
|
||||
//============================================================================
|
||||
void CDockAreaWidget::onDockWidgetTitleClicked()
|
||||
{
|
||||
CDockWidgetTitleBar* TitleWidget = qobject_cast<CDockWidgetTitleBar*>(sender());
|
||||
CDockWidgetTab* TitleWidget = qobject_cast<CDockWidgetTab*>(sender());
|
||||
if (!TitleWidget)
|
||||
{
|
||||
return;
|
||||
@@ -532,7 +401,9 @@ void CDockAreaWidget::setCurrentIndex(int index)
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO << "Invalid index" << index;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
emit currentChanging(index);
|
||||
|
||||
// Set active TAB and update all other tabs to be inactive
|
||||
for (int i = 0; i < d->TabsLayout->count(); ++i)
|
||||
@@ -543,7 +414,7 @@ void CDockAreaWidget::setCurrentIndex(int index)
|
||||
continue;
|
||||
}
|
||||
|
||||
auto TitleWidget = dynamic_cast<CDockWidgetTitleBar*>(item->widget());
|
||||
auto TitleWidget = dynamic_cast<CDockWidgetTab*>(item->widget());
|
||||
if (!TitleWidget)
|
||||
{
|
||||
continue;
|
||||
@@ -553,7 +424,7 @@ void CDockAreaWidget::setCurrentIndex(int index)
|
||||
{
|
||||
TitleWidget->show();
|
||||
TitleWidget->setActiveTab(true);
|
||||
d->TabsScrollArea->ensureWidgetVisible(TitleWidget);
|
||||
d->TabBar->ensureWidgetVisible(TitleWidget);
|
||||
auto Features = TitleWidget->dockWidget()->features();
|
||||
d->CloseButton->setVisible(Features.testFlag(CDockWidget::DockWidgetClosable));
|
||||
}
|
||||
@@ -706,15 +577,18 @@ void CDockAreaWidget::updateDockArea()
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockAreaWidget::saveState(QDataStream& stream) const
|
||||
void CDockAreaWidget::saveState(QXmlStreamWriter& s) const
|
||||
{
|
||||
stream << d->ContentsLayout->count() << d->ContentsLayout->currentIndex();
|
||||
s.writeStartElement("DockAreaWidget");
|
||||
s.writeAttribute("Tabs", QString::number(d->ContentsLayout->count()));
|
||||
s.writeAttribute("CurrentIndex", QString::number(d->ContentsLayout->currentIndex()));
|
||||
qDebug() << "CDockAreaWidget::saveState TabCount: " << d->ContentsLayout->count()
|
||||
<< " CurrentIndex: " << d->ContentsLayout->currentIndex();
|
||||
for (int i = 0; i < d->ContentsLayout->count(); ++i)
|
||||
{
|
||||
dockWidget(i)->saveState(stream);
|
||||
dockWidget(i)->saveState(s);
|
||||
}
|
||||
s.writeEndElement();
|
||||
}
|
||||
|
||||
} // namespace ads
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
/*******************************************************************************
|
||||
** Qt Advanced Docking System
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU Lesser General Public
|
||||
** License as published by the Free Software Foundation; either
|
||||
** version 2.1 of the License, or (at your option) any later version.
|
||||
**
|
||||
**
|
||||
** This library 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
|
||||
** Lesser General Public License for more details.
|
||||
**
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser General Public
|
||||
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
@@ -32,31 +32,72 @@
|
||||
//============================================================================
|
||||
#include <QFrame>
|
||||
|
||||
#include "ads_globals.h"
|
||||
|
||||
class QXmlStreamWriter;
|
||||
|
||||
namespace ads
|
||||
{
|
||||
struct DockAreaWidgetPrivate;
|
||||
class CDockManager;
|
||||
class CDockContainerWidget;
|
||||
struct DockContainerWidgetPrivate;
|
||||
class CDockWidget;
|
||||
|
||||
|
||||
/**
|
||||
* DockAreaWidget manages multiple instances of DckWidgets.
|
||||
* DockAreaWidget manages multiple instances of DockWidgets.
|
||||
* It displays a title tab, which is clickable and will switch to
|
||||
* the contents associated to the title when clicked.
|
||||
*/
|
||||
class CDockAreaWidget : public QFrame
|
||||
class ADS_EXPORT CDockAreaWidget : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
DockAreaWidgetPrivate* d; ///< private data (pimpl)
|
||||
friend class DockAreaWidgetPrivate;
|
||||
friend struct DockAreaWidgetPrivate;
|
||||
friend class CDockContainerWidget;
|
||||
friend class DockContainerWidgetPrivate;
|
||||
friend class CDockWidgetTab;
|
||||
|
||||
private slots:
|
||||
void onDockWidgetTitleClicked();
|
||||
void onTabsMenuActionTriggered(QAction* Action);
|
||||
void onCloseButtonClicked();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Inserts a dock widget into dock area.
|
||||
* All dockwidgets in the dock area tabified in a stacked layout with tabs.
|
||||
* The index indicates the index of the new dockwidget in the tabbar and
|
||||
* in the stacked layout. If the Activate parameter is true, the new
|
||||
* DockWidget will be the active one in the stacked layout
|
||||
*/
|
||||
void insertDockWidget(int index, CDockWidget* DockWidget, bool Activate = true);
|
||||
|
||||
/**
|
||||
* Add a new dock widget to dock area.
|
||||
* All dockwidgets in the dock area tabified in a stacked layout with tabs
|
||||
*/
|
||||
void addDockWidget(CDockWidget* DockWidget);
|
||||
|
||||
/**
|
||||
* Removes the given dock widget from the dock area
|
||||
*/
|
||||
void removeDockWidget(CDockWidget* DockWidget);
|
||||
|
||||
/**
|
||||
* Returns the index of contents of the title widget that is located at
|
||||
* mouse position pos
|
||||
*/
|
||||
int indexOfContentByTitlePos(const QPoint& pos, QWidget* exclude = nullptr) const;
|
||||
|
||||
/**
|
||||
* Reorder the index position of DockWidget at fromIndx to toIndex.
|
||||
*/
|
||||
void reorderDockWidget(int fromIndex, int toIndex);
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default Constructor
|
||||
@@ -79,26 +120,6 @@ public:
|
||||
*/
|
||||
CDockContainerWidget* dockContainer() const;
|
||||
|
||||
/**
|
||||
* Inserts a dock widget into dock area.
|
||||
* All dockwidgets in the dock area tabified in a stacked layout with tabs.
|
||||
* The index indicates the index of the new dockwidget in the tabbar and
|
||||
* in the stacked layout. If the Activate parameter is true, the new
|
||||
* DockWidget will be the active one in the stacked layout
|
||||
*/
|
||||
void insertDockWidget(int index, CDockWidget* DockWidget, bool Activate = true);
|
||||
|
||||
/**
|
||||
* Add a new dock widget to dock area.
|
||||
* All dockwidgets in the dock area tabified in a stacked layout with tabs
|
||||
*/
|
||||
void addDockWidget(CDockWidget* DockWidget);
|
||||
|
||||
/**
|
||||
* Removes the given dock widget from the dock area
|
||||
*/
|
||||
void removeDockWidget(CDockWidget* DockWidget);
|
||||
|
||||
/**
|
||||
* Returns the rectangle of the title area
|
||||
*/
|
||||
@@ -114,12 +135,6 @@ public:
|
||||
*/
|
||||
int tabIndex(CDockWidget* DockWidget);
|
||||
|
||||
/**
|
||||
* Returns the index of contents of the title widget that is located at
|
||||
* mouse position pos
|
||||
*/
|
||||
int indexOfContentByTitlePos(const QPoint& pos, QWidget* exclude = nullptr) const;
|
||||
|
||||
/**
|
||||
* Returns a list of all dock widgets in this dock area.
|
||||
* This list contains open and closed dock widgets.
|
||||
@@ -141,11 +156,6 @@ public:
|
||||
*/
|
||||
CDockWidget* dockWidget(int Index) const;
|
||||
|
||||
/**
|
||||
* Reorder the index position of DockWidget at fromIndx to toIndex.
|
||||
*/
|
||||
void reorderDockWidget(int fromIndex, int toIndex);
|
||||
|
||||
/**
|
||||
* Returns the index of the current active dock widget
|
||||
*/
|
||||
@@ -157,14 +167,14 @@ public:
|
||||
CDockWidget* currentDockWidget() const;
|
||||
|
||||
/**
|
||||
* Shows the tab with tghe given dock widget
|
||||
* Shows the tab with the given dock widget
|
||||
*/
|
||||
void setCurrentDockWidget(CDockWidget* DockWidget);
|
||||
|
||||
/**
|
||||
* Saves the state into the given stream
|
||||
*/
|
||||
void saveState(QDataStream& Stream) const;
|
||||
void saveState(QXmlStreamWriter& Stream) const;
|
||||
|
||||
public slots:
|
||||
/**
|
||||
@@ -183,6 +193,13 @@ signals:
|
||||
*/
|
||||
void tabBarClicked(int index);
|
||||
|
||||
/**
|
||||
* This signal is emitted when the tab bar's current tab is about to be changed. The new
|
||||
* current has the given index, or -1 if there isn't a new one.
|
||||
* @param index
|
||||
*/
|
||||
void currentChanging(int index);
|
||||
|
||||
/**
|
||||
* This signal is emitted when the tab bar's current tab changes. The new
|
||||
* current has the given index, or -1 if there isn't a new one
|
||||
|
||||
@@ -30,12 +30,15 @@
|
||||
//============================================================================
|
||||
#include "DockContainerWidget.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QEvent>
|
||||
#include <QList>
|
||||
#include <QGridLayout>
|
||||
#include <QPointer>
|
||||
#include <QVariant>
|
||||
#include <QDebug>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
#include "DockManager.h"
|
||||
#include "DockAreaWidget.h"
|
||||
@@ -120,7 +123,7 @@ struct DockContainerWidgetPrivate
|
||||
/**
|
||||
* Save state of child nodes
|
||||
*/
|
||||
void saveChildNodesState(QDataStream& Stream, QWidget* Widget);
|
||||
void saveChildNodesState(QXmlStreamWriter& Stream, QWidget* Widget);
|
||||
|
||||
/**
|
||||
* Restore state of child nodes.
|
||||
@@ -130,21 +133,21 @@ struct DockContainerWidgetPrivate
|
||||
* \param[in] Testing If Testing is true, only the stream data is
|
||||
* parsed without modifiying anything.
|
||||
*/
|
||||
bool restoreChildNodes(QDataStream& Stream, QWidget*& CreatedWidget,
|
||||
bool restoreChildNodes(QXmlStreamReader& Stream, QWidget*& CreatedWidget,
|
||||
bool Testing);
|
||||
|
||||
/**
|
||||
* Restores a splitter.
|
||||
* \see restoreChildNodes() for details
|
||||
*/
|
||||
bool restoreSplitter(QDataStream& Stream, QWidget*& CreatedWidget,
|
||||
bool restoreSplitter(QXmlStreamReader& Stream, QWidget*& CreatedWidget,
|
||||
bool Testing);
|
||||
|
||||
/**
|
||||
* Restores a dock area.
|
||||
* \see restoreChildNodes() for details
|
||||
*/
|
||||
bool restoreDockArea(QDataStream& Stream, QWidget*& CreatedWidget,
|
||||
bool restoreDockArea(QXmlStreamReader& Stream, QWidget*& CreatedWidget,
|
||||
bool Testing);
|
||||
|
||||
/**
|
||||
@@ -169,6 +172,7 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float
|
||||
auto InsertParam = internal::dockAreaInsertParameters(area);
|
||||
auto NewDockAreas = FloatingWidget->dockContainer()->findChildren<CDockAreaWidget*>(
|
||||
QString(), Qt::FindChildrenRecursively);
|
||||
CDockWidget* DockWidget = FloatingWidget->dockContainer()->findChild<CDockWidget*>();
|
||||
QSplitter* Splitter = RootSplitter;
|
||||
|
||||
if (DockAreas.count() <= 1)
|
||||
@@ -205,6 +209,10 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float
|
||||
RootSplitter = Splitter;
|
||||
addDockAreasToList(NewDockAreas);
|
||||
FloatingWidget->deleteLater();
|
||||
if (DockWidget)
|
||||
{
|
||||
DockWidget->toggleView(true);
|
||||
}
|
||||
_this->dumpLayout();
|
||||
}
|
||||
|
||||
@@ -309,39 +317,56 @@ void DockContainerWidgetPrivate::addDockAreasToList(const QList<CDockAreaWidget*
|
||||
|
||||
|
||||
//============================================================================
|
||||
void DockContainerWidgetPrivate::saveChildNodesState(QDataStream& stream, QWidget* Widget)
|
||||
void DockContainerWidgetPrivate::saveChildNodesState(QXmlStreamWriter& s, QWidget* Widget)
|
||||
{
|
||||
QSplitter* Splitter = dynamic_cast<QSplitter*>(Widget);
|
||||
if (Splitter)
|
||||
{
|
||||
stream << internal::SplitterMarker << Splitter->orientation() << Splitter->count();
|
||||
s.writeStartElement("Splitter");
|
||||
s.writeAttribute("Orientation", QString::number(Splitter->orientation()));
|
||||
s.writeAttribute("Count", QString::number(Splitter->count()));
|
||||
qDebug() << "NodeSplitter orient: " << Splitter->orientation()
|
||||
<< " WidgetCont: " << Splitter->count();
|
||||
for (int i = 0; i < Splitter->count(); ++i)
|
||||
{
|
||||
saveChildNodesState(stream, Splitter->widget(i));
|
||||
}
|
||||
stream << Splitter->sizes();
|
||||
for (int i = 0; i < Splitter->count(); ++i)
|
||||
{
|
||||
saveChildNodesState(s, Splitter->widget(i));
|
||||
}
|
||||
|
||||
s.writeStartElement("Sizes");
|
||||
for (auto Size : Splitter->sizes())
|
||||
{
|
||||
s.writeCharacters(QString::number(Size) + " ");
|
||||
}
|
||||
s.writeEndElement();
|
||||
s.writeEndElement();
|
||||
}
|
||||
else
|
||||
{
|
||||
stream << internal::DockAreaMarker;
|
||||
CDockAreaWidget* DockArea = dynamic_cast<CDockAreaWidget*>(Widget);
|
||||
if (DockArea)
|
||||
{
|
||||
DockArea->saveState(stream);
|
||||
DockArea->saveState(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool DockContainerWidgetPrivate::restoreSplitter(QDataStream& stream,
|
||||
bool DockContainerWidgetPrivate::restoreSplitter(QXmlStreamReader& s,
|
||||
QWidget*& CreatedWidget, bool Testing)
|
||||
{
|
||||
int Orientation;
|
||||
int WidgetCount;
|
||||
stream >> Orientation >> WidgetCount;
|
||||
bool Ok;
|
||||
int Orientation = s.attributes().value("Orientation").toInt(&Ok);
|
||||
if (!Ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int WidgetCount = s.attributes().value("Count").toInt(&Ok);
|
||||
if (!Ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
qDebug() << "Restore NodeSplitter Orientation: " << Orientation <<
|
||||
" WidgetCount: " << WidgetCount;
|
||||
QSplitter* Splitter = nullptr;
|
||||
@@ -350,15 +375,42 @@ bool DockContainerWidgetPrivate::restoreSplitter(QDataStream& stream,
|
||||
Splitter = internal::newSplitter((Qt::Orientation)Orientation);
|
||||
}
|
||||
bool Visible = false;
|
||||
for (int i = 0; i < WidgetCount; ++i)
|
||||
QList<int> Sizes;
|
||||
while (s.readNextStartElement())
|
||||
{
|
||||
QWidget* ChildNode;
|
||||
if (!restoreChildNodes(stream, ChildNode, Testing))
|
||||
QWidget* ChildNode = nullptr;
|
||||
bool Result = true;
|
||||
if (s.name() == "Splitter")
|
||||
{
|
||||
Result = restoreSplitter(s, ChildNode, Testing);
|
||||
}
|
||||
else if (s.name() == "DockAreaWidget")
|
||||
{
|
||||
Result = restoreDockArea(s, ChildNode, Testing);
|
||||
}
|
||||
else if (s.name() == "Sizes")
|
||||
{
|
||||
QString sSizes = s.readElementText().trimmed();
|
||||
qDebug() << "Sizes: " << sSizes;
|
||||
QTextStream TextStream(&sSizes);
|
||||
while (!TextStream.atEnd())
|
||||
{
|
||||
int value;
|
||||
TextStream >> value;
|
||||
Sizes.append(value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s.skipCurrentElement();
|
||||
}
|
||||
|
||||
if (!Result)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Testing)
|
||||
if (Testing || !ChildNode)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -369,8 +421,11 @@ bool DockContainerWidgetPrivate::restoreSplitter(QDataStream& stream,
|
||||
Visible |= ChildNode->isVisibleTo(Splitter);
|
||||
}
|
||||
|
||||
QList<int> Sizes;
|
||||
stream >> Sizes;
|
||||
if (Sizes.count() != WidgetCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Testing)
|
||||
{
|
||||
if (!Splitter->count())
|
||||
@@ -389,17 +444,27 @@ bool DockContainerWidgetPrivate::restoreSplitter(QDataStream& stream,
|
||||
{
|
||||
CreatedWidget = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool DockContainerWidgetPrivate::restoreDockArea(QDataStream& stream,
|
||||
bool DockContainerWidgetPrivate::restoreDockArea(QXmlStreamReader& s,
|
||||
QWidget*& CreatedWidget, bool Testing)
|
||||
{
|
||||
int Tabs;
|
||||
int CurrentIndex;
|
||||
stream >> Tabs >> CurrentIndex;
|
||||
bool Ok;
|
||||
int Tabs = s.attributes().value("Tabs").toInt(&Ok);
|
||||
if (!Ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int CurrentIndex = s.attributes().value("CurrentIndex").toInt(&Ok);
|
||||
if (!Ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
qDebug() << "Restore NodeDockArea Tabs: " << Tabs << " CurrentIndex: "
|
||||
<< CurrentIndex;
|
||||
|
||||
@@ -409,21 +474,27 @@ bool DockContainerWidgetPrivate::restoreDockArea(QDataStream& stream,
|
||||
DockArea = new CDockAreaWidget(DockManager, _this);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Tabs; ++i)
|
||||
while (s.readNextStartElement())
|
||||
{
|
||||
int Marker;
|
||||
stream >> Marker;
|
||||
if (Marker != internal::DockWidgetMarker)
|
||||
if (s.name() != "DockWidget")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto ObjectName = s.attributes().value("ObjectName");
|
||||
if (ObjectName.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QString ObjectName;
|
||||
bool Closed;
|
||||
stream >> ObjectName >> Closed;
|
||||
qDebug() << "Restore DockWidget " << ObjectName << " Closed: " << Closed;
|
||||
bool Closed = s.attributes().value("Closed").toInt(&Ok);
|
||||
if (!Ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CDockWidget* DockWidget = DockManager->findDockWidget(ObjectName);
|
||||
s.skipCurrentElement();
|
||||
CDockWidget* DockWidget = DockManager->findDockWidget(ObjectName.toString());
|
||||
if (!DockWidget || Testing)
|
||||
{
|
||||
continue;
|
||||
@@ -451,31 +522,39 @@ bool DockContainerWidgetPrivate::restoreDockArea(QDataStream& stream,
|
||||
else
|
||||
{
|
||||
DockArea->setProperty("currentIndex", CurrentIndex);
|
||||
DockAreas.append(DockArea);
|
||||
}
|
||||
|
||||
CreatedWidget = DockArea;
|
||||
DockAreas.append(DockArea);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool DockContainerWidgetPrivate::restoreChildNodes(QDataStream& stream,
|
||||
bool DockContainerWidgetPrivate::restoreChildNodes(QXmlStreamReader& s,
|
||||
QWidget*& CreatedWidget, bool Testing)
|
||||
{
|
||||
int Marker;
|
||||
stream >> Marker;
|
||||
if (internal::SplitterMarker == Marker)
|
||||
bool Result = true;
|
||||
while (s.readNextStartElement())
|
||||
{
|
||||
return restoreSplitter(stream, CreatedWidget, Testing);
|
||||
}
|
||||
else if (internal::DockAreaMarker == Marker)
|
||||
{
|
||||
return restoreDockArea(stream, CreatedWidget, Testing);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
if (s.name() == "Splitter")
|
||||
{
|
||||
Result = restoreSplitter(s, CreatedWidget, Testing);
|
||||
qDebug() << "Splitter";
|
||||
}
|
||||
else if (s.name() == "DockAreaWidget")
|
||||
{
|
||||
Result = restoreDockArea(s, CreatedWidget, Testing);
|
||||
qDebug() << "DockAreaWidget";
|
||||
}
|
||||
else
|
||||
{
|
||||
s.skipCurrentElement();
|
||||
qDebug() << "Unknown element";
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
@@ -541,8 +620,11 @@ void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget)
|
||||
buf.fill(' ', level * 4);
|
||||
if (Splitter)
|
||||
{
|
||||
qDebug("%sSplitter %s", (const char*)buf, (Splitter->orientation() == Qt::Vertical)
|
||||
? "-" : "|");
|
||||
qDebug("%sSplitter %s v: %s c: %s",
|
||||
(const char*)buf,
|
||||
(Splitter->orientation() == Qt::Vertical) ? "-" : "|",
|
||||
Splitter->isVisibleTo(Splitter->parentWidget()) ? "1" : "0",
|
||||
QString::number(Splitter->count()).toStdString().c_str());
|
||||
for (int i = 0; i < Splitter->count(); ++i)
|
||||
{
|
||||
dumpRecursive(level + 1, Splitter->widget(i));
|
||||
@@ -706,22 +788,59 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
|
||||
{
|
||||
qDebug() << "CDockContainerWidget::removeDockArea";
|
||||
d->DockAreas.removeAll(area);
|
||||
QSplitter* Splitter = internal::findParent<QSplitter*>(area);
|
||||
CDockSplitter* Splitter = internal::findParent<CDockSplitter*>(area);
|
||||
|
||||
// Remove are from parent splitter and hide splitter if it has no visible
|
||||
// content
|
||||
area->setParent(0);
|
||||
if (Splitter == d->RootSplitter || Splitter->count() != 1)
|
||||
Splitter->setVisible(Splitter->hasVisibleContent());
|
||||
|
||||
// If splitter has more than 1 widgets, we are finished and can leave
|
||||
if (Splitter->count() > 1)
|
||||
{
|
||||
emit dockAreasRemoved();
|
||||
return;
|
||||
goto emitAndExit;
|
||||
}
|
||||
|
||||
// If this is the RootSplitter we need to remove empty splitters to
|
||||
// avoid too many empty splitters
|
||||
if (Splitter == d->RootSplitter)
|
||||
{
|
||||
qDebug() << "Removed from RootSplitter";
|
||||
// If splitter is empty, we are finished
|
||||
if (!Splitter->count())
|
||||
{
|
||||
Splitter->hide();
|
||||
goto emitAndExit;
|
||||
}
|
||||
|
||||
QWidget* widget = Splitter->widget(0);
|
||||
QSplitter* ChildSplitter = dynamic_cast<QSplitter*>(widget);
|
||||
// If the one and only content widget of the splitter is not a splitter
|
||||
// then we are finished
|
||||
if (!ChildSplitter)
|
||||
{
|
||||
goto emitAndExit;
|
||||
}
|
||||
|
||||
// We replace the superfluous RootSplitter with the ChildSplitter
|
||||
ChildSplitter->setParent(0);
|
||||
QLayoutItem* li = d->Layout->replaceWidget(Splitter, ChildSplitter);
|
||||
d->RootSplitter = ChildSplitter;
|
||||
delete li;
|
||||
qDebug() << "RootSplitter replaced by child splitter";
|
||||
}
|
||||
else if (Splitter->count() == 1)
|
||||
{
|
||||
qDebug() << "Replacing splitter with content";
|
||||
QWidget* widget = Splitter->widget(0);
|
||||
widget->setParent(this);
|
||||
QSplitter* ParentSplitter = internal::findParent<QSplitter*>(Splitter);
|
||||
internal::replaceSplitterWidget(ParentSplitter, Splitter, widget);
|
||||
}
|
||||
|
||||
// It the splitter contains only one single widget, then we do not need
|
||||
// it anymore and can replace it with its content
|
||||
qDebug() << "Replacing splitter with content";
|
||||
QWidget* widget = Splitter->widget(0);
|
||||
widget->setParent(this);
|
||||
QSplitter* ParentSplitter = internal::findParent<QSplitter*>(Splitter);
|
||||
internal::replaceSplitterWidget(ParentSplitter, Splitter, widget);
|
||||
delete Splitter;
|
||||
|
||||
emitAndExit:
|
||||
dumpLayout();
|
||||
emit dockAreasRemoved();
|
||||
}
|
||||
@@ -732,7 +851,7 @@ CDockAreaWidget* CDockContainerWidget::dockAreaAt(const QPoint& GlobalPos) const
|
||||
{
|
||||
for (const auto& DockArea : d->DockAreas)
|
||||
{
|
||||
if (DockArea->rect().contains(DockArea->mapFromGlobal(GlobalPos)))
|
||||
if (DockArea->isVisible() && DockArea->rect().contains(DockArea->mapFromGlobal(GlobalPos)))
|
||||
{
|
||||
return DockArea;
|
||||
}
|
||||
@@ -785,11 +904,18 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
|
||||
qDebug() << "CDockContainerWidget::dropFloatingWidget";
|
||||
CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
|
||||
auto dropArea = InvalidDockWidgetArea;
|
||||
auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
|
||||
if (DockArea)
|
||||
{
|
||||
auto dropOverlay = d->DockManager->dockAreaOverlay();
|
||||
dropOverlay->setAllowedAreas(AllDockAreas);
|
||||
dropArea = dropOverlay->showOverlay(DockArea);
|
||||
if (ContainerDropArea != InvalidDockWidgetArea &&
|
||||
ContainerDropArea != dropArea)
|
||||
{
|
||||
dropArea = InvalidDockWidgetArea;
|
||||
}
|
||||
|
||||
if (dropArea != InvalidDockWidgetArea)
|
||||
{
|
||||
qDebug() << "Dock Area Drop Content: " << dropArea;
|
||||
@@ -800,7 +926,7 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
|
||||
// mouse is over container
|
||||
if (InvalidDockWidgetArea == dropArea)
|
||||
{
|
||||
dropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
|
||||
dropArea = ContainerDropArea;
|
||||
qDebug() << "Container Drop Content: " << dropArea;
|
||||
if (dropArea != InvalidDockWidgetArea)
|
||||
{
|
||||
@@ -827,37 +953,31 @@ QList<CDockAreaWidget*> CDockContainerWidget::openedDockAreas() const
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockContainerWidget::saveState(QDataStream& stream) const
|
||||
void CDockContainerWidget::saveState(QXmlStreamWriter& s) const
|
||||
{
|
||||
qDebug() << "CDockContainerWidget::saveState isFloating "
|
||||
<< isFloating();
|
||||
stream << internal::ContainerMarker;
|
||||
stream << isFloating();
|
||||
|
||||
s.writeStartElement("DockContainerWidget");
|
||||
s.writeAttribute("Floating", QString::number(isFloating() ? 1 : 0));
|
||||
if (isFloating())
|
||||
{
|
||||
CFloatingDockContainer* FloatingWidget = internal::findParent<CFloatingDockContainer*>(this);
|
||||
stream << FloatingWidget->saveGeometry();
|
||||
QByteArray Geometry = FloatingWidget->saveGeometry();
|
||||
s.writeTextElement("Geometry", Geometry.toHex(' '));
|
||||
}
|
||||
|
||||
d->saveChildNodesState(stream, d->RootSplitter);
|
||||
d->saveChildNodesState(s, d->RootSplitter);
|
||||
s.writeEndElement();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool CDockContainerWidget::restoreState(QDataStream& stream, bool Testing)
|
||||
bool CDockContainerWidget::restoreState(QXmlStreamReader& s, bool Testing)
|
||||
{
|
||||
bool IsFloating;
|
||||
int Marker;
|
||||
stream >> Marker;
|
||||
if (Marker != internal::ContainerMarker)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
stream >> IsFloating;
|
||||
bool IsFloating = s.attributes().value("Floating").toInt();
|
||||
qDebug() << "Restore CDockContainerWidget Floating" << IsFloating;
|
||||
|
||||
QWidget* NewRootSplitter;
|
||||
QWidget*NewRootSplitter {};
|
||||
if (!Testing)
|
||||
{
|
||||
d->DockAreas.clear();
|
||||
@@ -866,17 +986,26 @@ bool CDockContainerWidget::restoreState(QDataStream& stream, bool Testing)
|
||||
if (IsFloating)
|
||||
{
|
||||
qDebug() << "Restore floating widget";
|
||||
QByteArray Geometry;
|
||||
stream >> Geometry;
|
||||
if (!s.readNextStartElement() || s.name() != "Geometry")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray GeometryString = s.readElementText(QXmlStreamReader::ErrorOnUnexpectedElement).toLocal8Bit();
|
||||
QByteArray Geometry = QByteArray::fromHex(GeometryString);
|
||||
if (Geometry.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Testing)
|
||||
{
|
||||
CFloatingDockContainer* FloatingWidget = internal::findParent<CFloatingDockContainer*>(this);
|
||||
FloatingWidget->restoreGeometry(Geometry);
|
||||
FloatingWidget->show();
|
||||
}
|
||||
}
|
||||
|
||||
if (!d->restoreChildNodes(stream, NewRootSplitter, Testing))
|
||||
if (!d->restoreChildNodes(s, NewRootSplitter, Testing))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -912,7 +1041,9 @@ QSplitter* CDockContainerWidget::rootSplitter() const
|
||||
//============================================================================
|
||||
void CDockContainerWidget::dumpLayout()
|
||||
{
|
||||
qDebug("\n\nDumping layout --------------------------");
|
||||
d->dumpRecursive(0, d->RootSplitter);
|
||||
qDebug("--------------------------\n\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
/*******************************************************************************
|
||||
** Qt Advanced Docking System
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU Lesser General Public
|
||||
** License as published by the Free Software Foundation; either
|
||||
** version 2.1 of the License, or (at your option) any later version.
|
||||
**
|
||||
**
|
||||
** This library 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
|
||||
** Lesser General Public License for more details.
|
||||
**
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser General Public
|
||||
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
@@ -34,24 +34,35 @@
|
||||
|
||||
#include "ads_globals.h"
|
||||
|
||||
|
||||
class QXmlStreamWriter;
|
||||
class QXmlStreamReader;
|
||||
|
||||
namespace ads
|
||||
{
|
||||
struct DockContainerWidgetPrivate;
|
||||
class CDockAreaWidget;
|
||||
class CDockWidget;
|
||||
class CDockManager;
|
||||
struct DockManagerPrivate;
|
||||
class CFloatingDockContainer;
|
||||
struct FloatingDockContainerPrivate;
|
||||
|
||||
/**
|
||||
* Container that manages a number of dock areas with single dock widgets
|
||||
* or tabyfied dock widgets in each area
|
||||
*/
|
||||
class CDockContainerWidget : public QFrame
|
||||
class ADS_EXPORT CDockContainerWidget : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
DockContainerWidgetPrivate* d; ///< private data (pimpl)
|
||||
friend class DockContainerWidgetPrivate;
|
||||
friend struct DockContainerWidgetPrivate;
|
||||
friend class CDockManager;
|
||||
friend struct DockManagerPrivate;
|
||||
friend class CDockAreaWidget;
|
||||
friend class CFloatingDockContainer;
|
||||
friend struct FloatingDockContainerPrivate;
|
||||
|
||||
protected:
|
||||
/**
|
||||
@@ -64,6 +75,34 @@ protected:
|
||||
*/
|
||||
QSplitter* rootSplitter() const;
|
||||
|
||||
/**
|
||||
* Drop floating widget into the container
|
||||
*/
|
||||
void dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos);
|
||||
|
||||
/**
|
||||
* Adds the given dock area to this container widget
|
||||
*/
|
||||
void addDockArea(CDockAreaWidget* DockAreaWidget, DockWidgetArea area = CenterDockWidgetArea);
|
||||
|
||||
/**
|
||||
* Removes the given dock area from this container
|
||||
*/
|
||||
void removeDockArea(CDockAreaWidget* area);
|
||||
|
||||
/**
|
||||
* Saves the state into the given stream
|
||||
*/
|
||||
void saveState(QXmlStreamWriter& Stream) const;
|
||||
|
||||
/**
|
||||
* Restores the state from given stream.
|
||||
* If Testing is true, the function only parses the data from the given
|
||||
* stream but does not restore anything. You can use this check for
|
||||
* faulty files before you start restoring the state
|
||||
*/
|
||||
bool restoreState(QXmlStreamReader& Stream, bool Testing);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default Constructor
|
||||
@@ -75,11 +114,6 @@ public:
|
||||
*/
|
||||
virtual ~CDockContainerWidget();
|
||||
|
||||
/**
|
||||
* Drop floating widget into the container
|
||||
*/
|
||||
void dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos);
|
||||
|
||||
/**
|
||||
* Adds dockwidget into the given area.
|
||||
* If DockAreaWidget is not null, then the area parameter indicates the area
|
||||
@@ -90,16 +124,6 @@ public:
|
||||
CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
|
||||
CDockAreaWidget* DockAreaWidget = nullptr);
|
||||
|
||||
/**
|
||||
* Adds the given dock area to this container widget
|
||||
*/
|
||||
void addDockArea(CDockAreaWidget* DockAreaWidget, DockWidgetArea area = CenterDockWidgetArea);
|
||||
|
||||
/**
|
||||
* Removes the given dock area from this container
|
||||
*/
|
||||
void removeDockArea(CDockAreaWidget* area);
|
||||
|
||||
/**
|
||||
* Returns the current zOrderIndex
|
||||
*/
|
||||
@@ -144,19 +168,6 @@ public:
|
||||
*/
|
||||
bool isFloating() const;
|
||||
|
||||
/**
|
||||
* Saves the state into the given stream
|
||||
*/
|
||||
void saveState(QDataStream& Stream) const;
|
||||
|
||||
/**
|
||||
* Restores the state from given stream.
|
||||
* If Testing is true, the function only parses the data from the given
|
||||
* stream but does not restore anything. You can use this check for
|
||||
* faulty files before you start restoring the state
|
||||
*/
|
||||
bool restoreState(QDataStream& Stream, bool Testing);
|
||||
|
||||
/**
|
||||
* Dumps the layout for debugging purposes
|
||||
*/
|
||||
|
||||
@@ -28,8 +28,11 @@
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include <DockWidgetTab.h>
|
||||
#include "DockManager.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
@@ -38,18 +41,19 @@
|
||||
#include <QFile>
|
||||
#include <QApplication>
|
||||
#include <QAction>
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QSettings>
|
||||
|
||||
#include "FloatingDockContainer.h"
|
||||
#include "DockOverlay.h"
|
||||
#include "DockWidget.h"
|
||||
#include "ads_globals.h"
|
||||
#include "DockStateSerialization.h"
|
||||
#include "DockWidgetTitleBar.h"
|
||||
#include "DockAreaWidget.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
/**
|
||||
* Private data class of CDockManager class (pimpl)
|
||||
*/
|
||||
@@ -61,6 +65,7 @@ struct DockManagerPrivate
|
||||
CDockOverlay* ContainerOverlay;
|
||||
CDockOverlay* DockAreaOverlay;
|
||||
QMap<QString, CDockWidget*> DockWidgetsMap;
|
||||
QMap<QString, QByteArray> Perspectives;
|
||||
|
||||
/**
|
||||
* Private data constructor
|
||||
@@ -76,12 +81,12 @@ struct DockManagerPrivate
|
||||
/**
|
||||
* Restores the state
|
||||
*/
|
||||
bool restoreState(const QByteArray &state, int version);
|
||||
bool restoreState(const QByteArray &state, int version, bool Testing = internal::Restore);
|
||||
|
||||
/**
|
||||
* Restores the container with the given index
|
||||
*/
|
||||
bool restoreContainer(int Index, QDataStream& stream, bool Testing);
|
||||
bool restoreContainer(int Index, QXmlStreamReader& stream, bool Testing);
|
||||
|
||||
/**
|
||||
* Loads the stylesheet
|
||||
@@ -112,45 +117,13 @@ void DockManagerPrivate::loadStylesheet()
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool DockManagerPrivate::checkFormat(const QByteArray &state, int version)
|
||||
bool DockManagerPrivate::restoreContainer(int Index, QXmlStreamReader& stream, bool Testing)
|
||||
{
|
||||
if (state.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
QByteArray sd = state;
|
||||
QDataStream stream(&sd, QIODevice::ReadOnly);
|
||||
if (Testing)
|
||||
{
|
||||
Index = 0;
|
||||
}
|
||||
|
||||
int marker;
|
||||
int v;
|
||||
stream >> marker;
|
||||
stream >> v;
|
||||
|
||||
if (stream.status() != QDataStream::Ok || marker != internal::VersionMarker || v != version)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int Result = true;
|
||||
int ContainerCount;
|
||||
stream >> ContainerCount;
|
||||
int i;
|
||||
for (i = 0; i < ContainerCount; ++i)
|
||||
{
|
||||
if (!Containers[0]->restoreState(stream, internal::RestoreTesting))
|
||||
{
|
||||
Result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool DockManagerPrivate::restoreContainer(int Index, QDataStream& stream, bool Testing)
|
||||
{
|
||||
if (Index >= Containers.count())
|
||||
{
|
||||
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this);
|
||||
@@ -165,45 +138,60 @@ bool DockManagerPrivate::restoreContainer(int Index, QDataStream& stream, bool T
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool DockManagerPrivate::restoreState(const QByteArray &state, int version)
|
||||
bool DockManagerPrivate::checkFormat(const QByteArray &state, int version)
|
||||
{
|
||||
return restoreState(state, version, internal::RestoreTesting);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool DockManagerPrivate::restoreState(const QByteArray &state, int version,
|
||||
bool Testing)
|
||||
{
|
||||
if (state.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
QByteArray sd = state;
|
||||
QDataStream stream(&sd, QIODevice::ReadOnly);
|
||||
|
||||
int marker;
|
||||
int v;
|
||||
stream >> marker;
|
||||
stream >> v;
|
||||
|
||||
if (stream.status() != QDataStream::Ok || marker != internal::VersionMarker || v != version)
|
||||
QXmlStreamReader s(state);
|
||||
s.readNextStartElement();
|
||||
if (s.name() != "QtAdvancedDockingSystem")
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
qDebug() << s.attributes().value("Version");
|
||||
bool ok;
|
||||
int v = s.attributes().value("Version").toInt(&ok);
|
||||
if (!ok || v != version)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int Result = true;
|
||||
int ContainerCount;
|
||||
stream >> ContainerCount;
|
||||
qDebug() << "ContainerCount " << ContainerCount;
|
||||
int i;
|
||||
for (i = 0; i < ContainerCount; ++i)
|
||||
bool Result = true;
|
||||
int DockContainers = s.attributes().value("DockContainers").toInt();
|
||||
qDebug() << DockContainers;
|
||||
int DockContainerCount = 0;
|
||||
while (s.readNextStartElement())
|
||||
{
|
||||
Result = restoreContainer(i, stream, internal::Restore);
|
||||
if (!Result)
|
||||
if (s.name() == "DockContainerWidget")
|
||||
{
|
||||
break;
|
||||
Result = restoreContainer(DockContainerCount, s, Testing);
|
||||
if (!Result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
DockContainerCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete remaining empty floating widgets
|
||||
int FloatingWidgetIndex = i - 1;
|
||||
int DeleteCount = FloatingWidgets.count() - FloatingWidgetIndex;
|
||||
for (int i = 0; i < DeleteCount; ++i)
|
||||
if (!Testing)
|
||||
{
|
||||
FloatingWidgets[FloatingWidgetIndex + i]->deleteLater();
|
||||
// Delete remaining empty floating widgets
|
||||
int FloatingWidgetIndex = DockContainerCount - 1;
|
||||
int DeleteCount = FloatingWidgets.count() - FloatingWidgetIndex;
|
||||
for (int i = 0; i < DeleteCount; ++i)
|
||||
{
|
||||
FloatingWidgets[FloatingWidgetIndex + i]->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
@@ -309,17 +297,22 @@ unsigned int CDockManager::zOrderIndex() const
|
||||
//============================================================================
|
||||
QByteArray CDockManager::saveState(int version) const
|
||||
{
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << internal::VersionMarker;
|
||||
stream << version;
|
||||
QByteArray xmldata;
|
||||
QXmlStreamWriter s(&xmldata);
|
||||
s.setAutoFormatting(true);
|
||||
s.writeStartDocument();
|
||||
s.writeStartElement("QtAdvancedDockingSystem");
|
||||
s.writeAttribute("Version", QString::number(version));
|
||||
s.writeAttribute("DockContainers", QString::number(d->Containers.count()));
|
||||
for (auto Container : d->Containers)
|
||||
{
|
||||
Container->saveState(s);
|
||||
}
|
||||
|
||||
stream << d->Containers.count();
|
||||
for (auto Container : d->Containers)
|
||||
{
|
||||
Container->saveState(stream);
|
||||
}
|
||||
return data;
|
||||
s.writeEndElement();
|
||||
s.writeEndDocument();
|
||||
|
||||
return xmldata;
|
||||
}
|
||||
|
||||
|
||||
@@ -345,7 +338,7 @@ bool CDockManager::restoreState(const QByteArray &state, int version)
|
||||
|
||||
// All dock widgets, that have not been processed in the restore state
|
||||
// function are invisible to the user now and have no assigned dock area
|
||||
// The do not belong to any dock container, until the user toggles the
|
||||
// They do not belong to any dock container, until the user toggles the
|
||||
// toggle view action the next time
|
||||
for (auto DockWidget : d->DockWidgetsMap)
|
||||
{
|
||||
@@ -353,9 +346,9 @@ bool CDockManager::restoreState(const QByteArray &state, int version)
|
||||
{
|
||||
DockWidget->flagAsUnassigned();
|
||||
}
|
||||
else if (!DockWidget->property("closed").toBool())
|
||||
else
|
||||
{
|
||||
DockWidget->toggleView(true);
|
||||
DockWidget->toggleView(!DockWidget->property("closed").toBool());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,6 +368,7 @@ bool CDockManager::restoreState(const QByteArray &state, int version)
|
||||
}
|
||||
}
|
||||
|
||||
emit stateChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -393,6 +387,78 @@ CDockWidget* CDockManager::findDockWidget(const QString& ObjectName)
|
||||
{
|
||||
return d->DockWidgetsMap.value(ObjectName, nullptr);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockManager::addPerspective(const QString& UniquePrespectiveName)
|
||||
{
|
||||
d->Perspectives.insert(UniquePrespectiveName, saveState());
|
||||
emit perspectiveListChanged();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QStringList CDockManager::perspectiveNames() const
|
||||
{
|
||||
return d->Perspectives.keys();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockManager::openPerspective(const QString& PerspectiveName)
|
||||
{
|
||||
const auto Iterator = d->Perspectives.find(PerspectiveName);
|
||||
if (d->Perspectives.end() == Iterator)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
restoreState(Iterator.value());
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockManager::savePerspectives(QSettings& Settings) const
|
||||
{
|
||||
Settings.beginWriteArray("Perspectives", d->Perspectives.size());
|
||||
int i = 0;
|
||||
for (auto it = d->Perspectives.constBegin(); it != d->Perspectives.constEnd(); ++it)
|
||||
{
|
||||
Settings.setArrayIndex(i);
|
||||
Settings.setValue("Name", it.key());
|
||||
Settings.setValue("State", it.value());
|
||||
++i;
|
||||
}
|
||||
Settings.endArray();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockManager::loadPerspectives(QSettings& Settings)
|
||||
{
|
||||
d->Perspectives.clear();
|
||||
int Size = Settings.beginReadArray("Perspectives");
|
||||
if (!Size)
|
||||
{
|
||||
Settings.endArray();
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < Size; ++i)
|
||||
{
|
||||
Settings.setArrayIndex(i);
|
||||
QString Name = Settings.value("Name").toString();
|
||||
QByteArray Data = Settings.value("State").toByteArray();
|
||||
if (Name.isEmpty() || Data.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
d->Perspectives.insert(Name, Data);
|
||||
}
|
||||
|
||||
Settings.endArray();
|
||||
}
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
/*******************************************************************************
|
||||
** Qt Advanced Docking System
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU Lesser General Public
|
||||
** License as published by the Free Software Foundation; either
|
||||
** version 2.1 of the License, or (at your option) any later version.
|
||||
**
|
||||
**
|
||||
** This library 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
|
||||
** Lesser General Public License for more details.
|
||||
**
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser General Public
|
||||
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
@@ -32,39 +32,40 @@
|
||||
//============================================================================
|
||||
#include "DockContainerWidget.h"
|
||||
|
||||
#include "ads_globals.h"
|
||||
|
||||
class QSettings;
|
||||
|
||||
namespace ads
|
||||
{
|
||||
struct DockManagerPrivate;
|
||||
class CFloatingDockContainer;
|
||||
struct FloatingDockContainerPrivate;
|
||||
class CDockContainerWidget;
|
||||
class CDockOverlay;
|
||||
class CDockAreaTabBar;
|
||||
class CDockWidgetTab;
|
||||
struct DockWidgetTabPrivate;
|
||||
struct DockAreaWidgetPrivate;
|
||||
|
||||
/**
|
||||
* The central dock manager that maintains the complete docking system
|
||||
**/
|
||||
class CDockManager : public CDockContainerWidget
|
||||
class ADS_EXPORT CDockManager : public CDockContainerWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
DockManagerPrivate* d; ///< private data (pimpl)
|
||||
friend class DockManagerPrivate;
|
||||
friend struct DockManagerPrivate;
|
||||
friend class CFloatingDockContainer;
|
||||
friend struct FloatingDockContainerPrivate;
|
||||
friend class CDockContainerWidget;
|
||||
friend class CDockAreaTabBar;
|
||||
friend class CDockWidgetTab;
|
||||
friend struct DockAreaWidgetPrivate;
|
||||
friend struct DockWidgetTabPrivate;
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default Constructor.
|
||||
* If the given parent is a QMainWindow, the dock manager sets itself as the
|
||||
* central widget
|
||||
*/
|
||||
CDockManager(QWidget* parent = 0);
|
||||
|
||||
/**
|
||||
* Virtual Destructor
|
||||
*/
|
||||
virtual ~CDockManager();
|
||||
|
||||
/**
|
||||
* Registers the given floating widget in the internal list of
|
||||
* floating widgets
|
||||
@@ -98,11 +99,30 @@ public:
|
||||
*/
|
||||
CDockOverlay* dockAreaOverlay() const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default Constructor.
|
||||
* If the given parent is a QMainWindow, the dock manager sets itself as the
|
||||
* central widget
|
||||
*/
|
||||
CDockManager(QWidget* parent = 0);
|
||||
|
||||
/**
|
||||
* Virtual Destructor
|
||||
*/
|
||||
virtual ~CDockManager();
|
||||
|
||||
/**
|
||||
* Adds dockwidget into the given area.
|
||||
* If DockAreaWidget is not null, then the area parameter indicates the area
|
||||
* into the DockAreaWidget. If DockAreaWidget is null, the Dockwidget will
|
||||
* be dropped into the container.
|
||||
* be dropped into the container. If you would like to add a dock widget
|
||||
* tabified, then you need to add it to an existing dock area object
|
||||
* into the CenterDockWidgetArea. The following code shows this:
|
||||
* \code
|
||||
* DockManager->addDockWidget(ads::CenterDockWidgetArea, NewDockWidget,
|
||||
* ExisitingDockArea);
|
||||
* \endcode
|
||||
* \return Returns the dock area widget that contains the new DockWidget
|
||||
*/
|
||||
CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
|
||||
@@ -134,6 +154,7 @@ public:
|
||||
|
||||
/**
|
||||
* Saves the current state of the dockmanger and all its dock widgets
|
||||
* into the returned QByteArray
|
||||
*/
|
||||
QByteArray saveState(int version = 0) const;
|
||||
|
||||
@@ -145,6 +166,50 @@ public:
|
||||
* returns true.
|
||||
*/
|
||||
bool restoreState(const QByteArray &state, int version = 0);
|
||||
|
||||
/**
|
||||
* Saves the current perspective to the internal list of perspectives.
|
||||
* A perspective is the current state of the dock manager assigned
|
||||
* with a certain name. This makes it possible for the user,
|
||||
* to switch between different perspectives quickly.
|
||||
* If a perspective with the given name already exists, then
|
||||
* it will be overwritten with the new state.
|
||||
*/
|
||||
void addPerspective(const QString& UniquePrespectiveName);
|
||||
|
||||
/**
|
||||
* Returns the names of all available perspectives
|
||||
*/
|
||||
QStringList perspectiveNames() const;
|
||||
|
||||
/**
|
||||
* Saves the perspectives to the given settings file.
|
||||
*/
|
||||
void savePerspectives(QSettings& Settings) const;
|
||||
|
||||
/**
|
||||
* Loads the perspectives from the given settings file
|
||||
*/
|
||||
void loadPerspectives(QSettings& Settings);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Opens the perspective with the given name.
|
||||
*/
|
||||
void openPerspective(const QString& PerspectiveName);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* This signal is emitted if the list of perspectives changed
|
||||
*/
|
||||
void perspectiveListChanged();
|
||||
|
||||
/**
|
||||
* This signal is emitted if the state changed in restoreState.
|
||||
* The signal is emitted if the restoreState() function is called or
|
||||
* if the openPerspective() function is called
|
||||
*/
|
||||
void stateChanged();
|
||||
}; // class DockManager
|
||||
} // namespace ads
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -33,160 +33,14 @@
|
||||
#include <QLabel>
|
||||
#include <QtGlobal>
|
||||
#include <QDebug>
|
||||
#include <QMap>
|
||||
|
||||
#include "DockAreaWidget.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace ads
|
||||
{
|
||||
//============================================================================
|
||||
static QPixmap createDropIndicatorPixmap(const QPalette& pal, const QSizeF& size, DockWidgetArea DockWidgetArea,
|
||||
CDockOverlay::eMode Mode)
|
||||
{
|
||||
QColor borderColor = pal.color(QPalette::Active, QPalette::Highlight);
|
||||
QColor backgroundColor = pal.color(QPalette::Active, QPalette::Base);
|
||||
|
||||
QPixmap pm(size.width(), size.height());
|
||||
pm.fill(QColor(0, 0, 0, 0));
|
||||
|
||||
QPainter p(&pm);
|
||||
QPen pen = p.pen();
|
||||
QRectF ShadowRect(pm.rect());
|
||||
QRectF baseRect;
|
||||
baseRect.setSize(ShadowRect.size() * 0.7);
|
||||
baseRect.moveCenter(ShadowRect.center());
|
||||
|
||||
// Fill
|
||||
p.fillRect(ShadowRect, QColor(0, 0, 0, 64));
|
||||
|
||||
// Drop area rect.
|
||||
p.save();
|
||||
QRectF areaRect;
|
||||
QLineF areaLine;
|
||||
QRectF nonAreaRect;
|
||||
switch (DockWidgetArea)
|
||||
{
|
||||
case TopDockWidgetArea:
|
||||
areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
|
||||
nonAreaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
|
||||
areaLine = QLineF(areaRect.bottomLeft(), areaRect.bottomRight());
|
||||
break;
|
||||
case RightDockWidgetArea:
|
||||
areaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
|
||||
nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
|
||||
areaLine = QLineF(areaRect.topLeft(), areaRect.bottomLeft());
|
||||
break;
|
||||
case BottomDockWidgetArea:
|
||||
areaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
|
||||
nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
|
||||
areaLine = QLineF(areaRect.topLeft(), areaRect.topRight());
|
||||
break;
|
||||
case LeftDockWidgetArea:
|
||||
areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
|
||||
nonAreaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
|
||||
areaLine = QLineF(areaRect.topRight(), areaRect.bottomRight());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QSizeF baseSize = baseRect.size();
|
||||
if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea)
|
||||
{
|
||||
baseRect = areaRect;
|
||||
}
|
||||
|
||||
p.fillRect(baseRect, backgroundColor);
|
||||
if (areaRect.isValid())
|
||||
{
|
||||
pen = p.pen();
|
||||
pen.setColor(borderColor);
|
||||
QColor Color = borderColor;
|
||||
Color.setAlpha(64);
|
||||
p.setBrush(Color);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawRect(areaRect);
|
||||
|
||||
pen = p.pen();
|
||||
pen.setColor(borderColor);
|
||||
pen.setStyle(Qt::DashLine);
|
||||
p.setPen(pen);
|
||||
p.drawLine(areaLine);
|
||||
}
|
||||
p.restore();
|
||||
|
||||
p.save();
|
||||
// Draw outer border
|
||||
pen = p.pen();
|
||||
pen.setColor(borderColor);
|
||||
pen.setWidth(1);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.setPen(pen);
|
||||
p.drawRect(baseRect);
|
||||
|
||||
// draw window title bar
|
||||
p.setBrush(borderColor);
|
||||
QRectF FrameRect(baseRect.topLeft(), QSizeF(baseRect.width(), baseSize.height() / 10));
|
||||
p.drawRect(FrameRect);
|
||||
p.restore();
|
||||
|
||||
// Draw arrow for outer container drop indicators
|
||||
if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea)
|
||||
{
|
||||
QRectF ArrowRect;
|
||||
ArrowRect.setSize(baseSize);
|
||||
ArrowRect.setWidth(ArrowRect.width() / 4.6);
|
||||
ArrowRect.setHeight(ArrowRect.height() / 2);
|
||||
ArrowRect.moveCenter(QPointF(0, 0));
|
||||
QPolygonF Arrow;
|
||||
Arrow << ArrowRect.topLeft()
|
||||
<< QPointF( ArrowRect.right(), ArrowRect.center().y())
|
||||
<< ArrowRect.bottomLeft();
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(backgroundColor);
|
||||
p.setRenderHint(QPainter::Antialiasing, true);
|
||||
p.translate(nonAreaRect.center().x(), nonAreaRect.center().y());
|
||||
|
||||
switch (DockWidgetArea)
|
||||
{
|
||||
case TopDockWidgetArea:
|
||||
p.rotate(-90);
|
||||
break;
|
||||
case RightDockWidgetArea:
|
||||
break;
|
||||
case BottomDockWidgetArea:
|
||||
p.rotate(90);
|
||||
break;
|
||||
case LeftDockWidgetArea:
|
||||
p.rotate(180);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
p.drawPolygon(Arrow);
|
||||
}
|
||||
|
||||
return pm;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QWidget* createDropIndicatorWidget(DockWidgetArea DockWidgetArea,
|
||||
CDockOverlay::eMode Mode)
|
||||
{
|
||||
QLabel* l = new QLabel();
|
||||
l->setObjectName("DockWidgetAreaLabel");
|
||||
|
||||
const qreal metric = static_cast<qreal>(l->fontMetrics().height()) * 3.f;
|
||||
const QSizeF size(metric, metric);
|
||||
|
||||
l->setPixmap(createDropIndicatorPixmap(l->palette(), size, DockWidgetArea,
|
||||
Mode));
|
||||
l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
|
||||
l->setAttribute(Qt::WA_TranslucentBackground);
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Private data class of CDockOverlay
|
||||
@@ -219,6 +73,8 @@ struct DockOverlayCrossPrivate
|
||||
CDockOverlay* DockOverlay;
|
||||
QHash<DockWidgetArea, QWidget*> DropIndicatorWidgets;
|
||||
QGridLayout* GridLayout;
|
||||
QColor IconColors[5];
|
||||
bool UpdateRequired = false;
|
||||
|
||||
/**
|
||||
* Private data constructor
|
||||
@@ -231,6 +87,206 @@ struct DockOverlayCrossPrivate
|
||||
* @return
|
||||
*/
|
||||
QPoint areaGridPosition(const DockWidgetArea area);
|
||||
|
||||
|
||||
/**
|
||||
* Palette based default icon colors
|
||||
*/
|
||||
QColor defaultIconColor(CDockOverlayCross::eIconColor ColorIndex)
|
||||
{
|
||||
QPalette pal = _this->palette();
|
||||
switch (ColorIndex)
|
||||
{
|
||||
case CDockOverlayCross::FrameColor: return pal.color(QPalette::Active, QPalette::Highlight);
|
||||
case CDockOverlayCross::WindowBackgroundColor: return pal.color(QPalette::Active, QPalette::Base);
|
||||
case CDockOverlayCross::OverlayColor:
|
||||
{
|
||||
QColor Color = pal.color(QPalette::Active, QPalette::Highlight);
|
||||
Color.setAlpha(64);
|
||||
return Color;
|
||||
}
|
||||
break;
|
||||
|
||||
case CDockOverlayCross::ArrowColor: return pal.color(QPalette::Active, QPalette::Base);
|
||||
case CDockOverlayCross::ShadowColor: return QColor(0, 0, 0, 64);
|
||||
default:
|
||||
return QColor();
|
||||
}
|
||||
|
||||
return QColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stylehseet based icon colors
|
||||
*/
|
||||
QColor iconColor(CDockOverlayCross::eIconColor ColorIndex)
|
||||
{
|
||||
QColor Color = IconColors[ColorIndex];
|
||||
if (!Color.isValid())
|
||||
{
|
||||
Color = defaultIconColor(ColorIndex);
|
||||
IconColors[ColorIndex] = Color;
|
||||
}
|
||||
return Color;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QWidget* createDropIndicatorWidget(DockWidgetArea DockWidgetArea,
|
||||
CDockOverlay::eMode Mode)
|
||||
{
|
||||
QLabel* l = new QLabel();
|
||||
l->setObjectName("DockWidgetAreaLabel");
|
||||
|
||||
const qreal metric = static_cast<qreal>(l->fontMetrics().height()) * 3.f;
|
||||
const QSizeF size(metric, metric);
|
||||
|
||||
l->setPixmap(createDropIndicatorPixmap(size, DockWidgetArea, Mode));
|
||||
l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
|
||||
l->setAttribute(Qt::WA_TranslucentBackground);
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QPixmap createDropIndicatorPixmap(const QSizeF& size, DockWidgetArea DockWidgetArea,
|
||||
CDockOverlay::eMode Mode)
|
||||
{
|
||||
QColor borderColor = iconColor(CDockOverlayCross::FrameColor);
|
||||
QColor backgroundColor = iconColor(CDockOverlayCross::WindowBackgroundColor);
|
||||
|
||||
QPixmap pm(size.width(), size.height());
|
||||
pm.fill(QColor(0, 0, 0, 0));
|
||||
|
||||
QPainter p(&pm);
|
||||
QPen pen = p.pen();
|
||||
QRectF ShadowRect(pm.rect());
|
||||
QRectF baseRect;
|
||||
baseRect.setSize(ShadowRect.size() * 0.7);
|
||||
baseRect.moveCenter(ShadowRect.center());
|
||||
|
||||
// Fill
|
||||
QColor ShadowColor = iconColor(CDockOverlayCross::ShadowColor);
|
||||
if (ShadowColor.alpha() == 255)
|
||||
{
|
||||
ShadowColor.setAlpha(64);
|
||||
}
|
||||
p.fillRect(ShadowRect, ShadowColor);
|
||||
|
||||
// Drop area rect.
|
||||
p.save();
|
||||
QRectF areaRect;
|
||||
QLineF areaLine;
|
||||
QRectF nonAreaRect;
|
||||
switch (DockWidgetArea)
|
||||
{
|
||||
case TopDockWidgetArea:
|
||||
areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
|
||||
nonAreaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
|
||||
areaLine = QLineF(areaRect.bottomLeft(), areaRect.bottomRight());
|
||||
break;
|
||||
case RightDockWidgetArea:
|
||||
areaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
|
||||
nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
|
||||
areaLine = QLineF(areaRect.topLeft(), areaRect.bottomLeft());
|
||||
break;
|
||||
case BottomDockWidgetArea:
|
||||
areaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
|
||||
nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
|
||||
areaLine = QLineF(areaRect.topLeft(), areaRect.topRight());
|
||||
break;
|
||||
case LeftDockWidgetArea:
|
||||
areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
|
||||
nonAreaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
|
||||
areaLine = QLineF(areaRect.topRight(), areaRect.bottomRight());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QSizeF baseSize = baseRect.size();
|
||||
if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea)
|
||||
{
|
||||
baseRect = areaRect;
|
||||
}
|
||||
|
||||
p.fillRect(baseRect, backgroundColor);
|
||||
if (areaRect.isValid())
|
||||
{
|
||||
pen = p.pen();
|
||||
pen.setColor(borderColor);
|
||||
QColor Color = iconColor(CDockOverlayCross::OverlayColor);
|
||||
if (Color.alpha() == 255)
|
||||
{
|
||||
Color.setAlpha(64);
|
||||
}
|
||||
p.setBrush(Color);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawRect(areaRect);
|
||||
|
||||
pen = p.pen();
|
||||
pen.setColor(borderColor);
|
||||
pen.setStyle(Qt::DashLine);
|
||||
p.setPen(pen);
|
||||
p.drawLine(areaLine);
|
||||
}
|
||||
p.restore();
|
||||
|
||||
p.save();
|
||||
// Draw outer border
|
||||
pen = p.pen();
|
||||
pen.setColor(borderColor);
|
||||
pen.setWidth(1);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.setPen(pen);
|
||||
p.drawRect(baseRect);
|
||||
|
||||
// draw window title bar
|
||||
p.setBrush(borderColor);
|
||||
QRectF FrameRect(baseRect.topLeft(), QSizeF(baseRect.width(), baseSize.height() / 10));
|
||||
p.drawRect(FrameRect);
|
||||
p.restore();
|
||||
|
||||
// Draw arrow for outer container drop indicators
|
||||
if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea)
|
||||
{
|
||||
QRectF ArrowRect;
|
||||
ArrowRect.setSize(baseSize);
|
||||
ArrowRect.setWidth(ArrowRect.width() / 4.6);
|
||||
ArrowRect.setHeight(ArrowRect.height() / 2);
|
||||
ArrowRect.moveCenter(QPointF(0, 0));
|
||||
QPolygonF Arrow;
|
||||
Arrow << ArrowRect.topLeft()
|
||||
<< QPointF( ArrowRect.right(), ArrowRect.center().y())
|
||||
<< ArrowRect.bottomLeft();
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(iconColor(CDockOverlayCross::ArrowColor));
|
||||
p.setRenderHint(QPainter::Antialiasing, true);
|
||||
p.translate(nonAreaRect.center().x(), nonAreaRect.center().y());
|
||||
|
||||
switch (DockWidgetArea)
|
||||
{
|
||||
case TopDockWidgetArea:
|
||||
p.rotate(-90);
|
||||
break;
|
||||
case RightDockWidgetArea:
|
||||
break;
|
||||
case BottomDockWidgetArea:
|
||||
p.rotate(90);
|
||||
break;
|
||||
case LeftDockWidgetArea:
|
||||
p.rotate(180);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
p.drawPolygon(Arrow);
|
||||
}
|
||||
|
||||
return pm;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -247,7 +303,6 @@ CDockOverlay::CDockOverlay(QWidget* parent, eMode Mode) :
|
||||
setAttribute(Qt::WA_NoSystemBackground);
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
|
||||
d->Cross->setupOverlayCross(Mode);
|
||||
d->Cross->setVisible(false);
|
||||
setVisible(false);
|
||||
}
|
||||
@@ -405,6 +460,18 @@ void CDockOverlay::hideEvent(QHideEvent* e)
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool CDockOverlay::event(QEvent *e)
|
||||
{
|
||||
bool Result = Super::event(e);
|
||||
if (e->type() == QEvent::Polish)
|
||||
{
|
||||
d->Cross->setupOverlayCross(d->Mode);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
static int areaAlignment(const DockWidgetArea area)
|
||||
{
|
||||
@@ -480,13 +547,29 @@ void CDockOverlayCross::setupOverlayCross(CDockOverlay::eMode Mode)
|
||||
d->Mode = Mode;
|
||||
|
||||
QHash<DockWidgetArea, QWidget*> areaWidgets;
|
||||
areaWidgets.insert(TopDockWidgetArea, createDropIndicatorWidget(TopDockWidgetArea, Mode));
|
||||
areaWidgets.insert(RightDockWidgetArea, createDropIndicatorWidget(RightDockWidgetArea, Mode));
|
||||
areaWidgets.insert(BottomDockWidgetArea, createDropIndicatorWidget(BottomDockWidgetArea, Mode));
|
||||
areaWidgets.insert(LeftDockWidgetArea, createDropIndicatorWidget(LeftDockWidgetArea, Mode));
|
||||
areaWidgets.insert(CenterDockWidgetArea, createDropIndicatorWidget(CenterDockWidgetArea, Mode));
|
||||
areaWidgets.insert(TopDockWidgetArea, d->createDropIndicatorWidget(TopDockWidgetArea, Mode));
|
||||
areaWidgets.insert(RightDockWidgetArea, d->createDropIndicatorWidget(RightDockWidgetArea, Mode));
|
||||
areaWidgets.insert(BottomDockWidgetArea, d->createDropIndicatorWidget(BottomDockWidgetArea, Mode));
|
||||
areaWidgets.insert(LeftDockWidgetArea, d->createDropIndicatorWidget(LeftDockWidgetArea, Mode));
|
||||
areaWidgets.insert(CenterDockWidgetArea, d->createDropIndicatorWidget(CenterDockWidgetArea, Mode));
|
||||
|
||||
setAreaWidgets(areaWidgets);
|
||||
d->UpdateRequired = false;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockOverlayCross::setIconColor(eIconColor ColorIndex, const QColor& Color)
|
||||
{
|
||||
d->IconColors[ColorIndex] = Color;
|
||||
d->UpdateRequired = true;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QColor CDockOverlayCross::iconColor(eIconColor ColorIndex) const
|
||||
{
|
||||
return d->IconColors[ColorIndex];
|
||||
}
|
||||
|
||||
|
||||
@@ -573,6 +656,10 @@ DockWidgetArea CDockOverlayCross::cursorLocation() const
|
||||
//============================================================================
|
||||
void CDockOverlayCross::showEvent(QShowEvent*)
|
||||
{
|
||||
if (d->UpdateRequired)
|
||||
{
|
||||
setupOverlayCross(d->Mode);
|
||||
}
|
||||
this->updatePosition();
|
||||
}
|
||||
|
||||
@@ -611,6 +698,38 @@ void CDockOverlayCross::reset()
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockOverlayCross::setIconColors(const QString& Colors)
|
||||
{
|
||||
static const QMap<QString, int> ColorCompenentStringMap{
|
||||
{"Frame", CDockOverlayCross::FrameColor},
|
||||
{"Background", CDockOverlayCross::WindowBackgroundColor},
|
||||
{"Overlay", CDockOverlayCross::OverlayColor},
|
||||
{"Arrow", CDockOverlayCross::ArrowColor},
|
||||
{"Shadow", CDockOverlayCross::ShadowColor}};
|
||||
|
||||
auto ColorList = Colors.split(' ', QString::SkipEmptyParts);
|
||||
for (const auto& ColorListEntry : ColorList)
|
||||
{
|
||||
auto ComponentColor = ColorListEntry.split('=', QString::SkipEmptyParts);
|
||||
int Component = ColorCompenentStringMap.value(ComponentColor[0], -1);
|
||||
if (Component < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
d->IconColors[Component] = QColor(ComponentColor[1]);
|
||||
}
|
||||
|
||||
d->UpdateRequired = true;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
QString CDockOverlayCross::iconColors() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace ads
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
/*******************************************************************************
|
||||
** Qt Advanced Docking System
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU Lesser General Public
|
||||
** License as published by the Free Software Foundation; either
|
||||
** version 2.1 of the License, or (at your option) any later version.
|
||||
**
|
||||
**
|
||||
** This library 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
|
||||
** Lesser General Public License for more details.
|
||||
**
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser General Public
|
||||
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
@@ -39,15 +39,17 @@ class CDockOverlayCross;
|
||||
* DockOverlay paints a translucent rectangle over another widget. The geometry
|
||||
* of the rectangle is based on the mouse location.
|
||||
*/
|
||||
class CDockOverlay : public QFrame
|
||||
class ADS_EXPORT CDockOverlay : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
DockOverlayPrivate* d; //< private data class
|
||||
friend class DockOverlayPrivate;
|
||||
friend struct DockOverlayPrivate;
|
||||
friend class DockOverlayCross;
|
||||
|
||||
public:
|
||||
using Super = QFrame;
|
||||
|
||||
enum eMode
|
||||
{
|
||||
ModeDockAreaOverlay,
|
||||
@@ -100,6 +102,11 @@ public:
|
||||
*/
|
||||
QRect dropOverlayRect() const;
|
||||
|
||||
/**
|
||||
* Handle polish events
|
||||
*/
|
||||
virtual bool event(QEvent *e) override;
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent *e) override;
|
||||
virtual void showEvent(QShowEvent* e) override;
|
||||
@@ -112,18 +119,71 @@ struct DockOverlayCrossPrivate;
|
||||
* DockOverlayCross shows a cross with 5 different drop area possibilities.
|
||||
* I could have handled everything inside DockOverlay, but because of some
|
||||
* styling issues it's better to have a separate class for the cross.
|
||||
* You can style the cross icon using the property system.
|
||||
* \code
|
||||
* ads--CDockOverlayCross
|
||||
{
|
||||
qproperty-iconFrameColor: palette(highlight);
|
||||
qproperty-iconBackgroundColor: palette(base);
|
||||
qproperty-iconOverlayColor: palette(highlight);
|
||||
qproperty-iconArrowColor: rgb(227, 227, 227);
|
||||
qproperty-iconShadowColor: rgb(0, 0, 0);
|
||||
}
|
||||
* \endcode
|
||||
* Or you can use the iconColors property to pass in AARRGGBB values as
|
||||
* hex string like shown in the example below.
|
||||
* \code
|
||||
* ads--CDockOverlayCross
|
||||
* {
|
||||
* qproperty-iconColors: "Frame=#ff3d3d3d Background=#ff929292 Overlay=#1f3d3d3d Arrow=#ffb4b4b4 Shadow=#40474747";
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
class CDockOverlayCross : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString iconColors READ iconColors WRITE setIconColors)
|
||||
Q_PROPERTY(QColor iconFrameColor READ iconColor WRITE setIconFrameColor)
|
||||
Q_PROPERTY(QColor iconBackgroundColor READ iconColor WRITE setIconBackgroundColor)
|
||||
Q_PROPERTY(QColor iconOverlayColor READ iconColor WRITE setIconOverlayColor)
|
||||
Q_PROPERTY(QColor iconArrowColor READ iconColor WRITE setIconArrowColor)
|
||||
Q_PROPERTY(QColor iconShadowColor READ iconColor WRITE setIconShadowColor)
|
||||
|
||||
public:
|
||||
enum eIconColor
|
||||
{
|
||||
FrameColor,///< the color of the frame of the small window icon
|
||||
WindowBackgroundColor,///< the background color of the small window in the icon
|
||||
OverlayColor,///< the color that shows the overlay (the dock side) in the icon
|
||||
ArrowColor,///< the arrow that points into the direction
|
||||
ShadowColor///< the color of the shadow rectangle that is painted below the icons
|
||||
};
|
||||
|
||||
private:
|
||||
DockOverlayCrossPrivate* d;
|
||||
friend class DockOverlayCrossPrivate;
|
||||
friend struct DockOverlayCrossPrivate;
|
||||
friend class CDockOverlay;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* This function returns an empty string and is only here to silence
|
||||
* moc
|
||||
*/
|
||||
QString iconColors() const;
|
||||
|
||||
/**
|
||||
* This is a dummy function for the property system
|
||||
*/
|
||||
QColor iconColor() const {return QColor();}
|
||||
void setIconFrameColor(const QColor& Color) {setIconColor(FrameColor, Color);}
|
||||
void setIconBackgroundColor(const QColor& Color) {setIconColor(WindowBackgroundColor, Color);}
|
||||
void setIconOverlayColor(const QColor& Color) {setIconColor(OverlayColor, Color);}
|
||||
void setIconArrowColor(const QColor& Color) {setIconColor(ArrowColor, Color);}
|
||||
void setIconShadowColor(const QColor& Color) {setIconColor(ShadowColor, Color);}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates an overlay corss for the given overlay
|
||||
* Creates an overlay cross for the given overlay
|
||||
*/
|
||||
CDockOverlayCross(CDockOverlay* overlay);
|
||||
|
||||
@@ -132,6 +192,16 @@ public:
|
||||
*/
|
||||
virtual ~CDockOverlayCross();
|
||||
|
||||
/**
|
||||
* Sets a certain icon color
|
||||
*/
|
||||
void setIconColor(eIconColor ColorIndex, const QColor& Color);
|
||||
|
||||
/**
|
||||
* Returns the icon color given by ColorIndex
|
||||
*/
|
||||
QColor iconColor(eIconColor ColorIndex) const;
|
||||
|
||||
/**
|
||||
* Returns the dock widget area depending on the current cursor location.
|
||||
* The function checks, if the mouse cursor is inside of any drop indicator
|
||||
@@ -154,6 +224,19 @@ public:
|
||||
*/
|
||||
void updatePosition();
|
||||
|
||||
/**
|
||||
* A string with all icon colors to set.
|
||||
* You can use this property to style the overly icon via CSS stylesheet
|
||||
* file. The colors are set via a color identifier and a hex AARRGGBB value like
|
||||
* in the example below.
|
||||
* \code
|
||||
* ads--CDockOverlayCross
|
||||
* {
|
||||
* qproperty-iconColors: "Frame=#ff3d3d3d Background=#ff929292 Overlay=#1f3d3d3d Arrow=#ffb4b4b4 Shadow=#40474747";
|
||||
* }
|
||||
*/
|
||||
void setIconColors(const QString& Colors);
|
||||
|
||||
protected:
|
||||
virtual void showEvent(QShowEvent* e) override;
|
||||
void setAreaWidgets(const QHash<DockWidgetArea, QWidget*>& widgets);
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
/*******************************************************************************
|
||||
** Qt Advanced Docking System
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU Lesser General Public
|
||||
** License as published by the Free Software Foundation; either
|
||||
** version 2.1 of the License, or (at your option) any later version.
|
||||
**
|
||||
**
|
||||
** This library 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
|
||||
** Lesser General Public License for more details.
|
||||
**
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser General Public
|
||||
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
@@ -31,6 +31,8 @@
|
||||
//============================================================================
|
||||
#include <QSplitter>
|
||||
|
||||
#include "ads_globals.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
struct DockSplitterPrivate;
|
||||
@@ -38,12 +40,12 @@ struct DockSplitterPrivate;
|
||||
/**
|
||||
* Splitter used internally instead of QSplitter
|
||||
*/
|
||||
class CDockSplitter : public QSplitter
|
||||
class ADS_EXPORT CDockSplitter : public QSplitter
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
DockSplitterPrivate* d;
|
||||
friend class DockSplitterPrivate;
|
||||
friend struct DockSplitterPrivate;
|
||||
|
||||
public:
|
||||
CDockSplitter(QWidget *parent = Q_NULLPTR);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include <DockWidgetTab.h>
|
||||
#include "DockWidget.h"
|
||||
|
||||
#include <QBoxLayout>
|
||||
@@ -38,8 +39,8 @@
|
||||
#include <QPointer>
|
||||
#include <QEvent>
|
||||
#include <QDebug>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
#include "DockWidgetTitleBar.h"
|
||||
#include "DockContainerWidget.h"
|
||||
#include "DockAreaWidget.h"
|
||||
#include "DockManager.h"
|
||||
@@ -58,7 +59,7 @@ struct DockWidgetPrivate
|
||||
CDockWidget* _this;
|
||||
QBoxLayout* Layout;
|
||||
QWidget* Widget = nullptr;
|
||||
CDockWidgetTitleBar* TitleWidget;
|
||||
CDockWidgetTab* TitleWidget;
|
||||
CDockWidget::DockWidgetFeatures Features = CDockWidget::AllDockWidgetFeatures;
|
||||
CDockManager* DockManager = nullptr;
|
||||
CDockAreaWidget* DockArea = nullptr;
|
||||
@@ -210,8 +211,9 @@ CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
|
||||
d->Layout->setSpacing(0);
|
||||
setLayout(d->Layout);
|
||||
setWindowTitle(title);
|
||||
setObjectName(title);
|
||||
|
||||
d->TitleWidget = new CDockWidgetTitleBar(this);
|
||||
d->TitleWidget = new CDockWidgetTab(this);
|
||||
d->ToggleViewAction = new QAction(title);
|
||||
d->ToggleViewAction->setCheckable(true);
|
||||
connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this,
|
||||
@@ -260,7 +262,7 @@ QWidget* CDockWidget::widget() const
|
||||
|
||||
|
||||
//============================================================================
|
||||
CDockWidgetTitleBar* CDockWidget::titleBar() const
|
||||
CDockWidgetTab* CDockWidget::titleBar() const
|
||||
{
|
||||
return d->TitleWidget;
|
||||
}
|
||||
@@ -273,6 +275,13 @@ void CDockWidget::setFeatures(DockWidgetFeatures features)
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockWidget::setFeature(DockWidgetFeature flag, bool on)
|
||||
{
|
||||
d->Features.setFlag(flag, on);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
CDockWidget::DockWidgetFeatures CDockWidget::features() const
|
||||
{
|
||||
@@ -329,9 +338,31 @@ QAction* CDockWidget::toggleViewAction() const
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockWidget::setToggleViewActionMode(eToggleViewActionMode Mode)
|
||||
{
|
||||
if (ActionModeToggle == Mode)
|
||||
{
|
||||
d->ToggleViewAction->setCheckable(true);
|
||||
d->ToggleViewAction->setIcon(QIcon());
|
||||
}
|
||||
else
|
||||
{
|
||||
d->ToggleViewAction->setCheckable(false);
|
||||
d->ToggleViewAction->setIcon(d->TitleWidget->icon());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockWidget::toggleView(bool Open)
|
||||
{
|
||||
QAction* Sender = qobject_cast<QAction*>(sender());
|
||||
if (Sender == d->ToggleViewAction && !d->ToggleViewAction->isCheckable())
|
||||
{
|
||||
Open = true;
|
||||
}
|
||||
|
||||
if (Open)
|
||||
{
|
||||
d->showDockWidget();
|
||||
@@ -361,11 +392,12 @@ void CDockWidget::setDockArea(CDockAreaWidget* DockArea)
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockWidget::saveState(QDataStream& stream) const
|
||||
void CDockWidget::saveState(QXmlStreamWriter& s) const
|
||||
{
|
||||
stream << internal::DockWidgetMarker;
|
||||
qDebug() << "CDockWidget::saveState " << objectName() << " closed " << d->Closed;
|
||||
stream << objectName() << d->Closed;
|
||||
s.writeStartElement("DockWidget");
|
||||
s.writeAttribute("ObjectName", objectName());
|
||||
s.writeAttribute("Closed", QString::number(d->Closed ? 1 : 0));
|
||||
s.writeEndElement();
|
||||
}
|
||||
|
||||
|
||||
@@ -389,6 +421,24 @@ bool CDockWidget::event(QEvent *e)
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockWidget::setIcon(const QIcon& Icon)
|
||||
{
|
||||
d->TitleWidget->setIcon(Icon);
|
||||
if (!d->ToggleViewAction->isCheckable())
|
||||
{
|
||||
d->ToggleViewAction->setIcon(Icon);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QIcon CDockWidget::icon() const
|
||||
{
|
||||
return d->TitleWidget->icon();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace ads
|
||||
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
/*******************************************************************************
|
||||
** Qt Advanced Docking System
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU Lesser General Public
|
||||
** License as published by the Free Software Foundation; either
|
||||
** version 2.1 of the License, or (at your option) any later version.
|
||||
**
|
||||
**
|
||||
** This library 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
|
||||
** Lesser General Public License for more details.
|
||||
**
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser General Public
|
||||
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
@@ -32,10 +32,14 @@
|
||||
//============================================================================
|
||||
#include <QFrame>
|
||||
|
||||
#include "ads_globals.h"
|
||||
|
||||
class QXmlStreamWriter;
|
||||
|
||||
namespace ads
|
||||
{
|
||||
struct DockWidgetPrivate;
|
||||
class CDockWidgetTitleBar;
|
||||
class CDockWidgetTab;
|
||||
class CDockManager;
|
||||
class CDockContainerWidget;
|
||||
class CDockAreaWidget;
|
||||
@@ -45,19 +49,19 @@ struct DockContainerWidgetPrivate;
|
||||
* The QDockWidget class provides a widget that can be docked inside a
|
||||
* CDockManager or floated as a top-level window on the desktop.
|
||||
*/
|
||||
class CDockWidget : public QFrame
|
||||
class ADS_EXPORT CDockWidget : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
DockWidgetPrivate* d; ///< private data (pimpl)
|
||||
friend class DockWidgetPrivate;
|
||||
friend struct DockWidgetPrivate;
|
||||
|
||||
protected:
|
||||
friend class CDockContainerWidget;
|
||||
friend class CDockAreaWidget;
|
||||
friend class CFloatingDockContainer;
|
||||
friend class CDockManager;
|
||||
friend class DockContainerWidgetPrivate;
|
||||
friend struct DockContainerWidgetPrivate;
|
||||
|
||||
/**
|
||||
* Assigns the dock manager that manages this dock widget
|
||||
@@ -81,7 +85,7 @@ protected:
|
||||
/**
|
||||
* Saves the state into the given stream
|
||||
*/
|
||||
void saveState(QDataStream& Stream) const;
|
||||
void saveState(QXmlStreamWriter& Stream) const;
|
||||
|
||||
/**
|
||||
* This is a helper function for the dock manager to flag this widget
|
||||
@@ -114,7 +118,30 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Default Constructor
|
||||
* This mode configures the behavior of the toggle view action.
|
||||
* If the mode if ActionModeToggle, then the toggle view action is
|
||||
* a checkable action to show / hide the dock widget. If the mode
|
||||
* is ActionModeShow, then the action is not checkable an it will
|
||||
* always show the dock widget if clicked. If the mode is ActionModeShow,
|
||||
* the user can only close the DockWidget with the close button.
|
||||
*/
|
||||
enum eToggleViewActionMode
|
||||
{
|
||||
ActionModeToggle,//!< ActionModeToggle
|
||||
ActionModeShow //!< ActionModeShow
|
||||
};
|
||||
|
||||
/**
|
||||
* This constructor creates a dock widget with the given title.
|
||||
* The title is the text that is shown in the window title when the dock
|
||||
* widget is floating and it is the title that is shown in the titlebar
|
||||
* or the tab of this dock widget if it is tabified.
|
||||
* The object name of the dock widget is also set to the title. The
|
||||
* object name is required by the dock manager to properly save and restore
|
||||
* the state of the dock widget. That means, the title needs to be unique.
|
||||
* If your title is not unique or if you would like to change the title
|
||||
* during runtime, you need to set a unique object name explicitely
|
||||
* by calling setObjectName() after construction.
|
||||
*/
|
||||
CDockWidget(const QString &title, QWidget* parent = 0);
|
||||
|
||||
@@ -137,13 +164,19 @@ public:
|
||||
/**
|
||||
* Returns the title bar widget of this dock widget
|
||||
*/
|
||||
CDockWidgetTitleBar* titleBar() const;
|
||||
CDockWidgetTab* titleBar() const;
|
||||
|
||||
/**
|
||||
* Sets, whether the dock widget is movable, closable, and floatable.
|
||||
*/
|
||||
void setFeatures(DockWidgetFeatures features);
|
||||
|
||||
/**
|
||||
* Sets the feature flag for this dock widget if on is true; otherwise
|
||||
* clears the flag.
|
||||
*/
|
||||
void setFeature(DockWidgetFeature flag, bool on);
|
||||
|
||||
/**
|
||||
* This property holds whether the dock widget is movable, closable, and
|
||||
* floatable.
|
||||
@@ -187,7 +220,26 @@ public:
|
||||
QAction* toggleViewAction() const;
|
||||
|
||||
/**
|
||||
* Emits titleChanged signal if title change event occures
|
||||
* Configures the behavior of the toggle view action.
|
||||
* \see eToggleViewActionMode for a detailed description
|
||||
*/
|
||||
void setToggleViewActionMode(eToggleViewActionMode Mode);
|
||||
|
||||
/**
|
||||
* Sets the dock widget icon that is shown in tabs and in toggle view
|
||||
* actions
|
||||
*/
|
||||
void setIcon(const QIcon& Icon);
|
||||
|
||||
/**
|
||||
* Returns tzhe icon that has been assigned to the dock widget
|
||||
*/
|
||||
QIcon icon() const;
|
||||
|
||||
|
||||
public: // reimplements QFrame -----------------------------------------------
|
||||
/**
|
||||
* Emits titleChanged signal if title change event occurs
|
||||
*/
|
||||
virtual bool event(QEvent *e) override;
|
||||
|
||||
@@ -196,7 +248,7 @@ public slots:
|
||||
* This property controls whether the dock widget is open or closed.
|
||||
* The toogleViewAction triggers this slot
|
||||
*/
|
||||
void toggleView(bool Open);
|
||||
void toggleView(bool Open = true);
|
||||
|
||||
signals:
|
||||
/**
|
||||
|
||||
@@ -18,17 +18,17 @@
|
||||
|
||||
|
||||
//============================================================================
|
||||
/// \file DockWidgetTitleBar.cpp
|
||||
/// \file DockWidgetTab.cpp
|
||||
/// \author Uwe Kindler
|
||||
/// \date 27.02.2017
|
||||
/// \brief Implementation of CDockWidgetTitleBar class
|
||||
/// \brief Implementation of CDockWidgetTab class
|
||||
//============================================================================
|
||||
|
||||
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include "DockWidgetTitleBar.h"
|
||||
#include "DockWidgetTab.h"
|
||||
|
||||
#include <QBoxLayout>
|
||||
#include <QLabel>
|
||||
@@ -60,11 +60,11 @@ enum eDragState
|
||||
|
||||
|
||||
/**
|
||||
* Private data class of CDockWidgetTitleBar class (pimpl)
|
||||
* Private data class of CDockWidgetTab class (pimpl)
|
||||
*/
|
||||
struct DockWidgetTitleBarPrivate
|
||||
struct DockWidgetTabPrivate
|
||||
{
|
||||
CDockWidgetTitleBar* _this;
|
||||
CDockWidgetTab* _this;
|
||||
CDockWidget* DockWidget;
|
||||
QLabel* IconLabel;
|
||||
QLabel* TitleLabel;
|
||||
@@ -73,11 +73,12 @@ struct DockWidgetTitleBarPrivate
|
||||
CDockAreaWidget* DockArea = nullptr;
|
||||
eDragState DragState = DraggingInactive;
|
||||
CFloatingDockContainer* FloatingWidget = nullptr;
|
||||
QIcon Icon;
|
||||
|
||||
/**
|
||||
* Private data constructor
|
||||
*/
|
||||
DockWidgetTitleBarPrivate(CDockWidgetTitleBar* _public);
|
||||
DockWidgetTabPrivate(CDockWidgetTab* _public);
|
||||
|
||||
/**
|
||||
* Creates the complete layout including all controls
|
||||
@@ -114,11 +115,11 @@ struct DockWidgetTitleBarPrivate
|
||||
*/
|
||||
bool startFloating();
|
||||
};
|
||||
// struct DockWidgetTitleBarPrivate
|
||||
// struct DockWidgetTabPrivate
|
||||
|
||||
|
||||
//============================================================================
|
||||
DockWidgetTitleBarPrivate::DockWidgetTitleBarPrivate(CDockWidgetTitleBar* _public) :
|
||||
DockWidgetTabPrivate::DockWidgetTabPrivate(CDockWidgetTab* _public) :
|
||||
_this(_public)
|
||||
{
|
||||
|
||||
@@ -126,7 +127,7 @@ DockWidgetTitleBarPrivate::DockWidgetTitleBarPrivate(CDockWidgetTitleBar* _publi
|
||||
|
||||
|
||||
//============================================================================
|
||||
void DockWidgetTitleBarPrivate::createLayout()
|
||||
void DockWidgetTabPrivate::createLayout()
|
||||
{
|
||||
QBoxLayout* l = new QBoxLayout(QBoxLayout::LeftToRight);
|
||||
l->setContentsMargins(0, 0, 0, 0);
|
||||
@@ -137,6 +138,7 @@ void DockWidgetTitleBarPrivate::createLayout()
|
||||
l->addWidget(IconLabel, Qt::AlignVCenter);
|
||||
|
||||
TitleLabel = new QLabel();
|
||||
TitleLabel->setObjectName("dockWidgetTabLabel");
|
||||
l->addWidget(TitleLabel, 1);
|
||||
|
||||
IconLabel->setVisible(false);
|
||||
@@ -145,7 +147,7 @@ void DockWidgetTitleBarPrivate::createLayout()
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
void DockWidgetTitleBarPrivate::moveTab(QMouseEvent* ev)
|
||||
void DockWidgetTabPrivate::moveTab(QMouseEvent* ev)
|
||||
{
|
||||
ev->accept();
|
||||
int left, top, right, bottom;
|
||||
@@ -158,13 +160,13 @@ void DockWidgetTitleBarPrivate::moveTab(QMouseEvent* ev)
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool DockWidgetTitleBarPrivate::startFloating()
|
||||
bool DockWidgetTabPrivate::startFloating()
|
||||
{
|
||||
qDebug() << "isFloating " << DockWidget->dockContainer()->isFloating();
|
||||
qDebug() << "areaCount " << DockWidget->dockContainer()->dockAreaCount();
|
||||
qDebug() << "widgetCount " << DockWidget->dockAreaWidget()->count();
|
||||
// if this is the last dock widget inside of this floating widget,
|
||||
// then it does not make any sense, to make if floating because
|
||||
// then it does not make any sense, to make it floating because
|
||||
// it is already floating
|
||||
if (DockWidget->dockContainer()->isFloating()
|
||||
&& (DockWidget->dockContainer()->visibleDockAreaCount() == 1)
|
||||
@@ -184,7 +186,7 @@ bool DockWidgetTitleBarPrivate::startFloating()
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "DockWidgetTitleBarPrivate::startFloating DockArea";
|
||||
qDebug() << "DockWidgetTabPrivate::startFloating DockArea";
|
||||
// If section widget has only one content widget, we can move the complete
|
||||
// dock area into floating widget
|
||||
FloatingWidget = new CFloatingDockContainer(DockArea);
|
||||
@@ -199,9 +201,9 @@ bool DockWidgetTitleBarPrivate::startFloating()
|
||||
|
||||
|
||||
//============================================================================
|
||||
CDockWidgetTitleBar::CDockWidgetTitleBar(CDockWidget* DockWidget, QWidget *parent) :
|
||||
CDockWidgetTab::CDockWidgetTab(CDockWidget* DockWidget, QWidget *parent) :
|
||||
QFrame(parent),
|
||||
d(new DockWidgetTitleBarPrivate(this))
|
||||
d(new DockWidgetTabPrivate(this))
|
||||
{
|
||||
setAttribute(Qt::WA_NoMousePropagation, true);
|
||||
d->DockWidget = DockWidget;
|
||||
@@ -209,19 +211,19 @@ CDockWidgetTitleBar::CDockWidgetTitleBar(CDockWidget* DockWidget, QWidget *paren
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
CDockWidgetTitleBar::~CDockWidgetTitleBar()
|
||||
CDockWidgetTab::~CDockWidgetTab()
|
||||
{
|
||||
qDebug() << "~CDockWidgetTitleBar()";
|
||||
qDebug() << "~CDockWidgetTab()";
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockWidgetTitleBar::mousePressEvent(QMouseEvent* ev)
|
||||
void CDockWidgetTab::mousePressEvent(QMouseEvent* ev)
|
||||
{
|
||||
if (ev->button() == Qt::LeftButton)
|
||||
{
|
||||
qDebug() << "CDockWidgetTitleBar::mousePressEvent";
|
||||
qDebug() << "CDockWidgetTab::mousePressEvent";
|
||||
ev->accept();
|
||||
d->DragStartMousePosition = ev->pos();
|
||||
d->DragState = DraggingMousePressed;
|
||||
@@ -233,22 +235,22 @@ void CDockWidgetTitleBar::mousePressEvent(QMouseEvent* ev)
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockWidgetTitleBar::mouseReleaseEvent(QMouseEvent* ev)
|
||||
void CDockWidgetTab::mouseReleaseEvent(QMouseEvent* ev)
|
||||
{
|
||||
qDebug() << "CDockWidgetTitleBar::mouseReleaseEvent";
|
||||
qDebug() << "CDockWidgetTab::mouseReleaseEvent";
|
||||
// End of tab moving, change order now
|
||||
if (d->isDraggingState(DraggingTab) && d->DockArea)
|
||||
{
|
||||
// Find tab under mouse
|
||||
QPoint pos = d->DockArea->mapFromGlobal(ev->globalPos());
|
||||
int fromIndex = d->DockArea->tabIndex(d->DockWidget);
|
||||
int toIndex = d->DockArea->indexOfContentByTitlePos(pos, this);
|
||||
if (-1 == toIndex)
|
||||
{
|
||||
toIndex = d->DockArea->count() - 1;
|
||||
}
|
||||
qDebug() << "Move tab from " << fromIndex << " to " << toIndex;
|
||||
d->DockArea->reorderDockWidget(fromIndex, toIndex);
|
||||
int fromIndex = d->DockArea->tabIndex(d->DockWidget);
|
||||
int toIndex = d->DockArea->indexOfContentByTitlePos(pos, this);
|
||||
if (-1 == toIndex)
|
||||
{
|
||||
toIndex = d->DockArea->count() - 1;
|
||||
}
|
||||
qDebug() << "Move tab from " << fromIndex << " to " << toIndex;
|
||||
d->DockArea->reorderDockWidget(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
if (!d->DragStartMousePosition.isNull())
|
||||
@@ -263,10 +265,8 @@ void CDockWidgetTitleBar::mouseReleaseEvent(QMouseEvent* ev)
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockWidgetTitleBar::mouseMoveEvent(QMouseEvent* ev)
|
||||
void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
|
||||
{
|
||||
/*std::cout << "CDockWidgetTitleBar::mouseMoveEventmouseMoveEvent DragState "
|
||||
<< d->DragState << std::endl;*/
|
||||
if (!(ev->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive))
|
||||
{
|
||||
d->DragState = DraggingInactive;
|
||||
@@ -274,10 +274,10 @@ void CDockWidgetTitleBar::mouseMoveEvent(QMouseEvent* ev)
|
||||
return;
|
||||
}
|
||||
|
||||
// move floating winwdow
|
||||
if (d->isDraggingState(DraggingFloatingWidget))
|
||||
{
|
||||
//std::cout << "DraggingFloatingWidget" << std::endl;
|
||||
d->FloatingWidget->moveFloating();
|
||||
d->FloatingWidget->moveFloating();
|
||||
QFrame::mouseMoveEvent(ev);
|
||||
return;
|
||||
}
|
||||
@@ -285,13 +285,19 @@ void CDockWidgetTitleBar::mouseMoveEvent(QMouseEvent* ev)
|
||||
// move tab
|
||||
if (d->isDraggingState(DraggingTab))
|
||||
{
|
||||
d->moveTab(ev);
|
||||
// Moving the tab is always allowed because it does not mean moving the
|
||||
// dock widget around
|
||||
d->moveTab(ev);
|
||||
}
|
||||
|
||||
bool MouseInsideTitleArea = d->titleAreaGeometryContains(ev->globalPos());
|
||||
if (!MouseInsideTitleArea)
|
||||
{
|
||||
d->startFloating();
|
||||
// Floating is only allowed for widgets that are movable
|
||||
if (d->DockWidget->features().testFlag(CDockWidget::DockWidgetMovable))
|
||||
{
|
||||
d->startFloating();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (d->DockArea->count() > 1
|
||||
@@ -306,14 +312,14 @@ void CDockWidgetTitleBar::mouseMoveEvent(QMouseEvent* ev)
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool CDockWidgetTitleBar::isActiveTab() const
|
||||
bool CDockWidgetTab::isActiveTab() const
|
||||
{
|
||||
return d->IsActiveTab;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockWidgetTitleBar::setActiveTab(bool active)
|
||||
void CDockWidgetTab::setActiveTab(bool active)
|
||||
{
|
||||
if (d->IsActiveTab == active)
|
||||
{
|
||||
@@ -332,25 +338,41 @@ void CDockWidgetTitleBar::setActiveTab(bool active)
|
||||
|
||||
|
||||
//============================================================================
|
||||
CDockWidget* CDockWidgetTitleBar::dockWidget() const
|
||||
CDockWidget* CDockWidgetTab::dockWidget() const
|
||||
{
|
||||
return d->DockWidget;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockWidgetTitleBar::setDockAreaWidget(CDockAreaWidget* DockArea)
|
||||
void CDockWidgetTab::setDockAreaWidget(CDockAreaWidget* DockArea)
|
||||
{
|
||||
d->DockArea = DockArea;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
CDockAreaWidget* CDockWidgetTitleBar::dockAreaWidget() const
|
||||
CDockAreaWidget* CDockWidgetTab::dockAreaWidget() const
|
||||
{
|
||||
return d->DockArea;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockWidgetTab::setIcon(const QIcon& Icon)
|
||||
{
|
||||
d->Icon = Icon;
|
||||
d->IconLabel->setPixmap(Icon.pixmap(this->windowHandle(), QSize(16, 16)));
|
||||
d->IconLabel->setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
const QIcon& CDockWidgetTab::icon() const
|
||||
{
|
||||
return d->Icon;
|
||||
}
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// EOF DockWidgetTitleBar.cpp
|
||||
// EOF DockWidgetTab.cpp
|
||||
@@ -1,29 +1,29 @@
|
||||
#ifndef DockWidgetTitleBarH
|
||||
#define DockWidgetTitleBarH
|
||||
#ifndef DockWidgetTabH
|
||||
#define DockWidgetTabH
|
||||
/*******************************************************************************
|
||||
** Qt Advanced Docking System
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU Lesser General Public
|
||||
** License as published by the Free Software Foundation; either
|
||||
** version 2.1 of the License, or (at your option) any later version.
|
||||
**
|
||||
**
|
||||
** This library 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
|
||||
** Lesser General Public License for more details.
|
||||
**
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser General Public
|
||||
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
//============================================================================
|
||||
/// \file DockWidgetTitleBar.h
|
||||
/// \file DockWidgetTab.h
|
||||
/// \author Uwe Kindler
|
||||
/// \date 27.02.2017
|
||||
/// \brief Declaration of CDockWidgetTitleBar class
|
||||
/// \brief Declaration of CDockWidgetTab class
|
||||
//============================================================================
|
||||
|
||||
|
||||
@@ -32,23 +32,27 @@
|
||||
//============================================================================
|
||||
#include <QFrame>
|
||||
|
||||
#include "ads_globals.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
class CDockWidget;
|
||||
class CDockAreaWidget;
|
||||
struct DockWidgetTitleBarPrivate;
|
||||
struct DockWidgetTabPrivate;
|
||||
|
||||
/**
|
||||
* A dock widget title bar that shows a title and an icon
|
||||
* A dock widget tab that shows a title and an icon.
|
||||
* The dock widget tab is shown in the dock area title bar to switch between
|
||||
* tabbed dock widgets
|
||||
*/
|
||||
class CDockWidgetTitleBar : public QFrame
|
||||
class ADS_EXPORT CDockWidgetTab : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool activeTab READ isActiveTab WRITE setActiveTab NOTIFY activeTabChanged)
|
||||
|
||||
private:
|
||||
DockWidgetTitleBarPrivate* d; ///< private data (pimpl)
|
||||
friend class DockWidgetTitleBarPrivate;
|
||||
DockWidgetTabPrivate* d; ///< private data (pimpl)
|
||||
friend struct DockWidgetTabPrivate;
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent* ev) override;
|
||||
@@ -61,12 +65,12 @@ public:
|
||||
* param[in] DockWidget The dock widget this title bar belongs to
|
||||
* param[in] parent The parent widget of this title bar
|
||||
*/
|
||||
CDockWidgetTitleBar(CDockWidget* DockWidget, QWidget* parent = 0);
|
||||
CDockWidgetTab(CDockWidget* DockWidget, QWidget* parent = 0);
|
||||
|
||||
/**
|
||||
* Virtual Destructor
|
||||
*/
|
||||
virtual ~CDockWidgetTitleBar();
|
||||
virtual ~CDockWidgetTab();
|
||||
|
||||
/**
|
||||
* Returns true, if this is the active tab
|
||||
@@ -96,11 +100,21 @@ public:
|
||||
*/
|
||||
CDockAreaWidget* dockAreaWidget() const;
|
||||
|
||||
/**
|
||||
* Sets the icon to show in title bar
|
||||
*/
|
||||
void setIcon(const QIcon& Icon);
|
||||
|
||||
/**
|
||||
* Returns the icon
|
||||
*/
|
||||
const QIcon& icon() const;
|
||||
|
||||
signals:
|
||||
void activeTabChanged();
|
||||
void clicked();
|
||||
}; // class DockWidgetTitleBar
|
||||
}; // class DockWidgetTab
|
||||
}
|
||||
// namespace ads
|
||||
//-----------------------------------------------------------------------------
|
||||
#endif // DockWidgetTitleBarH
|
||||
#endif // DockWidgetTabH
|
||||
@@ -59,6 +59,7 @@ struct FloatingDockContainerPrivate
|
||||
unsigned int zOrderIndex = ++zOrderCounter;
|
||||
QPointer<CDockManager> DockManager;
|
||||
bool DraggingActive = false;
|
||||
bool NonClientAreaMouseButtonPress = false;
|
||||
QPoint DragStartMousePosition;
|
||||
CDockContainerWidget* DropContainer = nullptr;
|
||||
CDockAreaWidget* SingleDockArea = nullptr;
|
||||
@@ -92,19 +93,24 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent()
|
||||
return;
|
||||
}
|
||||
|
||||
// Resize the floating widget to the size of the highlighted drop area
|
||||
// rectangle
|
||||
QRect Rect = DockManager->containerOverlay()->dropOverlayRect();
|
||||
if (!Rect.isValid())
|
||||
if (DockManager->dockAreaOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea
|
||||
|| DockManager->containerOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea)
|
||||
{
|
||||
Rect = DockManager->dockAreaOverlay()->rect();
|
||||
// Resize the floating widget to the size of the highlighted drop area
|
||||
// rectangle
|
||||
QRect Rect = DockManager->containerOverlay()->dropOverlayRect();
|
||||
if (!Rect.isValid())
|
||||
{
|
||||
Rect = DockManager->dockAreaOverlay()->rect();
|
||||
}
|
||||
|
||||
if (Rect.isValid())
|
||||
{
|
||||
_this->resize(Rect.size());
|
||||
}
|
||||
DropContainer->dropFloatingWidget(_this, QCursor::pos());
|
||||
}
|
||||
|
||||
if (Rect.isValid())
|
||||
{
|
||||
_this->resize(Rect.size());
|
||||
}
|
||||
DropContainer->dropFloatingWidget(_this, QCursor::pos());
|
||||
DockManager->containerOverlay()->hideOverlay();
|
||||
DockManager->dockAreaOverlay()->hideOverlay();
|
||||
}
|
||||
@@ -157,15 +163,29 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos)
|
||||
int VisibleDockAreas = TopContainer->visibleDockAreaCount();
|
||||
ContainerOverlay->setAllowedAreas(VisibleDockAreas > 1 ?
|
||||
OuterDockAreas : AllDockAreas);
|
||||
ContainerOverlay->showOverlay(TopContainer);
|
||||
DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer);
|
||||
|
||||
auto DockArea = TopContainer->dockAreaAt(GlobalPos);
|
||||
if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0)
|
||||
{
|
||||
DockAreaOverlay->enableDropPreview(true);
|
||||
DockAreaOverlay->setAllowedAreas((VisibleDockAreas == 1) ?
|
||||
NoDockWidgetArea : AllDockAreas);
|
||||
DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea);
|
||||
ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area);
|
||||
|
||||
// A CenterDockWidgetArea for the dockAreaOverlay() indicates that
|
||||
// the mouse is in the title bar. If the ContainerArea is valid
|
||||
// then we ignore the dock area of the dockAreaOverlay() and disable
|
||||
// the drop preview
|
||||
if ((Area == CenterDockWidgetArea) && (ContainerArea != InvalidDockWidgetArea))
|
||||
{
|
||||
DockAreaOverlay->enableDropPreview(false);
|
||||
ContainerOverlay->enableDropPreview(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -178,6 +198,10 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos)
|
||||
void FloatingDockContainerPrivate::setDraggingActive(bool Active)
|
||||
{
|
||||
DraggingActive = Active;
|
||||
if (!DraggingActive)
|
||||
{
|
||||
NonClientAreaMouseButtonPress = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -186,7 +210,6 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager* DockManager) :
|
||||
QWidget(DockManager, Qt::Window),
|
||||
d(new FloatingDockContainerPrivate(this))
|
||||
{
|
||||
//setAttribute(Qt::WA_DeleteOnClose);
|
||||
d->DockManager = DockManager;
|
||||
QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
|
||||
l->setContentsMargins(0, 0, 0, 0);
|
||||
@@ -276,15 +299,20 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event)
|
||||
//============================================================================
|
||||
void CFloatingDockContainer::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
qDebug() << "CFloatingDockContainer closeEvent";
|
||||
d->setDraggingActive(false);
|
||||
QWidget::closeEvent(event);
|
||||
|
||||
if (isClosable())
|
||||
QWidget::closeEvent(event);
|
||||
else
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingDockContainer::hideEvent(QHideEvent *event)
|
||||
{
|
||||
qDebug() << "CFloatingDockContainer hideEvent";
|
||||
QWidget::hideEvent(event);
|
||||
auto OpenDockAreas = d->DockContainer->openedDockAreas();
|
||||
for (auto DockArea : OpenDockAreas)
|
||||
@@ -292,7 +320,7 @@ void CFloatingDockContainer::hideEvent(QHideEvent *event)
|
||||
auto OpenDockWidgets = DockArea->openedDockWidgets();
|
||||
for (auto DockWidget : OpenDockWidgets)
|
||||
{
|
||||
DockWidget->setToggleViewActionChecked(false);
|
||||
DockWidget->toggleView(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -317,12 +345,13 @@ void CFloatingDockContainer::showEvent(QShowEvent *event)
|
||||
//============================================================================
|
||||
bool CFloatingDockContainer::event(QEvent *e)
|
||||
{
|
||||
if ((e->type() == QEvent::NonClientAreaMouseButtonPress))
|
||||
if (e->type() == QEvent::NonClientAreaMouseButtonPress)
|
||||
{
|
||||
if (QGuiApplication::mouseButtons() == Qt::LeftButton)
|
||||
{
|
||||
qDebug() << "FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type();
|
||||
d->setDraggingActive(true);
|
||||
d->NonClientAreaMouseButtonPress = true;
|
||||
}
|
||||
}
|
||||
else if (e->type() == QEvent::NonClientAreaMouseButtonDblClick)
|
||||
@@ -335,6 +364,20 @@ bool CFloatingDockContainer::event(QEvent *e)
|
||||
qDebug() << "FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease";
|
||||
d->titleMouseReleaseEvent();
|
||||
}
|
||||
else if (d->NonClientAreaMouseButtonPress && (e->type() == QEvent::Resize))
|
||||
{
|
||||
// If user resizes the floating widget, we do not want to show any
|
||||
// drop overlays or drop overlay icons. If the window is maximized,
|
||||
// then dragging the window via title bar will cause the widget to
|
||||
// leave the maximized state. This in turn will trigger a resize event.
|
||||
// To know, if the resize event was triggered by user via moving a
|
||||
// corner of the window frame or if it was caused by a windows state
|
||||
// change, we check, if we are not in maximized state.
|
||||
if (!isMaximized())
|
||||
{
|
||||
d->setDraggingActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
return QWidget::event(e);
|
||||
}
|
||||
@@ -375,6 +418,25 @@ void CFloatingDockContainer::moveFloating()
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool CFloatingDockContainer::isClosable() const
|
||||
{
|
||||
auto OpenDockAreas = d->DockContainer->openedDockAreas();
|
||||
for (auto DockArea : OpenDockAreas)
|
||||
{
|
||||
auto OpenDockWidgets = DockArea->openedDockWidgets();
|
||||
for (auto DockWidget : OpenDockWidgets)
|
||||
{
|
||||
if (!DockWidget->features().testFlag(CDockWidget::DockWidgetClosable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingDockContainer::onDockAreasAddedOrRemoved()
|
||||
{
|
||||
@@ -408,7 +470,7 @@ void CFloatingDockContainer::onDockAreaCurrentChanged(int Index)
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool CFloatingDockContainer::restoreState(QDataStream& Stream, bool Testing)
|
||||
bool CFloatingDockContainer::restoreState(QXmlStreamReader& Stream, bool Testing)
|
||||
{
|
||||
if (!d->DockContainer->restoreState(Stream, Testing))
|
||||
{
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
/*******************************************************************************
|
||||
** Qt Advanced Docking System
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU Lesser General Public
|
||||
** License as published by the Free Software Foundation; either
|
||||
** version 2.1 of the License, or (at your option) any later version.
|
||||
**
|
||||
**
|
||||
** This library 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
|
||||
** Lesser General Public License for more details.
|
||||
**
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser General Public
|
||||
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
@@ -31,30 +31,66 @@
|
||||
//============================================================================
|
||||
#include <QWidget>
|
||||
|
||||
#include "ads_globals.h"
|
||||
|
||||
class QXmlStreamReader;
|
||||
|
||||
namespace ads
|
||||
{
|
||||
struct FloatingDockContainerPrivate;
|
||||
class CDockManager;
|
||||
struct DockManagerPrivate;
|
||||
class CDockAreaWidget;
|
||||
class CDockContainerWidget;
|
||||
class CDockWidget;
|
||||
class CDockManager;
|
||||
class CDockAreaTabBar;
|
||||
class CDockWidgetTab;
|
||||
struct DockWidgetTabPrivate;
|
||||
|
||||
/**
|
||||
* This implements a floating widget that is a dock container that accepts
|
||||
* docking of dock widgets like the main window and that can be docked into
|
||||
* another dock container
|
||||
*/
|
||||
class CFloatingDockContainer : public QWidget
|
||||
class ADS_EXPORT CFloatingDockContainer : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
FloatingDockContainerPrivate* d; ///< private data (pimpl)
|
||||
friend class FloatingDockContainerPrivate;
|
||||
friend struct FloatingDockContainerPrivate;
|
||||
friend class CDockManager;
|
||||
friend struct DockManagerPrivate;
|
||||
friend class CDockAreaTabBar;
|
||||
friend struct DockWidgetTabPrivate;
|
||||
friend class CDockWidgetTab;
|
||||
|
||||
private slots:
|
||||
void onDockAreasAddedOrRemoved();
|
||||
void onDockAreaCurrentChanged(int Index);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Starts floating at the given global position.
|
||||
* Use moveToGlobalPos() to move the widget to a new position
|
||||
* depending on the start position given in Pos parameter
|
||||
*/
|
||||
void startFloating(const QPoint& Pos, const QSize& Size = QSize());
|
||||
|
||||
/**
|
||||
* Moves the widget to a new position relative to the position given when
|
||||
* startFloating() was called
|
||||
*/
|
||||
void moveFloating();
|
||||
|
||||
/**
|
||||
* Restores the state from given stream.
|
||||
* If Testing is true, the function only parses the data from the given
|
||||
* stream but does not restore anything. You can use this check for
|
||||
* faulty files before you start restoring the state
|
||||
*/
|
||||
bool restoreState(QXmlStreamReader& Stream, bool Testing);
|
||||
|
||||
|
||||
protected: // reimplements QWidget
|
||||
virtual void changeEvent(QEvent *event) override;
|
||||
@@ -92,25 +128,10 @@ public:
|
||||
CDockContainerWidget* dockContainer() const;
|
||||
|
||||
/**
|
||||
* Starts floating at the given global position.
|
||||
* Use moveToGlobalPos() to move the widget to a new position
|
||||
* depending on the start position given in Pos parameter
|
||||
* This function returns true, if it can be closed.
|
||||
* It can be closed, if all dock widgets in all dock areas can be closed
|
||||
*/
|
||||
void startFloating(const QPoint& Pos, const QSize& Size = QSize());
|
||||
|
||||
/**
|
||||
* Moves the widget to a new position relative to the position given when
|
||||
* startFloating() was called
|
||||
*/
|
||||
void moveFloating();
|
||||
|
||||
/**
|
||||
* Restores the state from given stream.
|
||||
* If Testing is true, the function only parses the data from the given
|
||||
* stream but does not restore anything. You can use this check for
|
||||
* faulty files before you start restoring the state
|
||||
*/
|
||||
bool restoreState(QDataStream& Stream, bool Testing);
|
||||
bool isClosable() const;
|
||||
}; // class FloatingDockContainer
|
||||
}
|
||||
// namespace ads
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*******************************************************************************
|
||||
** Qt Advanced Docking System
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU Lesser General Public
|
||||
** License as published by the Free Software Foundation; either
|
||||
** version 2.1 of the License, or (at your option) any later version.
|
||||
**
|
||||
**
|
||||
** This library 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
|
||||
** Lesser General Public License for more details.
|
||||
**
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser General Public
|
||||
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
@@ -62,12 +62,12 @@ CDockInsertParam dockAreaInsertParameters(DockWidgetArea Area)
|
||||
{
|
||||
switch (Area)
|
||||
{
|
||||
case TopDockWidgetArea: return QPair<Qt::Orientation, bool>(Qt::Vertical, false);
|
||||
case RightDockWidgetArea: return QPair<Qt::Orientation, bool>(Qt::Horizontal, true);
|
||||
case TopDockWidgetArea: return CDockInsertParam(Qt::Vertical, false);
|
||||
case RightDockWidgetArea: return CDockInsertParam(Qt::Horizontal, true);
|
||||
case CenterDockWidgetArea:
|
||||
case BottomDockWidgetArea: return QPair<Qt::Orientation, bool>(Qt::Vertical, true);
|
||||
case LeftDockWidgetArea: return QPair<Qt::Orientation, bool>(Qt::Horizontal, false);
|
||||
default: QPair<Qt::Orientation, bool>(Qt::Vertical, false);
|
||||
case BottomDockWidgetArea: return CDockInsertParam(Qt::Vertical, true);
|
||||
case LeftDockWidgetArea: return CDockInsertParam(Qt::Horizontal, false);
|
||||
default: CDockInsertParam(Qt::Vertical, false);
|
||||
} // switch (Area)
|
||||
|
||||
return CDockInsertParam(Qt::Vertical, false);
|
||||
|
||||
@@ -31,6 +31,13 @@
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include <QPair>
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
#ifdef ADS_SHARED_EXPORT
|
||||
#define ADS_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
#define ADS_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
class QSplitter;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ CONFIG += adsBuildShared
|
||||
|
||||
adsBuildShared {
|
||||
CONFIG += shared
|
||||
DEFINES += ADS_EXPORT
|
||||
DEFINES += ADS_SHARED_EXPORT
|
||||
}
|
||||
!adsBuildShared {
|
||||
CONFIG += staticlib
|
||||
@@ -33,10 +33,11 @@ RESOURCES += ads.qrc
|
||||
HEADERS += \
|
||||
ads_globals.h \
|
||||
DockAreaWidget.h \
|
||||
DockAreaTabBar.h \
|
||||
DockContainerWidget.h \
|
||||
DockManager.h \
|
||||
DockWidget.h \
|
||||
DockWidgetTitleBar.h \
|
||||
DockWidgetTab.h \
|
||||
FloatingDockContainer.h \
|
||||
DockOverlay.h \
|
||||
DockSplitter.h
|
||||
@@ -46,10 +47,11 @@ HEADERS += \
|
||||
SOURCES += \
|
||||
ads_globals.cpp \
|
||||
DockAreaWidget.cpp \
|
||||
DockAreaTabBar.cpp \
|
||||
DockContainerWidget.cpp \
|
||||
DockManager.cpp \
|
||||
DockWidget.cpp \
|
||||
DockWidgetTitleBar.cpp \
|
||||
DockWidgetTab.cpp \
|
||||
FloatingDockContainer.cpp \
|
||||
DockOverlay.cpp \
|
||||
DockSplitter.cpp
|
||||
|
||||
@@ -25,7 +25,7 @@ ads--CDockAreaWidget #tabsMenuButton::menu-indicator
|
||||
image: none;
|
||||
}
|
||||
|
||||
ads--CDockWidgetTitleBar
|
||||
ads--CDockWidgetTab
|
||||
{
|
||||
background: palette(window);
|
||||
border-color: palette(light);
|
||||
@@ -34,17 +34,17 @@ ads--CDockWidgetTitleBar
|
||||
padding: 0 9px;
|
||||
}
|
||||
|
||||
ads--CDockWidgetTitleBar[activeTab="true"]
|
||||
ads--CDockWidgetTab[activeTab="true"]
|
||||
{
|
||||
background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:0.5, stop:0 palette(window), stop:1 palette(light));
|
||||
}
|
||||
|
||||
ads--CDockWidgetTitleBar QLabel
|
||||
ads--CDockWidgetTab QLabel
|
||||
{
|
||||
color: palette(dark);
|
||||
}
|
||||
|
||||
ads--CDockWidgetTitleBar[activeTab="true"] QLabel
|
||||
ads--CDockWidgetTab[activeTab="true"] QLabel
|
||||
{
|
||||
color: palette(foreground);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user