mirror of
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
synced 2024-12-24 23:31:32 +08:00
Refactoring of project structure
This commit is contained in:
parent
c57d14d0d7
commit
97571e4be8
@ -1,2 +0,0 @@
|
||||
|
||||
|
@ -1,62 +0,0 @@
|
||||
include($$(cetoni_repository)/build/qt/qtprojectsettings/shared_library.pri)
|
||||
include(src/v2/v2.pri)
|
||||
|
||||
TARGET = $$qtLibraryTarget(AdvancedDockingSystem)
|
||||
TEMPLATE = lib
|
||||
#VERSION = 1.0.0
|
||||
|
||||
CONFIG += adsBuildShared
|
||||
|
||||
QT += core gui
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
greaterThan(QT_MAJOR_VERSION, 4): DEFINES += ADS_NAMESPACE_ENABLED
|
||||
|
||||
adsBuildShared {
|
||||
CONFIG += shared
|
||||
DEFINES += ADS_EXPORT
|
||||
}
|
||||
!adsBuildShared {
|
||||
CONFIG += staticlib
|
||||
}
|
||||
|
||||
INCLUDEPATH += $$PWD/include
|
||||
|
||||
windows {
|
||||
# MinGW
|
||||
*-g++* {
|
||||
QMAKE_CXXFLAGS += -std=c++11
|
||||
QMAKE_CXXFLAGS += -Wall -Wextra -pedantic
|
||||
}
|
||||
# MSVC
|
||||
*-msvc* {
|
||||
}
|
||||
}
|
||||
|
||||
RESOURCES += \
|
||||
res/ads.qrc
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/src/API.cpp \
|
||||
$$PWD/src/MainContainerWidget.cpp \
|
||||
$$PWD/src/SectionWidget.cpp \
|
||||
$$PWD/src/SectionContent.cpp \
|
||||
$$PWD/src/SectionTitleWidget.cpp \
|
||||
$$PWD/src/SectionContentWidget.cpp \
|
||||
$$PWD/src/DropOverlay.cpp \
|
||||
$$PWD/src/FloatingWidget.cpp \
|
||||
$$PWD/src/Internal.cpp \
|
||||
$$PWD/src/Serialization.cpp \
|
||||
$$PWD/src/ContainerWidget.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/src/API.h \
|
||||
$$PWD/src/MainContainerWidget.h \
|
||||
$$PWD/src/SectionWidget.h \
|
||||
$$PWD/src/SectionContent.h \
|
||||
$$PWD/src/SectionTitleWidget.h \
|
||||
$$PWD/src/SectionContentWidget.h \
|
||||
$$PWD/src/DropOverlay.h \
|
||||
$$PWD/src/FloatingWidget.h \
|
||||
$$PWD/src/Internal.h \
|
||||
$$PWD/src/Serialization.h \
|
||||
$$PWD/src/ContainerWidget.h
|
@ -1,112 +0,0 @@
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#include "MainContainerWidget.h"
|
||||
#include "API.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QSplitter>
|
||||
#include <QLayout>
|
||||
#include <QVariant>
|
||||
|
||||
#include "SectionWidget.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
static bool splitterContainsSectionWidget(QSplitter* splitter)
|
||||
{
|
||||
for (int i = 0; i < splitter->count(); ++i)
|
||||
{
|
||||
QWidget* w = splitter->widget(i);
|
||||
QSplitter* sp = qobject_cast<QSplitter*>(w);
|
||||
SectionWidget* sw = NULL;
|
||||
if (sp && splitterContainsSectionWidget(sp))
|
||||
return true;
|
||||
else if ((sw = qobject_cast<SectionWidget*>(w)) != NULL)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void deleteEmptySplitter(CMainContainerWidget* container)
|
||||
{
|
||||
bool doAgain = false;
|
||||
do
|
||||
{
|
||||
doAgain = false;
|
||||
QList<QSplitter*> splitters = container->findChildren<QSplitter*>();
|
||||
for (int i = 0; i < splitters.count(); ++i)
|
||||
{
|
||||
QSplitter* sp = splitters.at(i);
|
||||
if (!sp->property("ads-splitter").toBool())
|
||||
continue;
|
||||
if (sp->count() > 0 && splitterContainsSectionWidget(sp))
|
||||
continue;
|
||||
delete splitters[i];
|
||||
doAgain = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (doAgain);
|
||||
}
|
||||
|
||||
|
||||
QSplitter* findParentSplitter(QWidget* w)
|
||||
{
|
||||
QSplitter* splitter = 0;
|
||||
QWidget* parentWidget = w;
|
||||
do
|
||||
{
|
||||
if ((splitter = dynamic_cast<QSplitter*>(parentWidget)) != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
parentWidget = parentWidget->parentWidget();
|
||||
}
|
||||
while (parentWidget);
|
||||
return splitter;
|
||||
}
|
||||
|
||||
|
||||
QSplitter* findImmediateSplitter(QWidget* w)
|
||||
{
|
||||
QLayout* l = w->layout();
|
||||
if (!l || l->count() <= 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QSplitter* sp = nullptr;
|
||||
for (int i = 0; i < l->count(); ++i)
|
||||
{
|
||||
QLayoutItem* li = l->itemAt(0);
|
||||
if (!li->widget())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ((sp = dynamic_cast<QSplitter*>(li->widget())) != nullptr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sp;
|
||||
}
|
||||
|
||||
} // namespace ads
|
@ -1,71 +0,0 @@
|
||||
#ifndef ADS_API_H
|
||||
#define ADS_API_H
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include <QFlags>
|
||||
class QWidget;
|
||||
class QSplitter;
|
||||
|
||||
// DLL Export API
|
||||
#ifdef _WIN32
|
||||
#if defined(ADS_IMPORT)
|
||||
#define ADS_EXPORT_API
|
||||
#elif defined(ADS_EXPORT)
|
||||
#define ADS_EXPORT_API __declspec(dllexport)
|
||||
#else
|
||||
#define ADS_EXPORT_API __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define ADS_EXPORT_API
|
||||
#endif
|
||||
|
||||
|
||||
// Beautiful C++ stuff.
|
||||
#define ADS_Expects(cond)
|
||||
#define ADS_Ensures(cond)
|
||||
|
||||
// Indicates whether ADS should include animations.
|
||||
//#define ADS_ANIMATIONS_ENABLED 1
|
||||
//#define ADS_ANIMATION_DURATION 150
|
||||
|
||||
namespace ads
|
||||
{
|
||||
class CMainContainerWidget;
|
||||
class SectionWidget;
|
||||
|
||||
enum DropArea
|
||||
{
|
||||
InvalidDropArea = 0,
|
||||
TopDropArea = 1,
|
||||
RightDropArea = 2,
|
||||
BottomDropArea = 4,
|
||||
LeftDropArea = 8,
|
||||
CenterDropArea = 16,
|
||||
|
||||
OuterAreas = TopDropArea | RightDropArea | BottomDropArea | LeftDropArea,
|
||||
AllAreas = OuterAreas | CenterDropArea
|
||||
};
|
||||
Q_DECLARE_FLAGS(DropAreas, DropArea)
|
||||
|
||||
void deleteEmptySplitter(CMainContainerWidget* container);
|
||||
QSplitter* findParentSplitter(QWidget* w);
|
||||
QSplitter* findImmediateSplitter(QWidget* w);
|
||||
|
||||
} // namespace ads
|
||||
#endif
|
@ -1,560 +0,0 @@
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include "MainContainerWidget.h"
|
||||
#include "SectionContentWidget.h"
|
||||
#include "ContainerWidget.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPaintEvent>
|
||||
#include <QPainter>
|
||||
#include <QContextMenuEvent>
|
||||
#include <QMenu>
|
||||
#include <QSplitter>
|
||||
#include <QDataStream>
|
||||
#include <QtGlobal>
|
||||
#include <QGridLayout>
|
||||
#include <QPoint>
|
||||
#include <QApplication>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "Internal.h"
|
||||
#include "SectionWidget.h"
|
||||
#include "SectionTitleWidget.h"
|
||||
#include "DropOverlay.h"
|
||||
#include "Serialization.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
unsigned int CContainerWidget::zOrderCounter = 0;
|
||||
|
||||
//============================================================================
|
||||
CContainerWidget::CContainerWidget(CMainContainerWidget* MainContainer, QWidget *parent)
|
||||
: QFrame(parent),
|
||||
m_MainContainerWidget(MainContainer)
|
||||
{
|
||||
m_MainLayout = new QGridLayout();
|
||||
m_MainLayout->setContentsMargins(0, 1, 0, 0);
|
||||
m_MainLayout->setSpacing(0);
|
||||
setLayout(m_MainLayout);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
CContainerWidget::~CContainerWidget()
|
||||
{
|
||||
std::cout << "CContainerWidget::~CContainerWidget()" << std::endl;
|
||||
m_MainContainerWidget->m_Containers.removeAll(this);
|
||||
}
|
||||
|
||||
|
||||
bool CContainerWidget::event(QEvent *e)
|
||||
{
|
||||
bool Result = QWidget::event(e);
|
||||
if (e->type() == QEvent::WindowActivate)
|
||||
{
|
||||
m_zOrderIndex = ++zOrderCounter;
|
||||
}
|
||||
else if (e->type() == QEvent::Show && !m_zOrderIndex)
|
||||
{
|
||||
m_zOrderIndex = ++zOrderCounter;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
unsigned int CContainerWidget::zOrderIndex() const
|
||||
{
|
||||
return m_zOrderIndex;
|
||||
}
|
||||
|
||||
void CContainerWidget::dropFloatingWidget(FloatingWidget* FloatingWidget,
|
||||
const QPoint& TargetPos)
|
||||
{
|
||||
SectionWidget* sectionWidget = sectionWidgetAt(TargetPos);
|
||||
DropArea dropArea = InvalidDropArea;
|
||||
if (sectionWidget)
|
||||
{
|
||||
auto dropOverlay = m_MainContainerWidget->sectionDropOverlay();
|
||||
dropOverlay->setAllowedAreas(AllAreas);
|
||||
dropArea = dropOverlay->showDropOverlay(sectionWidget);
|
||||
if (dropArea != InvalidDropArea)
|
||||
{
|
||||
std::cout << "Section Drop Content: " << dropArea << std::endl;
|
||||
/*InternalContentData data;
|
||||
FloatingWidget->takeContent(data);
|
||||
FloatingWidget->deleteLater();
|
||||
dropContent(data, sectionWidget, dropArea, true);*/
|
||||
dropIntoSection(FloatingWidget, sectionWidget, dropArea);
|
||||
}
|
||||
}
|
||||
|
||||
// mouse is over container
|
||||
if (InvalidDropArea == dropArea)
|
||||
{
|
||||
dropArea = m_MainContainerWidget->dropOverlay()->dropAreaUnderCursor();
|
||||
std::cout << "Container Drop Content: " << dropArea << std::endl;
|
||||
if (dropArea != InvalidDropArea)
|
||||
{
|
||||
// drop content
|
||||
dropIntoContainer(FloatingWidget, dropArea);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CContainerWidget::dropIntoContainer(FloatingWidget* FloatingWidget, DropArea area)
|
||||
{
|
||||
CContainerWidget* FloatingContainer = FloatingWidget->containerWidget();
|
||||
QSplitter* FloatingMainSplitter = FloatingContainer->findChild<QSplitter*>(QString(), Qt::FindDirectChildrenOnly);
|
||||
|
||||
//QSplitter* oldsp = findImmediateSplitter(this);
|
||||
// We use findChild here instead of findImmediateSplitter because I do not
|
||||
// know what the advantage of the findImmediateSplitter function is
|
||||
QSplitter* OldSplitter = this->findChild<QSplitter*>(QString(), Qt::FindDirectChildrenOnly);
|
||||
//auto SectionWidgets = FloatingMainSplitter->findChildren<SectionWidget*>(QString(), Qt::FindDirectChildrenOnly);
|
||||
QList<SectionWidget*> SectionWidgets;
|
||||
for (int i = 0; i < FloatingMainSplitter->count(); ++i)
|
||||
{
|
||||
SectionWidgets.append(static_cast<SectionWidget*>(FloatingMainSplitter->widget(i)));
|
||||
}
|
||||
|
||||
std::cout << "SectionWIdget[0] " << SectionWidgets[0] << " FloatingSplitter index 0"
|
||||
<< FloatingMainSplitter->widget(0) << std::endl;
|
||||
//std::cout<< "oldsp " << oldsp << " oldsp2 " << oldsp2 << std::endl;
|
||||
|
||||
Qt::Orientation orientation;
|
||||
bool append;
|
||||
|
||||
switch (area)
|
||||
{
|
||||
case TopDropArea: orientation = Qt::Vertical; append = false; break;
|
||||
case RightDropArea: orientation = Qt::Horizontal; append = true; break;
|
||||
case CenterDropArea:
|
||||
case BottomDropArea: orientation = Qt::Vertical; append = true; break;
|
||||
case LeftDropArea: orientation = Qt::Horizontal; append = false; break;
|
||||
}
|
||||
|
||||
auto l = m_MainLayout;
|
||||
|
||||
if (!OldSplitter)
|
||||
{
|
||||
std::cout << "Create new splitter" << std::endl;
|
||||
// we have no splitter yet - let us create one
|
||||
QSplitter* sp = CMainContainerWidget::newSplitter(FloatingMainSplitter->orientation());
|
||||
if (l->count() > 0)
|
||||
{
|
||||
qWarning() << "Still items in layout. This should never happen.";
|
||||
QLayoutItem* li = l->takeAt(0);
|
||||
delete li;
|
||||
}
|
||||
l->addWidget(sp);
|
||||
for (auto SectionWidget : SectionWidgets)
|
||||
{
|
||||
sp->addWidget(SectionWidget);
|
||||
}
|
||||
}
|
||||
else if ((FloatingMainSplitter->orientation() == orientation || FloatingMainSplitter->count() == 1) &&
|
||||
(OldSplitter->count() == 1 || OldSplitter->orientation() == orientation))
|
||||
{
|
||||
OldSplitter->setOrientation(orientation);
|
||||
std::cout << "Splitter with right orientation" << std::endl;
|
||||
// we have a splitter with only one item or with the right orientation so
|
||||
// we can make it match the orientation of the floating splitter
|
||||
for (int i = 0; i < SectionWidgets.count(); ++i)
|
||||
{
|
||||
if (append)
|
||||
{
|
||||
OldSplitter->addWidget(SectionWidgets[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
OldSplitter->insertWidget(i, SectionWidgets[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Splitter with wrong orientation" << std::endl;
|
||||
// we have a splitter but with the wrong orientation
|
||||
QSplitter* sp = CMainContainerWidget::newSplitter(orientation);
|
||||
if (append)
|
||||
{
|
||||
QLayoutItem* li = l->replaceWidget(OldSplitter, sp);
|
||||
sp->addWidget(OldSplitter);
|
||||
sp->addWidget(FloatingMainSplitter);
|
||||
delete li;
|
||||
}
|
||||
else
|
||||
{
|
||||
sp->addWidget(FloatingMainSplitter);
|
||||
QLayoutItem* li = l->replaceWidget(OldSplitter, sp);
|
||||
sp->addWidget(OldSplitter);
|
||||
delete li;
|
||||
}
|
||||
}
|
||||
|
||||
m_Sections.append(SectionWidgets);
|
||||
FloatingWidget->deleteLater();
|
||||
}
|
||||
|
||||
|
||||
void CContainerWidget::dropIntoSection(FloatingWidget* FloatingWidget,
|
||||
SectionWidget* targetSection, DropArea area)
|
||||
{
|
||||
CContainerWidget* FloatingContainer = FloatingWidget->containerWidget();
|
||||
QSplitter* FloatingMainSplitter = FloatingContainer->findChild<QSplitter*>(QString(),
|
||||
Qt::FindDirectChildrenOnly);
|
||||
QList<SectionWidget*> SectionWidgets;
|
||||
for (int i = 0; i < FloatingMainSplitter->count(); ++i)
|
||||
{
|
||||
SectionWidgets.append(static_cast<SectionWidget*>(FloatingMainSplitter->widget(i)));
|
||||
}
|
||||
|
||||
Qt::Orientation Orientation;
|
||||
int InsertIndexOffset;
|
||||
switch (area)
|
||||
{
|
||||
case TopDropArea: Orientation = Qt::Vertical; InsertIndexOffset = 0;break;
|
||||
case RightDropArea: Orientation = Qt::Horizontal; InsertIndexOffset = 1;break;
|
||||
case BottomDropArea: Orientation = Qt::Vertical; InsertIndexOffset = 1;break;
|
||||
case LeftDropArea: Orientation = Qt::Horizontal; InsertIndexOffset = 0;break;
|
||||
|
||||
case CenterDropArea:
|
||||
{
|
||||
QList<SectionWidget*> SectionWidgets = FloatingContainer->findChildren<SectionWidget*>(QString(), Qt::FindChildrenRecursively);
|
||||
for (auto SectionWidget : SectionWidgets)
|
||||
{
|
||||
std::cout << "dropping into section CenterDropArea " << SectionWidget->contentCount() << std::endl;
|
||||
while (SectionWidget->contentCount())
|
||||
{
|
||||
InternalContentData data;
|
||||
if (!SectionWidget->takeContentAt(0, data))
|
||||
{
|
||||
qWarning() << "THIS SHOULD NOT HAPPEN!! " << 0;
|
||||
return;
|
||||
}
|
||||
targetSection->addContent(data, false);
|
||||
}
|
||||
}
|
||||
FloatingWidget->deleteLater();
|
||||
}
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QSplitter* targetSectionSplitter = findParentSplitter(targetSection);
|
||||
std::cout << "target->orientaton " << targetSectionSplitter->orientation()
|
||||
<< " orien " << Orientation << std::endl;
|
||||
int index = targetSectionSplitter->indexOf(targetSection);
|
||||
std::cout << "targetSectionSplitter->indexOf(targetSection) " << index << std::endl;
|
||||
if (targetSectionSplitter->orientation() == Orientation)
|
||||
{
|
||||
std::cout << "targetSectionSplitter->orientation() == Orientation" << std::endl;
|
||||
if (FloatingMainSplitter->orientation() == Orientation || FloatingMainSplitter->count() == 1)
|
||||
{
|
||||
std::cout << "FloatingMainSplitter->orientation() == Orientation || FloatingMainSplitter->count() == 1" << std::endl;
|
||||
for (int i = 0; i < SectionWidgets.count(); ++i)
|
||||
{
|
||||
targetSectionSplitter->insertWidget(index + InsertIndexOffset, SectionWidgets[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
targetSectionSplitter->insertWidget(index + InsertIndexOffset, FloatingMainSplitter);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "targetSectionSplitter->orientation() != Orientation" << std::endl;
|
||||
QSplitter* s = CMainContainerWidget::newSplitter(Orientation);
|
||||
if (FloatingMainSplitter->orientation() == Orientation || FloatingMainSplitter->count() == 1)
|
||||
{
|
||||
std::cout << "FloatingMainSplitter->orientation() == Orientation || FloatingMainSplitter->count() == 1" << std::endl;
|
||||
for (int i = 0; i < SectionWidgets.count(); ++i)
|
||||
{
|
||||
s->addWidget(SectionWidgets[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s->addWidget(FloatingMainSplitter);
|
||||
}
|
||||
|
||||
if (!InsertIndexOffset)
|
||||
{
|
||||
s->addWidget(targetSection);
|
||||
}
|
||||
else
|
||||
{
|
||||
s->insertWidget(0, targetSection);
|
||||
}
|
||||
targetSectionSplitter->insertWidget(index, s);
|
||||
}
|
||||
FloatingWidget->deleteLater();
|
||||
m_Sections.append(SectionWidgets);
|
||||
}
|
||||
|
||||
|
||||
|
||||
SectionWidget* CContainerWidget::sectionWidgetAt(const QPoint& pos) const
|
||||
{
|
||||
std::cout << "CContainerWidget::sectionWidgetAt m_Sections count "
|
||||
<< m_Sections.count() << std::endl;
|
||||
for (const auto& SectionWidget : m_Sections)
|
||||
{
|
||||
if (SectionWidget->rect().contains(SectionWidget->mapFromGlobal(pos)))
|
||||
{
|
||||
return SectionWidget;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool CContainerWidget::isInFrontOf(CContainerWidget* Other) const
|
||||
{
|
||||
return this->zOrderIndex() > Other->zOrderIndex();
|
||||
}
|
||||
|
||||
SectionWidget* CContainerWidget::dropContent(const InternalContentData& data, SectionWidget* targetSectionWidget, DropArea area, bool autoActive)
|
||||
{
|
||||
ADS_Expects(targetSection != NULL);
|
||||
|
||||
SectionWidget* section_widget = nullptr;
|
||||
|
||||
// If no sections exists yet, create a default one and always drop into it.
|
||||
if (m_Sections.isEmpty())
|
||||
{
|
||||
targetSectionWidget = newSectionWidget();
|
||||
addSectionWidget(targetSectionWidget);
|
||||
area = CenterDropArea;
|
||||
}
|
||||
|
||||
// Drop on outer area
|
||||
if (!targetSectionWidget)
|
||||
{
|
||||
switch (area)
|
||||
{
|
||||
case TopDropArea:return dropContentOuterHelper(m_MainLayout, data, Qt::Vertical, false);
|
||||
case RightDropArea: return dropContentOuterHelper(m_MainLayout, data, Qt::Horizontal, true);
|
||||
case CenterDropArea:
|
||||
case BottomDropArea:return dropContentOuterHelper(m_MainLayout, data, Qt::Vertical, true);
|
||||
case LeftDropArea: return dropContentOuterHelper(m_MainLayout, data, Qt::Horizontal, false);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
return section_widget;
|
||||
}
|
||||
|
||||
// Drop logic based on area.
|
||||
switch (area)
|
||||
{
|
||||
case TopDropArea:return insertNewSectionWidget(data, targetSectionWidget, section_widget, Qt::Vertical, 0);
|
||||
case RightDropArea: return insertNewSectionWidget(data, targetSectionWidget, section_widget, Qt::Horizontal, 1);
|
||||
case BottomDropArea: return insertNewSectionWidget(data, targetSectionWidget, section_widget, Qt::Vertical, 1);
|
||||
case LeftDropArea: return insertNewSectionWidget(data, targetSectionWidget, section_widget, Qt::Horizontal, 0);
|
||||
case CenterDropArea:
|
||||
targetSectionWidget->addContent(data, autoActive);
|
||||
return targetSectionWidget;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return section_widget;
|
||||
}
|
||||
|
||||
|
||||
SectionWidget* CContainerWidget::newSectionWidget()
|
||||
{
|
||||
SectionWidget* sw = new SectionWidget(m_MainContainerWidget, this);
|
||||
m_Sections.append(sw);
|
||||
return sw;
|
||||
}
|
||||
|
||||
void CContainerWidget::addSectionWidget(SectionWidget* section)
|
||||
{
|
||||
ADS_Expects(section != NULL);
|
||||
|
||||
if (section->containerWidget())
|
||||
{
|
||||
section->containerWidget()->takeSection(section);
|
||||
}
|
||||
|
||||
// Create default splitter.
|
||||
if (!m_Splitter)
|
||||
{
|
||||
m_Splitter = CMainContainerWidget::newSplitter(m_Orientation);
|
||||
m_MainLayout->addWidget(m_Splitter, 0, 0);
|
||||
}
|
||||
if (m_Splitter->indexOf(section) != -1)
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO << QString("Section has already been added");
|
||||
return;
|
||||
}
|
||||
m_Splitter->addWidget(section);
|
||||
m_Sections.append(section);
|
||||
}
|
||||
|
||||
|
||||
void CContainerWidget::takeSection(SectionWidget* Widget)
|
||||
{
|
||||
m_Sections.removeAll(Widget);
|
||||
}
|
||||
|
||||
SectionWidget* CContainerWidget::dropContentOuterHelper(QLayout* l, const InternalContentData& data, Qt::Orientation orientation, bool append)
|
||||
{
|
||||
ADS_Expects(l != NULL);
|
||||
|
||||
SectionWidget* sw = newSectionWidget();
|
||||
sw->addContent(data, true);
|
||||
|
||||
QSplitter* oldsp = findImmediateSplitter(this);
|
||||
if (!oldsp)
|
||||
{
|
||||
QSplitter* sp = CMainContainerWidget::newSplitter(orientation);
|
||||
if (l->count() > 0)
|
||||
{
|
||||
qWarning() << "Still items in layout. This should never happen.";
|
||||
QLayoutItem* li = l->takeAt(0);
|
||||
delete li;
|
||||
}
|
||||
l->addWidget(sp);
|
||||
sp->addWidget(sw);
|
||||
}
|
||||
else if (oldsp->orientation() == orientation
|
||||
|| oldsp->count() == 1)
|
||||
{
|
||||
oldsp->setOrientation(orientation);
|
||||
if (append)
|
||||
oldsp->addWidget(sw);
|
||||
else
|
||||
oldsp->insertWidget(0, sw);
|
||||
}
|
||||
else
|
||||
{
|
||||
QSplitter* sp = CMainContainerWidget::newSplitter(orientation);
|
||||
if (append)
|
||||
{
|
||||
QLayoutItem* li = l->replaceWidget(oldsp, sp);
|
||||
sp->addWidget(oldsp);
|
||||
sp->addWidget(sw);
|
||||
delete li;
|
||||
}
|
||||
else
|
||||
{
|
||||
sp->addWidget(sw);
|
||||
QLayoutItem* li = l->replaceWidget(oldsp, sp);
|
||||
sp->addWidget(oldsp);
|
||||
delete li;
|
||||
}
|
||||
}
|
||||
return sw;
|
||||
}
|
||||
|
||||
SectionWidget* CContainerWidget::insertNewSectionWidget(
|
||||
const InternalContentData& data, SectionWidget* targetSection, SectionWidget* ret,
|
||||
Qt::Orientation Orientation, int InsertIndexOffset)
|
||||
{
|
||||
QSplitter* targetSectionSplitter = findParentSplitter(targetSection);
|
||||
SectionWidget* sw = newSectionWidget();
|
||||
sw->addContent(data, true);
|
||||
if (targetSectionSplitter->orientation() == Orientation)
|
||||
{
|
||||
const int index = targetSectionSplitter->indexOf(targetSection);
|
||||
targetSectionSplitter->insertWidget(index + InsertIndexOffset, sw);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int index = targetSectionSplitter->indexOf(targetSection);
|
||||
QSplitter* s = CMainContainerWidget::newSplitter(Orientation);
|
||||
s->addWidget(sw);
|
||||
s->addWidget(targetSection);
|
||||
targetSectionSplitter->insertWidget(index, s);
|
||||
}
|
||||
ret = sw;
|
||||
return ret;
|
||||
}
|
||||
|
||||
SectionWidget* CContainerWidget::addSectionContent(const SectionContent::RefPtr& sc, SectionWidget* sw, DropArea area)
|
||||
{
|
||||
ADS_Expects(!sc.isNull());
|
||||
|
||||
// Drop it based on "area"
|
||||
InternalContentData data;
|
||||
data.content = sc;
|
||||
data.titleWidget = new SectionTitleWidget(sc, NULL);
|
||||
data.contentWidget = new CSectionContentWidget(sc, NULL);
|
||||
|
||||
connect(data.titleWidget, SIGNAL(activeTabChanged()), this, SLOT(onActiveTabChanged()));
|
||||
return dropContent(data, sw, area, false);
|
||||
}
|
||||
|
||||
|
||||
void dumpChildSplitters(QWidget* Widget)
|
||||
{
|
||||
QSplitter* ParentSplitter = dynamic_cast<QSplitter*>(Widget);
|
||||
auto Sections = Widget->findChildren<SectionWidget*>(QString(), Qt::FindDirectChildrenOnly);
|
||||
auto Splitters = Widget->findChildren<QSplitter*>(QString(), Qt::FindDirectChildrenOnly);
|
||||
|
||||
std::cout << "-----------------------" << std::endl;
|
||||
std::cout << "Sections " << Sections.size() << std::endl;
|
||||
std::cout << "Splitters " << Splitters.size() << std::endl;
|
||||
for (const auto& Splitter : Splitters)
|
||||
{
|
||||
if (ParentSplitter)
|
||||
{
|
||||
std::cout << "Orientation " << Splitter->orientation() << " index " << ParentSplitter->indexOf(Splitter) << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Orientation " << Splitter->orientation() << std::endl;
|
||||
}
|
||||
dumpChildSplitters(Splitter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CContainerWidget::dumpLayout()
|
||||
{
|
||||
dumpChildSplitters(this);
|
||||
}
|
||||
|
||||
void CContainerWidget::onActiveTabChanged()
|
||||
{
|
||||
SectionTitleWidget* stw = qobject_cast<SectionTitleWidget*>(sender());
|
||||
if (stw)
|
||||
{
|
||||
emit activeTabChanged(stw->m_Content, stw->isActiveTab());
|
||||
}
|
||||
}
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// EOF ContainerWidget.cpp
|
@ -1,126 +0,0 @@
|
||||
#ifndef ContainerWidgetH
|
||||
#define ContainerWidgetH
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include <QFrame>
|
||||
|
||||
#include "API.h"
|
||||
#include "Internal.h"
|
||||
#include "SectionContent.h"
|
||||
#include "FloatingWidget.h"
|
||||
#include "Serialization.h"
|
||||
#include "DropOverlay.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
class SectionWidget;
|
||||
class DropOverlay;
|
||||
class InternalContentData;
|
||||
class CMainContainerWidget;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
class CContainerWidget : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class SectionContent;
|
||||
friend class SectionWidget;
|
||||
friend class FloatingWidget;
|
||||
friend class SectionTitleWidget;
|
||||
friend class ContainerWidgetPrivate;
|
||||
|
||||
public:
|
||||
explicit CContainerWidget(CMainContainerWidget* MainContainerWidget, QWidget *parent = nullptr);
|
||||
virtual ~CContainerWidget();
|
||||
|
||||
/**
|
||||
* Returns the current zOrderIndex
|
||||
*/
|
||||
virtual unsigned int zOrderIndex() const;
|
||||
|
||||
void dropFloatingWidget(FloatingWidget* FloatingWidget,
|
||||
const QPoint& TargetPos);
|
||||
|
||||
SectionWidget* sectionWidgetAt(const QPoint& GlobalPos) const;
|
||||
|
||||
/**
|
||||
* This function returns true if this container widgets z order index is
|
||||
* higher than the index of the container widget given in Other parameter
|
||||
*/
|
||||
bool isInFrontOf(CContainerWidget* Other) const;
|
||||
|
||||
SectionWidget* dropContent(const InternalContentData& data, SectionWidget* targetSection, DropArea area, bool autoActive = true);
|
||||
|
||||
/*!
|
||||
* Adds the section-content <em>sc</em> to this container-widget into the section-widget <em>sw</em>.
|
||||
* If <em>sw</em> is not NULL, the <em>area</em> is used to indicate how the content should be arranged.
|
||||
* Returns a pointer to the SectionWidget of the added SectionContent. Do not use it for anything else than adding more
|
||||
* SectionContent elements with this method.
|
||||
*/
|
||||
SectionWidget* addSectionContent(const SectionContent::RefPtr& sc, SectionWidget* sw = NULL, DropArea area = CenterDropArea);
|
||||
|
||||
void dumpLayout();
|
||||
|
||||
CMainContainerWidget* mainContainerWidget() const {return m_MainContainerWidget;}
|
||||
|
||||
void addSectionWidget(SectionWidget* section);
|
||||
|
||||
void takeSection(SectionWidget* Widget);
|
||||
|
||||
signals:
|
||||
/*!
|
||||
* Emits whenever the "isActiveTab" state of a SectionContent changes.
|
||||
* Whenever the users sets another tab as active, this signal gets invoked
|
||||
* for the old tab and the new active tab (the order is unspecified).
|
||||
*/
|
||||
void activeTabChanged(const SectionContent::RefPtr& sc, bool active);
|
||||
|
||||
protected:
|
||||
void dropIntoContainer(FloatingWidget* FloatingWidget, DropArea area);
|
||||
void dropIntoSection(FloatingWidget* FloatingWidget, SectionWidget* targetSection, DropArea area);
|
||||
virtual bool event(QEvent *e) override;
|
||||
SectionWidget* newSectionWidget();
|
||||
SectionWidget* dropContentOuterHelper(QLayout* l, const InternalContentData& data, Qt::Orientation orientation, bool append);
|
||||
SectionWidget* insertNewSectionWidget(const InternalContentData& data,
|
||||
SectionWidget* targetSection, SectionWidget* ret, Qt::Orientation Orientation, int InsertIndexOffset);
|
||||
|
||||
QList<SectionWidget*> m_Sections;
|
||||
// Layout stuff
|
||||
QGridLayout* m_MainLayout = nullptr;
|
||||
Qt::Orientation m_Orientation = Qt::Horizontal;
|
||||
QPointer<QSplitter> m_Splitter; // $mfreiholz: I'd like to remove this variable entirely,
|
||||
// because it changes during user interaction anyway.
|
||||
|
||||
CMainContainerWidget* m_MainContainerWidget = 0;
|
||||
unsigned int m_zOrderIndex = 0;
|
||||
static unsigned int zOrderCounter;
|
||||
|
||||
private slots:
|
||||
void onActiveTabChanged();
|
||||
};
|
||||
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#endif // ContainerWidgetH
|
@ -1,461 +0,0 @@
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "DropOverlay.h"
|
||||
|
||||
#include <QPointer>
|
||||
#include <QPaintEvent>
|
||||
#include <QResizeEvent>
|
||||
#include <QMoveEvent>
|
||||
#include <QPainter>
|
||||
#include <QGridLayout>
|
||||
#include <QCursor>
|
||||
#include <QIcon>
|
||||
#include <QLabel>
|
||||
#include <QtGlobal>
|
||||
#include <QDebug>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
// Helper /////////////////////////////////////////////////////////////
|
||||
|
||||
static QPixmap createDropIndicatorPixmap(const QPalette& pal, const QSizeF& size, DropArea dropArea)
|
||||
{
|
||||
const QColor borderColor = pal.color(QPalette::Active, QPalette::Highlight);
|
||||
const QColor backgroundColor = pal.color(QPalette::Active, QPalette::Base);
|
||||
const QColor areaBackgroundColor = pal.color(QPalette::Active, QPalette::Highlight).lighter(150);
|
||||
|
||||
QPixmap pm(size.width(), size.height());
|
||||
pm.fill(QColor(0, 0, 0, 0));
|
||||
|
||||
QPainter p(&pm);
|
||||
QPen pen = p.pen();
|
||||
QRectF baseRect(pm.rect());
|
||||
|
||||
// Fill
|
||||
p.fillRect(baseRect, backgroundColor);
|
||||
|
||||
// Drop area rect.
|
||||
p.save();
|
||||
QRectF areaRect;
|
||||
QLineF areaLine;
|
||||
QLinearGradient gradient;
|
||||
switch (dropArea)
|
||||
{
|
||||
case TopDropArea:
|
||||
areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
|
||||
areaLine = QLineF(areaRect.bottomLeft(), areaRect.bottomRight());
|
||||
gradient.setStart(areaRect.topLeft());
|
||||
gradient.setFinalStop(areaRect.bottomLeft());
|
||||
break;
|
||||
case RightDropArea:
|
||||
areaRect = QRectF(baseRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
|
||||
areaLine = QLineF(areaRect.topLeft(), areaRect.bottomLeft());
|
||||
gradient.setStart(areaRect.topLeft());
|
||||
gradient.setFinalStop(areaRect.topRight());
|
||||
break;
|
||||
case BottomDropArea:
|
||||
areaRect = QRectF(baseRect.x(), baseRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
|
||||
areaLine = QLineF(areaRect.topLeft(), areaRect.topRight());
|
||||
gradient.setStart(areaRect.topLeft());
|
||||
gradient.setFinalStop(areaRect.bottomLeft());
|
||||
break;
|
||||
case LeftDropArea:
|
||||
areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
|
||||
areaLine = QLineF(areaRect.topRight(), areaRect.bottomRight());
|
||||
gradient.setStart(areaRect.topLeft());
|
||||
gradient.setFinalStop(areaRect.topRight());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (areaRect.isValid())
|
||||
{
|
||||
gradient.setColorAt(0.f, areaBackgroundColor);
|
||||
gradient.setColorAt(1.f, areaBackgroundColor.lighter(120));
|
||||
p.fillRect(areaRect, gradient);
|
||||
|
||||
pen = p.pen();
|
||||
pen.setColor(borderColor);
|
||||
pen.setStyle(Qt::DashLine);
|
||||
p.setPen(pen);
|
||||
p.drawLine(areaLine);
|
||||
}
|
||||
p.restore();
|
||||
|
||||
p.save();
|
||||
pen = p.pen();
|
||||
pen.setColor(borderColor);
|
||||
pen.setWidth(1);
|
||||
|
||||
p.setPen(pen);
|
||||
p.drawRect(baseRect.adjusted(0, 0, -pen.width(), -pen.width()));
|
||||
p.restore();
|
||||
return pm;
|
||||
}
|
||||
|
||||
QWidget* DropOverlay::createDropIndicatorWidget(DropArea dropArea)
|
||||
{
|
||||
QLabel* l = new QLabel();
|
||||
l->setObjectName("DropAreaLabel");
|
||||
|
||||
const qreal metric = static_cast<qreal>(l->fontMetrics().height()) * 2.f;
|
||||
const QSizeF size(metric, metric);
|
||||
|
||||
l->setPixmap(createDropIndicatorPixmap(l->palette(), size, dropArea));
|
||||
l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
|
||||
l->setAttribute(Qt::WA_TranslucentBackground);
|
||||
return l;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
DropOverlay::DropOverlay(QWidget* parent, eMode Mode) :
|
||||
QFrame(parent),
|
||||
_allowedAreas(InvalidDropArea),
|
||||
_cross(new DropOverlayCross(this)),
|
||||
_lastLocation(InvalidDropArea)
|
||||
{
|
||||
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
|
||||
setWindowOpacity(0.2);
|
||||
setWindowTitle("DropOverlay");
|
||||
setAttribute(Qt::WA_NoSystemBackground);
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
|
||||
QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
|
||||
l->setSpacing(0);
|
||||
setLayout(l);
|
||||
|
||||
_cross->setupOverlayCross(Mode);
|
||||
_cross->setVisible(false);
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
DropOverlay::~DropOverlay()
|
||||
{
|
||||
}
|
||||
|
||||
void DropOverlay::setAllowedAreas(DropAreas areas)
|
||||
{
|
||||
if (areas == _allowedAreas)
|
||||
return;
|
||||
_allowedAreas = areas;
|
||||
|
||||
_cross->reset();
|
||||
}
|
||||
|
||||
DropAreas DropOverlay::allowedAreas() const
|
||||
{
|
||||
return _allowedAreas;
|
||||
}
|
||||
|
||||
|
||||
DropArea DropOverlay::dropAreaUnderCursor() const
|
||||
{
|
||||
return _cross->cursorLocation();
|
||||
}
|
||||
|
||||
DropArea DropOverlay::showDropOverlay(QWidget* target)
|
||||
{
|
||||
//std::cout << "DropOverlay::showDropOverlay(QWidget* target)" << std::endl;
|
||||
if (_target == target)
|
||||
{
|
||||
qInfo() << "_target == target";
|
||||
// Hint: We could update geometry of overlay here.
|
||||
DropArea da = dropAreaUnderCursor();
|
||||
if (da != _lastLocation)
|
||||
{
|
||||
qInfo() << "repaint()";
|
||||
repaint();
|
||||
_lastLocation = da;
|
||||
}
|
||||
return da;
|
||||
}
|
||||
|
||||
_target = target;
|
||||
_targetRect = QRect();
|
||||
_lastLocation = InvalidDropArea;
|
||||
|
||||
// Move it over the target.
|
||||
resize(target->size());
|
||||
move(target->mapToGlobal(target->rect().topLeft()));
|
||||
show();
|
||||
return dropAreaUnderCursor();
|
||||
}
|
||||
|
||||
void DropOverlay::showDropOverlay(QWidget* target, const QRect& targetAreaRect)
|
||||
{
|
||||
qInfo() << "DropOverlay::showDropOverlay(QWidget* target, const QRect& targetAreaRect)";
|
||||
if (_target == target && _targetRect == targetAreaRect)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//hideDropOverlay();
|
||||
_target = target;
|
||||
_targetRect = targetAreaRect;
|
||||
_lastLocation = InvalidDropArea;
|
||||
|
||||
// Move it over the target's area.
|
||||
resize(targetAreaRect.size());
|
||||
move(target->mapToGlobal(QPoint(targetAreaRect.x(), targetAreaRect.y())));
|
||||
show();
|
||||
return;
|
||||
}
|
||||
|
||||
void DropOverlay::hideDropOverlay()
|
||||
{
|
||||
qInfo() << "hideDropOverlay() _fullAreaDrop = false";
|
||||
hide();
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
_target.clear();
|
||||
#else
|
||||
_target = 0;
|
||||
#endif
|
||||
_targetRect = QRect();
|
||||
_lastLocation = InvalidDropArea;
|
||||
}
|
||||
|
||||
void DropOverlay::paintEvent(QPaintEvent*)
|
||||
{
|
||||
// Draw rect based on location
|
||||
QRect r = rect();
|
||||
const DropArea da = dropAreaUnderCursor();
|
||||
std::cout << "CursorLocation: " << dropAreaUnderCursor() << std::endl;
|
||||
switch (da)
|
||||
{
|
||||
case TopDropArea: r.setHeight(r.height() / 2); break;
|
||||
case RightDropArea: r.setX(r.width() / 2); break;
|
||||
case BottomDropArea: r.setY(r.height() / 2); break;
|
||||
case LeftDropArea: r.setWidth(r.width() / 2); break;
|
||||
case CenterDropArea: r = rect();break;
|
||||
default: return;
|
||||
}
|
||||
QPainter painter(this);
|
||||
QColor Color = palette().color(QPalette::Active, QPalette::Highlight);
|
||||
painter.fillRect(r, QBrush(Color, Qt::Dense4Pattern));
|
||||
painter.setBrush(QBrush(Color));
|
||||
painter.drawRect(r);
|
||||
}
|
||||
|
||||
void DropOverlay::showEvent(QShowEvent*)
|
||||
{
|
||||
_cross->show();
|
||||
QWidget* w = parentWidget() ? parentWidget() : _target.data();
|
||||
QRect WidgetRect = w->rect();
|
||||
QPoint Pos(WidgetRect.left(), WidgetRect.center().y());
|
||||
}
|
||||
|
||||
void DropOverlay::hideEvent(QHideEvent*)
|
||||
{
|
||||
_cross->hide();
|
||||
}
|
||||
|
||||
void DropOverlay::resizeEvent(QResizeEvent* e)
|
||||
{
|
||||
qInfo() << "DropOverlay::resizeEvent" << e->size();
|
||||
_cross->resize(e->size());
|
||||
}
|
||||
|
||||
void DropOverlay::moveEvent(QMoveEvent* e)
|
||||
{
|
||||
qInfo() << "DropOverlay::moveEvent" << e->pos();
|
||||
_cross->move(e->pos());
|
||||
}
|
||||
|
||||
static int areaAlignment(const DropArea area)
|
||||
{
|
||||
switch (area)
|
||||
{
|
||||
case TopDropArea: return (int) Qt::AlignHCenter | Qt::AlignBottom;
|
||||
case RightDropArea: return (int) Qt::AlignLeft | Qt::AlignVCenter;
|
||||
case BottomDropArea: return (int) Qt::AlignHCenter | Qt::AlignTop;
|
||||
case LeftDropArea: return (int) Qt::AlignRight | Qt::AlignVCenter;
|
||||
case CenterDropArea: return (int) Qt::AlignCenter;
|
||||
default: return Qt::AlignCenter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QPoint DropOverlayCross::areaGridPosition(const DropArea area)
|
||||
{
|
||||
if (DropOverlay::ModeSectionOverlay == m_Mode)
|
||||
{
|
||||
switch (area)
|
||||
{
|
||||
case TopDropArea: return QPoint(1, 2);
|
||||
case RightDropArea: return QPoint(2, 3);
|
||||
case BottomDropArea: return QPoint(3, 2);
|
||||
case LeftDropArea: return QPoint(2, 1);
|
||||
case CenterDropArea: return QPoint(2, 2);
|
||||
default: return QPoint();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (area)
|
||||
{
|
||||
case TopDropArea: return QPoint(0, 2);
|
||||
case RightDropArea: return QPoint(2, 4);
|
||||
case BottomDropArea: return QPoint(4, 2);
|
||||
case LeftDropArea: return QPoint(2, 0);
|
||||
case CenterDropArea: return QPoint(2, 2);
|
||||
default: return QPoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DropOverlayCross::DropOverlayCross(DropOverlay* overlay) :
|
||||
QWidget(overlay->parentWidget()),
|
||||
m_DropOverlay(overlay)
|
||||
{
|
||||
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
|
||||
setWindowTitle("DropOverlayCross");
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
|
||||
m_GridLayout = new QGridLayout();
|
||||
m_GridLayout->setSpacing(6);
|
||||
setLayout(m_GridLayout);
|
||||
}
|
||||
|
||||
DropOverlayCross::~DropOverlayCross()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void DropOverlayCross::setupOverlayCross(DropOverlay::eMode Mode)
|
||||
{
|
||||
m_Mode = Mode;
|
||||
|
||||
QHash<DropArea, QWidget*> areaWidgets;
|
||||
areaWidgets.insert(TopDropArea, DropOverlay::createDropIndicatorWidget(TopDropArea));
|
||||
areaWidgets.insert(RightDropArea, DropOverlay::createDropIndicatorWidget(RightDropArea));
|
||||
areaWidgets.insert(BottomDropArea, DropOverlay::createDropIndicatorWidget(BottomDropArea));
|
||||
areaWidgets.insert(LeftDropArea, DropOverlay::createDropIndicatorWidget(LeftDropArea));
|
||||
areaWidgets.insert(CenterDropArea, DropOverlay::createDropIndicatorWidget(CenterDropArea));
|
||||
|
||||
setAreaWidgets(areaWidgets);
|
||||
}
|
||||
|
||||
|
||||
void DropOverlayCross::setAreaWidgets(const QHash<DropArea, QWidget*>& widgets)
|
||||
{
|
||||
// Delete old widgets.
|
||||
QMutableHashIterator<DropArea, QWidget*> i(m_DropIndicatorWidgets);
|
||||
while (i.hasNext())
|
||||
{
|
||||
i.next();
|
||||
QWidget* widget = i.value();
|
||||
m_GridLayout->removeWidget(widget);
|
||||
delete widget;
|
||||
i.remove();
|
||||
}
|
||||
|
||||
// Insert new widgets into grid.
|
||||
m_DropIndicatorWidgets = widgets;
|
||||
QHashIterator<DropArea, QWidget*> i2(m_DropIndicatorWidgets);
|
||||
while (i2.hasNext())
|
||||
{
|
||||
i2.next();
|
||||
const DropArea area = i2.key();
|
||||
QWidget* widget = i2.value();
|
||||
QPoint p = areaGridPosition(area);
|
||||
m_GridLayout->addWidget(widget, p.x(), p.y(), (Qt::Alignment) areaAlignment(area));
|
||||
}
|
||||
|
||||
if (DropOverlay::ModeSectionOverlay == m_Mode)
|
||||
{
|
||||
m_GridLayout->setContentsMargins(0, 0, 0, 0);
|
||||
m_GridLayout->setRowStretch(0, 1);
|
||||
m_GridLayout->setRowStretch(1, 0);
|
||||
m_GridLayout->setRowStretch(2, 0);
|
||||
m_GridLayout->setRowStretch(3, 0);
|
||||
m_GridLayout->setRowStretch(4, 1);
|
||||
|
||||
m_GridLayout->setColumnStretch(0, 1);
|
||||
m_GridLayout->setColumnStretch(1, 0);
|
||||
m_GridLayout->setColumnStretch(2, 0);
|
||||
m_GridLayout->setColumnStretch(3, 0);
|
||||
m_GridLayout->setColumnStretch(4, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_GridLayout->setContentsMargins(4, 4, 4, 4);
|
||||
m_GridLayout->setRowStretch(0, 0);
|
||||
m_GridLayout->setRowStretch(1, 1);
|
||||
m_GridLayout->setRowStretch(2, 1);
|
||||
m_GridLayout->setRowStretch(3, 1);
|
||||
m_GridLayout->setRowStretch(4, 0);
|
||||
|
||||
m_GridLayout->setColumnStretch(0, 0);
|
||||
m_GridLayout->setColumnStretch(1, 1);
|
||||
m_GridLayout->setColumnStretch(2, 1);
|
||||
m_GridLayout->setColumnStretch(3, 1);
|
||||
m_GridLayout->setColumnStretch(4, 0);
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
DropArea DropOverlayCross::cursorLocation() const
|
||||
{
|
||||
const QPoint pos = mapFromGlobal(QCursor::pos());
|
||||
QHashIterator<DropArea, QWidget*> i(m_DropIndicatorWidgets);
|
||||
while (i.hasNext())
|
||||
{
|
||||
i.next();
|
||||
if (m_DropOverlay->allowedAreas().testFlag(i.key())
|
||||
&& i.value()
|
||||
&& i.value()->isVisible()
|
||||
&& i.value()->geometry().contains(pos))
|
||||
{
|
||||
return i.key();
|
||||
}
|
||||
}
|
||||
return InvalidDropArea;
|
||||
}
|
||||
|
||||
void DropOverlayCross::showEvent(QShowEvent*)
|
||||
{
|
||||
resize(m_DropOverlay->size());
|
||||
move(m_DropOverlay->pos());
|
||||
}
|
||||
|
||||
void DropOverlayCross::reset()
|
||||
{
|
||||
QList<DropArea> allAreas;
|
||||
allAreas << TopDropArea << RightDropArea
|
||||
<< BottomDropArea << LeftDropArea << CenterDropArea;
|
||||
const DropAreas allowedAreas = m_DropOverlay->allowedAreas();
|
||||
|
||||
// Update visibility of area widgets based on allowedAreas.
|
||||
for (int i = 0; i < allAreas.count(); ++i)
|
||||
{
|
||||
QPoint p = areaGridPosition(allAreas.at(i));
|
||||
QLayoutItem* item = m_GridLayout->itemAtPosition(p.x(), p.y());
|
||||
QWidget* w = nullptr;
|
||||
if (item && (w = item->widget()) != nullptr)
|
||||
{
|
||||
w->setVisible(allowedAreas.testFlag(allAreas.at(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ads
|
@ -1,120 +0,0 @@
|
||||
#ifndef DROP_OVERLAY_H
|
||||
#define DROP_OVERLAY_H
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
#include <QPointer>
|
||||
#include <QHash>
|
||||
#include <QRect>
|
||||
#include <QFrame>
|
||||
class QGridLayout;
|
||||
|
||||
#include "API.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
class DropOverlayCross;
|
||||
|
||||
/*!
|
||||
* DropOverlay paints a translucent rectangle over another widget. The geometry
|
||||
* of the rectangle is based on the mouse location.
|
||||
*/
|
||||
class ADS_EXPORT_API DropOverlay : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class DropOverlayCross;
|
||||
|
||||
public:
|
||||
enum eMode
|
||||
{
|
||||
ModeSectionOverlay,
|
||||
ModeContainerOverlay
|
||||
};
|
||||
|
||||
DropOverlay(QWidget* parent, eMode Mode = ModeSectionOverlay);
|
||||
virtual ~DropOverlay();
|
||||
|
||||
void setAllowedAreas(DropAreas areas);
|
||||
|
||||
/**
|
||||
* Returns flags with all allowed drop areas
|
||||
*/
|
||||
DropAreas allowedAreas() const;
|
||||
|
||||
/**
|
||||
* Returns the drop area under the current cursor location
|
||||
*/
|
||||
DropArea dropAreaUnderCursor() const;
|
||||
|
||||
DropArea showDropOverlay(QWidget* target);
|
||||
void showDropOverlay(QWidget* target, const QRect& targetAreaRect);
|
||||
void hideDropOverlay();
|
||||
|
||||
/**
|
||||
* Creates a drop indicator widget for the given drop area
|
||||
*/
|
||||
static QWidget* createDropIndicatorWidget(DropArea dropArea);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent *e);
|
||||
virtual void showEvent(QShowEvent* e);
|
||||
virtual void hideEvent(QHideEvent* e);
|
||||
virtual void resizeEvent(QResizeEvent* e);
|
||||
virtual void moveEvent(QMoveEvent* e);
|
||||
|
||||
private:
|
||||
DropAreas _allowedAreas;
|
||||
DropOverlayCross* _cross;
|
||||
QPointer<QWidget> _target;
|
||||
QRect _targetRect;
|
||||
DropArea _lastLocation;
|
||||
};
|
||||
|
||||
/*!
|
||||
* DropOverlayCross shows a cross with 5 different drop area possibilities.
|
||||
* I could have handled everything inside DropOverlay, but because of some
|
||||
* styling issues it's better to have a separate class for the cross.
|
||||
*/
|
||||
class DropOverlayCross : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class DropOverlay;
|
||||
|
||||
public:
|
||||
DropOverlayCross(DropOverlay* overlay);
|
||||
virtual ~DropOverlayCross();
|
||||
|
||||
DropArea cursorLocation() const;
|
||||
void setupOverlayCross(DropOverlay::eMode Mode);
|
||||
|
||||
protected:
|
||||
virtual void showEvent(QShowEvent* e);
|
||||
void setAreaWidgets(const QHash<DropArea, QWidget*>& widgets);
|
||||
|
||||
private:
|
||||
void reset();
|
||||
QPoint areaGridPosition(const DropArea area);
|
||||
|
||||
private:
|
||||
DropOverlay::eMode m_Mode = DropOverlay::ModeSectionOverlay;
|
||||
DropOverlay* m_DropOverlay;
|
||||
QHash<DropArea, QWidget*> m_DropIndicatorWidgets;
|
||||
QGridLayout* m_GridLayout;
|
||||
};
|
||||
|
||||
} // namespace ads
|
||||
#endif
|
@ -1,422 +0,0 @@
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "FloatingWidget.h"
|
||||
|
||||
#include <QBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QSizePolicy>
|
||||
#include <QMouseEvent>
|
||||
#include <QStyle>
|
||||
#include <QLabel>
|
||||
#include <QGuiApplication>
|
||||
|
||||
#include "SectionTitleWidget.h"
|
||||
#include "Internal.h"
|
||||
#include "SectionWidget.h"
|
||||
#include "ContainerWidget.h"
|
||||
#include "MainContainerWidget.h"
|
||||
#include "SectionContentWidget.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
unsigned int FloatingWidget::zOrderCounter = 0;
|
||||
|
||||
|
||||
|
||||
CFloatingTitleWidget::CFloatingTitleWidget(SectionContent::Flags Flags, FloatingWidget* Parent)
|
||||
: QFrame(Parent)
|
||||
{
|
||||
auto Layout = new QHBoxLayout();
|
||||
QLabel* Label = new QLabel(this);
|
||||
Label->setText("Floating Widget");
|
||||
Label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
||||
Label->setAlignment(Qt::AlignLeft);
|
||||
Layout->addWidget(Label, 1, Qt::AlignLeft | Qt::AlignVCenter);
|
||||
Layout->setSpacing(0);
|
||||
setLayout(Layout);
|
||||
|
||||
if (Flags.testFlag(SectionContent::Maximizable))
|
||||
{
|
||||
QPushButton* Button = new QPushButton();
|
||||
Button->setObjectName("maximizeButton");
|
||||
Button->setFlat(true);
|
||||
Button->setIcon(style()->standardIcon(QStyle::SP_TitleBarMaxButton));
|
||||
Button->setToolTip(tr("Close"));
|
||||
Button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
Layout->addWidget(Button);
|
||||
connect(Button, SIGNAL(clicked(bool)), this, SLOT(onMaximizeButtonClicked()));
|
||||
}
|
||||
|
||||
if (Flags.testFlag(SectionContent::Closeable))
|
||||
{
|
||||
QPushButton* closeButton = new QPushButton();
|
||||
closeButton->setObjectName("closeButton");
|
||||
closeButton->setFlat(true);
|
||||
closeButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton));
|
||||
closeButton->setToolTip(tr("Maximize"));
|
||||
closeButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
Layout->addWidget(closeButton);
|
||||
connect(closeButton, SIGNAL(clicked(bool)), this, SIGNAL(closeButtonClicked()));
|
||||
}
|
||||
|
||||
if (Flags == 0)
|
||||
{
|
||||
Layout->setContentsMargins(6, 6, 6, 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
Layout->setContentsMargins(6, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
FloatingWidget* CFloatingTitleWidget::floatingWidget() const
|
||||
{
|
||||
return dynamic_cast<FloatingWidget*>(parentWidget());
|
||||
}
|
||||
|
||||
CMainContainerWidget* CFloatingTitleWidget::mainContainerWidget() const
|
||||
{
|
||||
return floatingWidget()->mainContainerWidget();
|
||||
}
|
||||
|
||||
|
||||
void CFloatingTitleWidget::mousePressEvent(QMouseEvent* ev)
|
||||
{
|
||||
if (ev->button() == Qt::LeftButton)
|
||||
{
|
||||
ev->accept();
|
||||
m_DragStartPosition = floatingWidget()->pos();
|
||||
m_DragStartMousePosition = ev->globalPos();
|
||||
return;
|
||||
}
|
||||
QFrame::mousePressEvent(ev);
|
||||
}
|
||||
|
||||
|
||||
void CFloatingTitleWidget::mouseReleaseEvent(QMouseEvent* ev)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CFloatingTitleWidget::mouseMoveEvent(QMouseEvent* ev)
|
||||
{
|
||||
if (!(ev->buttons() & Qt::LeftButton))
|
||||
{
|
||||
QFrame::mouseMoveEvent(ev);
|
||||
return;
|
||||
}
|
||||
|
||||
floatingWidget()->updateDropOverlays(ev->globalPos());
|
||||
ev->accept();
|
||||
moveFloatingWidget(ev);
|
||||
}
|
||||
|
||||
|
||||
void CFloatingTitleWidget::moveFloatingWidget(QMouseEvent* ev)
|
||||
{
|
||||
const QPoint DragDistance = ev->globalPos() - m_DragStartMousePosition;
|
||||
const QPoint moveToPos = m_DragStartPosition + DragDistance;
|
||||
floatingWidget()->move(moveToPos);
|
||||
}
|
||||
|
||||
|
||||
void CFloatingTitleWidget::onMaximizeButtonClicked()
|
||||
{
|
||||
if (floatingWidget()->isMaximized())
|
||||
{
|
||||
floatingWidget()->showNormal();
|
||||
}
|
||||
else
|
||||
{
|
||||
floatingWidget()->showMaximized();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
FloatingWidget::FloatingWidget(CMainContainerWidget* MainContainer, SectionContent::RefPtr sc, SectionTitleWidget* titleWidget, CSectionContentWidget* contentWidget, QWidget* parent) :
|
||||
QWidget(MainContainer, Qt::Window),
|
||||
m_MainContainerWidget(MainContainer)
|
||||
{
|
||||
QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
|
||||
l->setContentsMargins(0, 0, 0, 0);
|
||||
l->setSpacing(0);
|
||||
setLayout(l);
|
||||
m_ContainerWidget = new CContainerWidget(m_MainContainerWidget, this);
|
||||
m_MainContainerWidget->m_Containers.append(m_ContainerWidget);
|
||||
l->addWidget(m_ContainerWidget, 1);
|
||||
|
||||
InternalContentData data;
|
||||
data.content = sc;
|
||||
data.contentWidget = contentWidget;
|
||||
data.titleWidget = titleWidget;
|
||||
|
||||
m_ContainerWidget->dropContent(data, nullptr, CenterDropArea);
|
||||
m_ContainerWidget->show();
|
||||
m_zOrderIndex = ++zOrderCounter;
|
||||
m_MainContainerWidget->m_Floatings.append(this);
|
||||
}
|
||||
|
||||
|
||||
FloatingWidget::FloatingWidget(CMainContainerWidget* MainContainer, SectionWidget* sectionWidget)
|
||||
: QWidget(MainContainer, Qt::Window),
|
||||
m_MainContainerWidget(MainContainer)
|
||||
{
|
||||
QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
|
||||
l->setContentsMargins(0, 0, 0, 0);
|
||||
l->setSpacing(0);
|
||||
setLayout(l);
|
||||
|
||||
m_ContainerWidget = new CContainerWidget(m_MainContainerWidget, this);
|
||||
m_MainContainerWidget->m_Containers.append(m_ContainerWidget);
|
||||
l->addWidget(m_ContainerWidget, 1);
|
||||
|
||||
m_ContainerWidget->addSectionWidget(sectionWidget);
|
||||
m_ContainerWidget->show();
|
||||
m_zOrderIndex = ++zOrderCounter;
|
||||
m_MainContainerWidget->m_Floatings.append(this);
|
||||
}
|
||||
|
||||
|
||||
FloatingWidget::~FloatingWidget()
|
||||
{
|
||||
std::cout << "FloatingWidget::~FloatingWidget" << std::endl;
|
||||
m_MainContainerWidget->m_Floatings.removeAll(this);
|
||||
}
|
||||
|
||||
bool FloatingWidget::takeContent(InternalContentData& data)
|
||||
{
|
||||
// TODO remove takeContent function
|
||||
/*data.content = _content;
|
||||
data.titleWidget = _titleWidget;
|
||||
data.contentWidget = _contentWidget;
|
||||
|
||||
//_titleLayout->removeWidget(_titleWidget);
|
||||
_titleWidget->setParent(m_MainContainerWidget);
|
||||
_titleWidget = NULL;
|
||||
|
||||
layout()->removeWidget(_contentWidget);
|
||||
_contentWidget->setParent(m_MainContainerWidget);
|
||||
_contentWidget = NULL;*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FloatingWidget::onCloseButtonClicked()
|
||||
{
|
||||
//m_MainContainerWidget->hideSectionContent(_content);
|
||||
}
|
||||
|
||||
|
||||
void FloatingWidget::setDraggingActive(bool Active)
|
||||
{
|
||||
if (m_DraggingActive == Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_DraggingActive = Active;
|
||||
if (Active)
|
||||
{
|
||||
std::cout << "FloatingWidget:: InstallEventFilter" << std::endl;
|
||||
qApp->installEventFilter(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "FloatingWidget:: RemoveEventFilter" << std::endl;
|
||||
qApp->removeEventFilter(this);
|
||||
}
|
||||
}
|
||||
|
||||
void FloatingWidget::changeEvent(QEvent *event)
|
||||
{
|
||||
QWidget::changeEvent(event);
|
||||
if (event->type() == QEvent::ActivationChange && isActiveWindow())
|
||||
{
|
||||
std::cout << "FloatingWidget::changeEvent QEvent::ActivationChange " << std::endl;
|
||||
m_zOrderIndex = ++zOrderCounter;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FloatingWidget::moveEvent(QMoveEvent *event)
|
||||
{
|
||||
QWidget::moveEvent(event);
|
||||
if (m_DraggingActive && qApp->mouseButtons().testFlag(Qt::LeftButton))
|
||||
{
|
||||
//std::cout << "Dragging" << std::endl;
|
||||
updateDropOverlays(QCursor::pos());
|
||||
}
|
||||
}
|
||||
|
||||
bool FloatingWidget::event(QEvent *e)
|
||||
{
|
||||
if ((e->type() == QEvent::NonClientAreaMouseButtonPress))
|
||||
{
|
||||
if (QGuiApplication::mouseButtons() == Qt::LeftButton)
|
||||
{
|
||||
std::cout << "FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type() << std::endl;
|
||||
setDraggingActive(true);
|
||||
}
|
||||
}
|
||||
else if (e->type() == QEvent::NonClientAreaMouseButtonDblClick)
|
||||
{
|
||||
std::cout << "FloatingWidget::event QEvent::NonClientAreaMouseButtonDblClick" << std::endl;
|
||||
setDraggingActive(false);
|
||||
}
|
||||
else if ((e->type() == QEvent::NonClientAreaMouseButtonRelease) && m_DraggingActive)
|
||||
{
|
||||
std::cout << "FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease" << std::endl;
|
||||
titleMouseReleaseEvent();
|
||||
}
|
||||
return QWidget::event(e);
|
||||
}
|
||||
|
||||
|
||||
bool FloatingWidget::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::MouseButtonRelease)
|
||||
{
|
||||
std::cout << "FloatingWidget::eventFilter QEvent::MouseButtonRelease" << std::endl;
|
||||
titleMouseReleaseEvent();
|
||||
}
|
||||
else if (event->type() == QEvent::MouseMove)
|
||||
{
|
||||
if (m_DraggingActive)
|
||||
{
|
||||
QMouseEvent* MouseEvent = dynamic_cast<QMouseEvent*>(event);
|
||||
int BorderSize = (frameSize().width() - size().width()) / 2;
|
||||
const QPoint moveToPos = QCursor::pos() - m_DragStartMousePosition - QPoint(BorderSize, 0);
|
||||
move(moveToPos);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void FloatingWidget::startFloating(const QPoint& Pos)
|
||||
{
|
||||
setDraggingActive(true);
|
||||
QPoint TargetPos = QCursor::pos() - Pos;
|
||||
move(TargetPos);
|
||||
show();
|
||||
m_DragStartMousePosition = Pos;
|
||||
m_DragStartPosition = this->pos();
|
||||
}
|
||||
|
||||
|
||||
void FloatingWidget::titleMouseReleaseEvent()
|
||||
{
|
||||
setDraggingActive(false);
|
||||
if (!m_DropContainer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "Dropped" << std::endl;
|
||||
CMainContainerWidget* MainContainerWidget = mainContainerWidget();
|
||||
m_DropContainer->dropFloatingWidget(this, QCursor::pos());
|
||||
MainContainerWidget->dropOverlay()->hideDropOverlay();
|
||||
MainContainerWidget->sectionDropOverlay()->hideDropOverlay();
|
||||
}
|
||||
|
||||
|
||||
unsigned int FloatingWidget::zOrderIndex() const
|
||||
{
|
||||
return m_zOrderIndex;
|
||||
}
|
||||
|
||||
|
||||
void FloatingWidget::updateDropOverlays(const QPoint& GlobalPos)
|
||||
{
|
||||
if (!isVisible())
|
||||
{
|
||||
return;
|
||||
}
|
||||
CMainContainerWidget* MainContainerWidget = mainContainerWidget();
|
||||
auto Containers = MainContainerWidget->m_Containers;
|
||||
CContainerWidget* TopContainer = nullptr;
|
||||
for (auto ContainerWidget : Containers)
|
||||
{
|
||||
if (!ContainerWidget->isVisible())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (containerWidget() == ContainerWidget)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos);
|
||||
if (ContainerWidget->rect().contains(MappedPos))
|
||||
{
|
||||
std::cout << "Container " << ContainerWidget << " contains mousepos" << std::endl;
|
||||
if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer))
|
||||
{
|
||||
TopContainer = ContainerWidget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_DropContainer = TopContainer;
|
||||
DropOverlay* ContainerDropOverlay = MainContainerWidget->dropOverlay();
|
||||
DropOverlay* SectionDropOverlay = MainContainerWidget->sectionDropOverlay();
|
||||
|
||||
if (!TopContainer)
|
||||
{
|
||||
ContainerDropOverlay->hideDropOverlay();
|
||||
SectionDropOverlay->hideDropOverlay();
|
||||
return;
|
||||
}
|
||||
|
||||
ContainerDropOverlay->showDropOverlay(TopContainer);
|
||||
ContainerDropOverlay->raise();
|
||||
|
||||
SectionWidget* sectionwidget = TopContainer->sectionWidgetAt(GlobalPos);
|
||||
if (sectionwidget)
|
||||
{
|
||||
SectionDropOverlay->setAllowedAreas(AllAreas);
|
||||
SectionDropOverlay->showDropOverlay(sectionwidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
SectionDropOverlay->hideDropOverlay();
|
||||
}
|
||||
|
||||
|
||||
if (TopContainer)
|
||||
{
|
||||
ContainerDropOverlay->showDropOverlay(TopContainer);
|
||||
ContainerDropOverlay->raise();
|
||||
}
|
||||
else
|
||||
{
|
||||
ContainerDropOverlay->hideDropOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ads
|
@ -1,116 +0,0 @@
|
||||
#ifndef FLOATINGWIDGET_H
|
||||
#define FLOATINGWIDGET_H
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
#include <QWidget>
|
||||
#include <QFrame>
|
||||
class QBoxLayout;
|
||||
|
||||
#include "API.h"
|
||||
#include "SectionContent.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
class CMainContainerWidget;
|
||||
class SectionTitleWidget;
|
||||
class CSectionContentWidget;
|
||||
class InternalContentData;
|
||||
class SectionWidget;
|
||||
class CContainerWidget;
|
||||
class FloatingWidget;
|
||||
|
||||
class CFloatingTitleWidget : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
QPoint m_DragStartPosition;
|
||||
QPoint m_DragStartMousePosition;
|
||||
FloatingWidget* floatingWidget() const;
|
||||
CMainContainerWidget* mainContainerWidget() const;
|
||||
void moveFloatingWidget(QMouseEvent* ev);
|
||||
|
||||
private slots:
|
||||
void onMaximizeButtonClicked();
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent* ev);
|
||||
virtual void mouseReleaseEvent(QMouseEvent* ev);
|
||||
virtual void mouseMoveEvent(QMouseEvent* ev);
|
||||
|
||||
public:
|
||||
CFloatingTitleWidget(SectionContent::Flags Flags, FloatingWidget* Parent);
|
||||
|
||||
signals:
|
||||
void closeButtonClicked();
|
||||
};
|
||||
|
||||
|
||||
// FloatingWidget holds and displays SectionContent as a floating window.
|
||||
// It can be resized, moved and dropped back into a SectionWidget.
|
||||
class FloatingWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class CMainContainerWidget;
|
||||
friend class CFloatingTitleWidget;
|
||||
|
||||
public:
|
||||
FloatingWidget(CMainContainerWidget* container, SectionContent::RefPtr sc, SectionTitleWidget* titleWidget, CSectionContentWidget* contentWidget, QWidget* parent = NULL);
|
||||
FloatingWidget(CMainContainerWidget* container, SectionWidget* sectionWidget);
|
||||
virtual ~FloatingWidget();
|
||||
|
||||
/**
|
||||
* Returns the current zOrderIndex
|
||||
*/
|
||||
unsigned int zOrderIndex() const;
|
||||
|
||||
CContainerWidget* containerWidget() const {return m_ContainerWidget;}
|
||||
CMainContainerWidget* mainContainerWidget() const {return m_MainContainerWidget;}
|
||||
|
||||
public://private:
|
||||
bool takeContent(InternalContentData& data);
|
||||
|
||||
void startFloating(const QPoint& Pos);
|
||||
|
||||
protected:
|
||||
virtual void changeEvent(QEvent *event) override;
|
||||
virtual void moveEvent(QMoveEvent *event) override;
|
||||
virtual bool event(QEvent *e);
|
||||
void titleMouseReleaseEvent();
|
||||
virtual bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
void updateDropOverlays(const QPoint& GlobalPos);
|
||||
|
||||
private slots:
|
||||
void onCloseButtonClicked();
|
||||
|
||||
private:
|
||||
void setDraggingActive(bool Active);
|
||||
|
||||
CMainContainerWidget* m_MainContainerWidget;
|
||||
CContainerWidget* m_ContainerWidget;
|
||||
CContainerWidget* m_DropContainer;
|
||||
bool m_DraggingActive = false;
|
||||
unsigned int m_zOrderIndex = 0;
|
||||
QPoint m_DragStartPosition;
|
||||
QPoint m_DragStartMousePosition;
|
||||
static unsigned int zOrderCounter;
|
||||
};
|
||||
|
||||
} // namespace ads
|
||||
#endif
|
@ -1,34 +0,0 @@
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "Internal.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
InternalContentData::InternalContentData() :
|
||||
titleWidget(NULL),
|
||||
contentWidget(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
InternalContentData::~InternalContentData()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace ads
|
@ -1,62 +0,0 @@
|
||||
#ifndef ADS_INTERNAL_HEADER
|
||||
#define ADS_INTERNAL_HEADER
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
#include <QSharedPointer>
|
||||
#include <QWeakPointer>
|
||||
|
||||
#include "API.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
class SectionContent;
|
||||
class SectionTitleWidget;
|
||||
class CSectionContentWidget;
|
||||
|
||||
|
||||
class InternalContentData
|
||||
{
|
||||
public:
|
||||
typedef QSharedPointer<InternalContentData> RefPtr;
|
||||
typedef QWeakPointer<InternalContentData> WeakPtr;
|
||||
|
||||
InternalContentData();
|
||||
~InternalContentData();
|
||||
|
||||
QSharedPointer<SectionContent> content;
|
||||
SectionTitleWidget* titleWidget;
|
||||
CSectionContentWidget* contentWidget;
|
||||
};
|
||||
|
||||
|
||||
class HiddenSectionItem
|
||||
{
|
||||
public:
|
||||
HiddenSectionItem() :
|
||||
preferredSectionId(-1),
|
||||
preferredSectionIndex(-1)
|
||||
{}
|
||||
|
||||
int preferredSectionId;
|
||||
int preferredSectionIndex;
|
||||
InternalContentData data;
|
||||
};
|
||||
|
||||
|
||||
} // namespace ads
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,189 +0,0 @@
|
||||
#ifndef ADS_CONTAINERWIDGET_H
|
||||
#define ADS_CONTAINERWIDGET_H
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
#include <QList>
|
||||
#include <QHash>
|
||||
#include <QPointer>
|
||||
#include <QFrame>
|
||||
#include <QGridLayout>
|
||||
#include <QSplitter>
|
||||
|
||||
class QPoint;
|
||||
class QMenu;
|
||||
|
||||
#include "API.h"
|
||||
#include "Internal.h"
|
||||
#include "SectionContent.h"
|
||||
#include "FloatingWidget.h"
|
||||
#include "Serialization.h"
|
||||
#include "DropOverlay.h"
|
||||
#include "ContainerWidget.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
class SectionWidget;
|
||||
class DropOverlay;
|
||||
class InternalContentData;
|
||||
class CSectionContentWidget;
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* ContainerWidget is the main container to provide the docking
|
||||
* functionality. It manages multiple sections with all possible areas.
|
||||
*/
|
||||
class ADS_EXPORT_API CMainContainerWidget : public CContainerWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class SectionContent;
|
||||
friend class SectionWidget;
|
||||
friend class FloatingWidget;
|
||||
friend class SectionTitleWidget;
|
||||
friend class ContainerWidgetPrivate;
|
||||
friend class CFloatingTitleWidget;
|
||||
friend class CContainerWidget;
|
||||
friend class CSectionContentWidget;
|
||||
|
||||
public:
|
||||
explicit CMainContainerWidget(QWidget *parent = nullptr);
|
||||
virtual ~CMainContainerWidget();
|
||||
|
||||
//
|
||||
// Public API
|
||||
//
|
||||
|
||||
/*!
|
||||
* Completely removes the <em>sc</em> from this ContainerWidget.
|
||||
* This container will no longer hold a reference to the content.
|
||||
* The content can be safely deleted.
|
||||
*/
|
||||
bool removeSectionContent(const SectionContent::RefPtr& sc);
|
||||
|
||||
/*!
|
||||
* Shows the specific SectionContent in UI.
|
||||
* Independed of the current state, whether it is used inside a section or is floating.
|
||||
*/
|
||||
bool showSectionContent(const SectionContent::RefPtr& sc);
|
||||
|
||||
/*!
|
||||
* Closes the specified SectionContent from UI.
|
||||
* Independed of the current state, whether it is used inside a section or is floating.
|
||||
*/
|
||||
bool hideSectionContent(const SectionContent::RefPtr& sc);
|
||||
|
||||
/*!
|
||||
* Selects the specific SectionContent as current, if it is part of a SectionWidget.
|
||||
* If SC is floating, it does nothing (or should we show it?)
|
||||
*/
|
||||
bool raiseSectionContent(const SectionContent::RefPtr& sc);
|
||||
|
||||
/*!
|
||||
* Indicates whether the SectionContent <em>sc</em> is visible.
|
||||
*/
|
||||
bool isSectionContentVisible(const SectionContent::RefPtr& sc);
|
||||
|
||||
/*!
|
||||
* Creates a QMenu based on available SectionContents.
|
||||
* The caller is responsible to delete the menu.
|
||||
*/
|
||||
QMenu* createContextMenu() const;
|
||||
|
||||
/*!
|
||||
* Serializes the current state of contents and returns it as a plain byte array.
|
||||
* \see restoreState(const QByteArray&)
|
||||
*/
|
||||
QByteArray saveState() const;
|
||||
|
||||
/*!
|
||||
* Deserilizes the state of contents from <em>data</em>, which was written with <em>saveState()</em>.
|
||||
* \see saveState()
|
||||
*/
|
||||
bool restoreState(const QByteArray& data);
|
||||
|
||||
//
|
||||
// Advanced Public API
|
||||
// You usually should not need access to this methods
|
||||
//
|
||||
/*!
|
||||
* \brief contents
|
||||
* \return List of known SectionContent for this ContainerWidget.
|
||||
*/
|
||||
QList<SectionContent::RefPtr> contents() const;
|
||||
|
||||
/**
|
||||
* Access function for the section drop overlay
|
||||
*/
|
||||
QPointer<DropOverlay> sectionDropOverlay() const;
|
||||
|
||||
QPointer<DropOverlay> dropOverlay() const;
|
||||
|
||||
static QSplitter* newSplitter(Qt::Orientation orientation = Qt::Horizontal, QWidget* parent = 0);
|
||||
|
||||
virtual unsigned int zOrderIndex() const {return 0;}
|
||||
|
||||
private:
|
||||
// Serialization
|
||||
QByteArray saveHierarchy() const;
|
||||
void saveFloatingWidgets(QDataStream& out) const;
|
||||
void saveSectionWidgets(QDataStream& out, QWidget* widget) const;
|
||||
|
||||
bool saveSectionIndex(SectionIndexData &sid) const;
|
||||
|
||||
bool restoreHierarchy(const QByteArray& data);
|
||||
bool restoreFloatingWidgets(QDataStream& in, int version, QList<FloatingWidget*>& floatings);
|
||||
bool restoreSectionWidgets(QDataStream& in, int version, QSplitter* currentSplitter, QList<SectionWidget*>& sections, QList<SectionContent::RefPtr>& contentsToHide);
|
||||
|
||||
bool takeContent(const SectionContent::RefPtr& sc, InternalContentData& data);
|
||||
void hideContainerOverlay();
|
||||
void moveFloatingWidget(const QPoint& TargetPos);
|
||||
|
||||
private slots:
|
||||
void onActionToggleSectionContentVisibility(bool visible);
|
||||
|
||||
signals:
|
||||
void orientationChanged();
|
||||
|
||||
/*!
|
||||
* Emits whenever the visibility of a SectionContent changes.
|
||||
* \see showSectionContent(), hideSectionContent()
|
||||
* \since 0.2
|
||||
*/
|
||||
void sectionContentVisibilityChanged(const SectionContent::RefPtr& sc, bool visible);
|
||||
|
||||
private:
|
||||
QList<FloatingWidget*> m_Floatings;
|
||||
QList<CContainerWidget*> m_Containers;
|
||||
QHash<int, HiddenSectionItem> m_HiddenSectionContents;
|
||||
|
||||
// Helper lookup maps, restricted to this container.
|
||||
QHash<int, SectionContent::WeakPtr> m_SectionContentIdMap;
|
||||
QHash<QString, SectionContent::WeakPtr> m_SectionContentNameMap;
|
||||
QHash<int, SectionWidget*> m_SectionWidgetIdMap;
|
||||
|
||||
QHash<int, CSectionContentWidget*> m_SectionContentWidgetIdMap;
|
||||
QHash<QString, CSectionContentWidget*> m_SectionContentWidgetNameMap;
|
||||
|
||||
QPointer<DropOverlay> m_ContainerDropOverlay;
|
||||
QPointer<DropOverlay> m_SectionDropOverlay;
|
||||
};
|
||||
|
||||
|
||||
} // namespace ads
|
||||
#endif
|
@ -1,140 +0,0 @@
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "MainContainerWidget.h"
|
||||
#include "SectionContent.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QLabel>
|
||||
|
||||
#include "Internal.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
SectionContent::SectionContent() :
|
||||
_uid(GetNextUid()),
|
||||
_flags(AllFlags)
|
||||
{
|
||||
}
|
||||
|
||||
SectionContent::RefPtr SectionContent::newSectionContent(const QString& uniqueName, CMainContainerWidget* container, QWidget* title, QWidget* content)
|
||||
{
|
||||
auto SectionContentNameMap = container->m_SectionContentNameMap;
|
||||
auto SectionContentIdMap = container->m_SectionContentIdMap;
|
||||
|
||||
if (uniqueName.isEmpty())
|
||||
{
|
||||
qFatal("Can not create SectionContent with empty uniqueName");
|
||||
return RefPtr();
|
||||
}
|
||||
else if (SectionContentNameMap.contains(uniqueName))
|
||||
{
|
||||
qFatal("Can not create SectionContent with already used uniqueName");
|
||||
return RefPtr();
|
||||
}
|
||||
else if (!container || !title || !content)
|
||||
{
|
||||
qFatal("Can not create SectionContent with NULL values");
|
||||
return RefPtr();
|
||||
}
|
||||
|
||||
QSharedPointer<SectionContent> sc(new SectionContent());
|
||||
sc->_uniqueName = uniqueName;
|
||||
sc->m_MainContainerWidget = container;
|
||||
sc->m_TitleWidgetContent = title;
|
||||
sc->m_ContentWidget = content;
|
||||
|
||||
SectionContentIdMap.insert(sc->uid(), sc);
|
||||
SectionContentNameMap.insert(sc->uniqueName(), sc);
|
||||
return sc;
|
||||
}
|
||||
|
||||
SectionContent::~SectionContent()
|
||||
{
|
||||
auto SectionContentNameMap = m_MainContainerWidget->m_SectionContentNameMap;
|
||||
auto SectionContentIdMap = m_MainContainerWidget->m_SectionContentIdMap;
|
||||
|
||||
if (m_MainContainerWidget)
|
||||
{
|
||||
SectionContentIdMap.remove(_uid);
|
||||
SectionContentNameMap.remove(_uniqueName);
|
||||
}
|
||||
delete m_TitleWidgetContent;
|
||||
delete m_ContentWidget;
|
||||
}
|
||||
|
||||
int SectionContent::uid() const
|
||||
{
|
||||
return _uid;
|
||||
}
|
||||
|
||||
QString SectionContent::uniqueName() const
|
||||
{
|
||||
return _uniqueName;
|
||||
}
|
||||
|
||||
CMainContainerWidget* SectionContent::containerWidget() const
|
||||
{
|
||||
return m_MainContainerWidget;
|
||||
}
|
||||
|
||||
QWidget* SectionContent::titleWidgetContent() const
|
||||
{
|
||||
return m_TitleWidgetContent;
|
||||
}
|
||||
|
||||
QWidget* SectionContent::contentWidget() const
|
||||
{
|
||||
return m_ContentWidget;
|
||||
}
|
||||
|
||||
SectionContent::Flags SectionContent::flags() const
|
||||
{
|
||||
return _flags;
|
||||
}
|
||||
|
||||
QString SectionContent::visibleTitle() const
|
||||
{
|
||||
if (_title.isEmpty())
|
||||
return _uniqueName;
|
||||
return _title;
|
||||
}
|
||||
|
||||
QString SectionContent::title() const
|
||||
{
|
||||
return _title;
|
||||
}
|
||||
|
||||
void SectionContent::setTitle(const QString& title)
|
||||
{
|
||||
_title = title;
|
||||
}
|
||||
|
||||
void SectionContent::setFlags(const Flags f)
|
||||
{
|
||||
_flags = f;
|
||||
}
|
||||
|
||||
int SectionContent::GetNextUid()
|
||||
{
|
||||
static int NextUid = 0;
|
||||
return ++NextUid;
|
||||
}
|
||||
|
||||
} // namespace ads
|
@ -1,99 +0,0 @@
|
||||
#ifndef SECTIONCONTENT_H
|
||||
#define SECTIONCONTENT_H
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
#include <QSharedPointer>
|
||||
#include <QWeakPointer>
|
||||
#include <QPointer>
|
||||
|
||||
|
||||
class QWidget;
|
||||
|
||||
#include "API.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
class CMainContainerWidget;
|
||||
|
||||
class ADS_EXPORT_API SectionContent
|
||||
{
|
||||
friend class CMainContainerWidget;
|
||||
|
||||
private:
|
||||
SectionContent();
|
||||
SectionContent(const SectionContent&);
|
||||
SectionContent& operator=(const SectionContent&);
|
||||
|
||||
public:
|
||||
typedef QSharedPointer<SectionContent> RefPtr;
|
||||
typedef QWeakPointer<SectionContent> WeakPtr;
|
||||
|
||||
enum Flag
|
||||
{
|
||||
None = 0,
|
||||
Closeable = 1,
|
||||
Maximizable = 2,
|
||||
AllFlags = Closeable | Maximizable
|
||||
};
|
||||
Q_DECLARE_FLAGS(Flags, Flag)
|
||||
|
||||
/*!
|
||||
* Creates new content, associates it to <em>container</em> and takes ownership of
|
||||
* <em>title</em>- and <em>content</em>- widgets.
|
||||
* \param uniqueName An unique identifier across the entire process.
|
||||
* \param container The parent ContainerWidget in which this content will be active.
|
||||
* \param title The widget to use as title.
|
||||
* \param content The widget to use as content.
|
||||
* \return May return a invalid ref-pointer in case of invalid parameters.
|
||||
*/
|
||||
static RefPtr newSectionContent(const QString& uniqueName, CMainContainerWidget* container, QWidget* title, QWidget* content);
|
||||
|
||||
virtual ~SectionContent();
|
||||
int uid() const;
|
||||
QString uniqueName() const;
|
||||
CMainContainerWidget* containerWidget() const;
|
||||
QWidget* titleWidgetContent() const;
|
||||
QWidget* contentWidget() const;
|
||||
Flags flags() const;
|
||||
|
||||
QString visibleTitle() const;
|
||||
QString title() const;
|
||||
void setTitle(const QString& title);
|
||||
void setFlags(const Flags f);
|
||||
|
||||
private:
|
||||
const int _uid;
|
||||
QString _uniqueName;
|
||||
|
||||
QPointer<CMainContainerWidget> m_MainContainerWidget;
|
||||
QPointer<QWidget> m_TitleWidgetContent;
|
||||
QPointer<QWidget> m_ContentWidget;
|
||||
|
||||
// Optional attributes
|
||||
QString _title;
|
||||
Flags _flags;
|
||||
|
||||
/* Note: This method could be a problem in static build environment
|
||||
* since it may begin with 0 for every module which uses ADS.
|
||||
*/
|
||||
static int GetNextUid();
|
||||
};
|
||||
|
||||
} // namespace ads
|
||||
#endif
|
@ -1,167 +0,0 @@
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "MainContainerWidget.h"
|
||||
#include <QBoxLayout>
|
||||
#include "SectionContentWidget.h"
|
||||
#include "SectionTitleWidget.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
struct SectionContentWidgetPrivate
|
||||
{
|
||||
CSectionContentWidget* _this;
|
||||
int Uid;
|
||||
QString UniqueName;
|
||||
QPointer<CMainContainerWidget> MainContainerWidget;
|
||||
QPointer<QWidget> TitleWidgetContent;
|
||||
QPointer<QWidget> ContentWidget;
|
||||
// Optional attributes
|
||||
QString Title;
|
||||
CSectionContentWidget::Flags Flags = CSectionContentWidget::AllFlags;
|
||||
|
||||
|
||||
|
||||
/* Note: This method could be a problem in static build environment
|
||||
* since it may begin with 0 for every module which uses ADS.
|
||||
*/
|
||||
static int GetNextUid()
|
||||
{
|
||||
static int NextUid = 0;
|
||||
return ++NextUid;
|
||||
}
|
||||
|
||||
|
||||
SectionContentWidgetPrivate(CSectionContentWidget* _public)
|
||||
: _this(_public),
|
||||
Uid(GetNextUid())
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
CSectionContentWidget::CSectionContentWidget(SectionContent::RefPtr c, QWidget* parent) :
|
||||
QFrame(parent),
|
||||
d(new SectionContentWidgetPrivate(this)),
|
||||
_content(c)
|
||||
{
|
||||
QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
|
||||
l->setContentsMargins(0, 0, 0, 0);
|
||||
l->setSpacing(0);
|
||||
l->addWidget(_content->contentWidget());
|
||||
setLayout(l);
|
||||
}
|
||||
|
||||
|
||||
CSectionContentWidget* CSectionContentWidget::newSectionContent(const QString& uniqueName,
|
||||
CMainContainerWidget* container, QWidget* title, QWidget* content)
|
||||
{
|
||||
auto SectionContentNameMap = container->m_SectionContentNameMap;
|
||||
auto SectionContentIdMap = container->m_SectionContentIdMap;
|
||||
|
||||
if (uniqueName.isEmpty())
|
||||
{
|
||||
qFatal("Can not create SectionContent with empty uniqueName");
|
||||
return nullptr;
|
||||
}
|
||||
else if (SectionContentNameMap.contains(uniqueName))
|
||||
{
|
||||
qFatal("Can not create SectionContent with already used uniqueName");
|
||||
return nullptr;
|
||||
}
|
||||
else if (!container || !title || !content)
|
||||
{
|
||||
qFatal("Can not create SectionContent with NULL values");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CSectionContentWidget* sc(new CSectionContentWidget());
|
||||
sc->d->UniqueName = uniqueName;
|
||||
sc->d->MainContainerWidget = container;
|
||||
sc->d->TitleWidgetContent = title;
|
||||
sc->d->ContentWidget = content;
|
||||
|
||||
container->m_SectionContentWidgetIdMap.insert(sc->uid(), sc);
|
||||
container->m_SectionContentWidgetNameMap.insert(sc->uniqueName(), sc);
|
||||
return sc;
|
||||
}
|
||||
|
||||
CSectionContentWidget::~CSectionContentWidget()
|
||||
{
|
||||
layout()->removeWidget(_content->contentWidget());
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
||||
int CSectionContentWidget::uid() const
|
||||
{
|
||||
return d->Uid;
|
||||
}
|
||||
|
||||
|
||||
QString CSectionContentWidget::uniqueName() const
|
||||
{
|
||||
return d->UniqueName;
|
||||
}
|
||||
|
||||
|
||||
CMainContainerWidget* CSectionContentWidget::containerWidget() const
|
||||
{
|
||||
return d->MainContainerWidget;
|
||||
}
|
||||
|
||||
QWidget* CSectionContentWidget::titleWidgetContent() const
|
||||
{
|
||||
return d->TitleWidgetContent.data();
|
||||
}
|
||||
|
||||
|
||||
QWidget* CSectionContentWidget::contentWidget() const
|
||||
{
|
||||
return d->ContentWidget;
|
||||
}
|
||||
|
||||
CSectionContentWidget::Flags CSectionContentWidget::flags() const
|
||||
{
|
||||
return d->Flags;
|
||||
}
|
||||
|
||||
|
||||
QString CSectionContentWidget::visibleTitle() const
|
||||
{
|
||||
return d->Title.isEmpty() ? d->UniqueName : d->Title;
|
||||
}
|
||||
|
||||
|
||||
QString CSectionContentWidget::title() const
|
||||
{
|
||||
return d->Title;
|
||||
}
|
||||
|
||||
void CSectionContentWidget::setTitle(const QString& title)
|
||||
{
|
||||
d->Title = title;
|
||||
}
|
||||
|
||||
void CSectionContentWidget::setFlags(const Flags f)
|
||||
{
|
||||
d->Flags = f;
|
||||
}
|
||||
|
||||
} // namespace ads
|
@ -1,85 +0,0 @@
|
||||
#ifndef SECTION_CONTENT_WIDGET_H
|
||||
#define SECTION_CONTENT_WIDGET_H
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
#include <QFrame>
|
||||
|
||||
#include "API.h"
|
||||
#include "SectionContent.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
class CMainContainerWidget;
|
||||
class SectionWidget;
|
||||
class SectionTitleWidget;
|
||||
|
||||
|
||||
struct SectionContentWidgetPrivate;
|
||||
|
||||
|
||||
class CSectionContentWidget : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
SectionContentWidgetPrivate* d;
|
||||
friend class SectionContentWidgetPrivate;
|
||||
friend class CMainContainerWidget;
|
||||
|
||||
public:
|
||||
enum Flag
|
||||
{
|
||||
None = 0,
|
||||
Closeable = 1,
|
||||
Maximizable = 2,
|
||||
AllFlags = Closeable | Maximizable
|
||||
};
|
||||
Q_DECLARE_FLAGS(Flags, Flag)
|
||||
|
||||
CSectionContentWidget(SectionContent::RefPtr c = SectionContent::RefPtr(), QWidget* parent = 0);
|
||||
virtual ~CSectionContentWidget();
|
||||
|
||||
/*!
|
||||
* Creates new content, associates it to <em>container</em> and takes ownership of
|
||||
* <em>title</em>- and <em>content</em>- widgets.
|
||||
* \param uniqueName An unique identifier across the entire process.
|
||||
* \param container The parent ContainerWidget in which this content will be active.
|
||||
* \param title The widget to use as title.
|
||||
* \param content The widget to use as content.
|
||||
* \return May return a invalid ref-pointer in case of invalid parameters.
|
||||
*/
|
||||
static CSectionContentWidget* newSectionContent(const QString& uniqueName,
|
||||
CMainContainerWidget* container, QWidget* title, QWidget* content);
|
||||
|
||||
int uid() const;
|
||||
QString uniqueName() const;
|
||||
CMainContainerWidget* containerWidget() const;
|
||||
QWidget* titleWidgetContent() const;
|
||||
QWidget* contentWidget() const;
|
||||
Flags flags() const;
|
||||
|
||||
QString visibleTitle() const;
|
||||
QString title() const;
|
||||
void setTitle(const QString& title);
|
||||
void setFlags(const Flags f);
|
||||
|
||||
private:
|
||||
SectionContent::RefPtr _content;
|
||||
};
|
||||
|
||||
} // namespace ads
|
||||
#endif
|
@ -1,290 +0,0 @@
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "MainContainerWidget.h"
|
||||
#include "SectionTitleWidget.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QApplication>
|
||||
#include <QBoxLayout>
|
||||
#include <QMouseEvent>
|
||||
#include <QMimeData>
|
||||
#include <QDrag>
|
||||
#include <QCursor>
|
||||
#include <QStyle>
|
||||
#include <QSplitter>
|
||||
#include <QPushButton>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "Internal.h"
|
||||
#include "DropOverlay.h"
|
||||
#include "SectionContent.h"
|
||||
#include "SectionWidget.h"
|
||||
#include "FloatingWidget.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
SectionTitleWidget::SectionTitleWidget(SectionContent::RefPtr content, QWidget* parent) :
|
||||
QFrame(parent),
|
||||
m_Content(content),
|
||||
m_TabMoving(false),
|
||||
m_IsActiveTab(false)
|
||||
{
|
||||
QBoxLayout* l = new QBoxLayout(QBoxLayout::LeftToRight);
|
||||
l->setContentsMargins(0, 0, 0, 0);
|
||||
l->setSpacing(0);
|
||||
l->addWidget(content->titleWidgetContent());
|
||||
setLayout(l);
|
||||
}
|
||||
|
||||
|
||||
SectionTitleWidget::~SectionTitleWidget()
|
||||
{
|
||||
layout()->removeWidget(m_Content->titleWidgetContent());
|
||||
}
|
||||
|
||||
bool SectionTitleWidget::isActiveTab() const
|
||||
{
|
||||
return m_IsActiveTab;
|
||||
}
|
||||
|
||||
void SectionTitleWidget::setActiveTab(bool active)
|
||||
{
|
||||
if (active != m_IsActiveTab)
|
||||
{
|
||||
m_IsActiveTab = active;
|
||||
|
||||
style()->unpolish(this);
|
||||
style()->polish(this);
|
||||
update();
|
||||
|
||||
emit activeTabChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void SectionTitleWidget::mousePressEvent(QMouseEvent* ev)
|
||||
{
|
||||
if (ev->button() == Qt::LeftButton)
|
||||
{
|
||||
ev->accept();
|
||||
m_DragStartMousePosition = ev->pos();
|
||||
m_DragStartGlobalMousePosition = ev->globalPos();
|
||||
m_DragStartPosition = mapToGlobal(this->pos());
|
||||
return;
|
||||
}
|
||||
QFrame::mousePressEvent(ev);
|
||||
}
|
||||
|
||||
|
||||
CContainerWidget* findParentContainerWidget(QWidget* w)
|
||||
{
|
||||
CContainerWidget* cw = 0;
|
||||
QWidget* next = w;
|
||||
do
|
||||
{
|
||||
if ((cw = dynamic_cast<CContainerWidget*>(next)) != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
next = next->parentWidget();
|
||||
}
|
||||
while (next);
|
||||
return cw;
|
||||
}
|
||||
|
||||
SectionWidget* findParentSectionWidget(class QWidget* w)
|
||||
{
|
||||
SectionWidget* cw = 0;
|
||||
QWidget* next = w;
|
||||
do
|
||||
{
|
||||
if ((cw = dynamic_cast<SectionWidget*>(next)) != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
next = next->parentWidget();
|
||||
}
|
||||
while (next);
|
||||
return cw;
|
||||
}
|
||||
|
||||
void SectionTitleWidget::mouseReleaseEvent(QMouseEvent* ev)
|
||||
{
|
||||
SectionWidget* section = nullptr;
|
||||
CContainerWidget* cw = findParentContainerWidget(this);
|
||||
CMainContainerWidget* mcw = cw->mainContainerWidget();
|
||||
std::cout << "SectionTitleWidget::mouseReleaseEvent" << std::endl;
|
||||
|
||||
//m_FloatingWidget.clear();
|
||||
// End of tab moving, change order now
|
||||
if (m_TabMoving && (section = findParentSectionWidget(this)) != nullptr)
|
||||
{
|
||||
// Find tab under mouse
|
||||
QPoint pos = ev->globalPos();
|
||||
pos = section->mapFromGlobal(pos);
|
||||
int fromIndex = section->indexOfContent(m_Content);
|
||||
int toIndex = section->indexOfContentByTitlePos(pos, this);
|
||||
qInfo() << "fromIndex: " << fromIndex << " toIndex: " << toIndex;
|
||||
if (-1 == toIndex)
|
||||
{
|
||||
toIndex = section->indexOfContent(section->contents().last());
|
||||
}
|
||||
section->moveContent(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
if (!m_DragStartMousePosition.isNull())
|
||||
{
|
||||
emit clicked();
|
||||
}
|
||||
|
||||
// Reset
|
||||
m_DragStartMousePosition = QPoint();
|
||||
m_TabMoving = false;
|
||||
mcw->m_SectionDropOverlay->hideDropOverlay();
|
||||
mcw->hideContainerOverlay();
|
||||
QFrame::mouseReleaseEvent(ev);
|
||||
}
|
||||
|
||||
|
||||
void SectionTitleWidget::startFloating(QMouseEvent* ev, CMainContainerWidget* cw, SectionWidget* sectionwidget)
|
||||
{
|
||||
std::cout << "SectionTitleWidget::startFloating" << std::endl;
|
||||
|
||||
FloatingWidget* fw;
|
||||
if (sectionwidget->contentCount() > 1)
|
||||
{
|
||||
// If section widget has multiple tabs, we take only one tab
|
||||
InternalContentData data;
|
||||
if (!sectionwidget->takeContent(m_Content->uid(), data))
|
||||
{
|
||||
qWarning() << "THIS SHOULD NOT HAPPEN!!" << m_Content->uid();
|
||||
return;
|
||||
}
|
||||
fw = new FloatingWidget(cw, data.content, data.titleWidget, data.contentWidget, cw);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If section widget has only one content widget, we can move the complete
|
||||
// section widget into floating widget
|
||||
QSplitter* splitter = findParentSplitter(sectionwidget);
|
||||
fw = new FloatingWidget(cw, sectionwidget);
|
||||
if (splitter && splitter->count() == 1)
|
||||
{
|
||||
// if splitter contains only one section widget, then we can
|
||||
// remove the splitter and replace it with the section widget
|
||||
std::cout << "splitter->count() == 1" << std::endl;
|
||||
SectionWidget* sectionwidget = dynamic_cast<SectionWidget*>(splitter->widget(0));
|
||||
QSplitter* parentSplitter = dynamic_cast<QSplitter*>(splitter->parentWidget());
|
||||
if (parentSplitter)
|
||||
{
|
||||
sectionwidget->setParent(0);
|
||||
int index = parentSplitter->indexOf(splitter);
|
||||
splitter->setParent(0);
|
||||
parentSplitter->insertWidget(index, sectionwidget);
|
||||
delete splitter;
|
||||
std::cout << "Index of splitter " << index << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fw->resize(sectionwidget->size());
|
||||
fw->setObjectName("FloatingWidget");
|
||||
fw->startFloating(m_DragStartMousePosition);
|
||||
|
||||
// Delete old section, if it is empty now.
|
||||
if (sectionwidget->contents().isEmpty())
|
||||
{
|
||||
delete sectionwidget;
|
||||
sectionwidget = NULL;
|
||||
}
|
||||
deleteEmptySplitter(cw);
|
||||
|
||||
DropOverlay* ContainerDropOverlay = cw->dropOverlay();
|
||||
ContainerDropOverlay->setAllowedAreas(OuterAreas);
|
||||
ContainerDropOverlay->showDropOverlay(this);
|
||||
ContainerDropOverlay->raise();
|
||||
}
|
||||
|
||||
|
||||
void SectionTitleWidget::moveTab(QMouseEvent* ev)
|
||||
{
|
||||
ev->accept();
|
||||
int left, top, right, bottom;
|
||||
getContentsMargins(&left, &top, &right, &bottom);
|
||||
QPoint moveToPos = mapToParent(ev->pos()) - m_DragStartMousePosition;
|
||||
moveToPos.setY(0/* + top*/);
|
||||
move(moveToPos);
|
||||
}
|
||||
|
||||
|
||||
void SectionTitleWidget::mouseMoveEvent(QMouseEvent* ev)
|
||||
{
|
||||
std::cout << "SectionTitleWidget::mouseMoveEvent" << std::endl;
|
||||
if (!(ev->buttons() & Qt::LeftButton))
|
||||
{
|
||||
QFrame::mouseMoveEvent(ev);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO make a member with the main container widget and assign it on
|
||||
// creation
|
||||
CMainContainerWidget* MainContainerWidget = findParentContainerWidget(this)->mainContainerWidget();
|
||||
ev->accept();
|
||||
|
||||
|
||||
SectionWidget* sectionwidget = findParentSectionWidget(this);
|
||||
if (!sectionwidget)
|
||||
{
|
||||
QFrame::mouseMoveEvent(ev);
|
||||
return;
|
||||
}
|
||||
|
||||
// move tab
|
||||
if (m_TabMoving)
|
||||
{
|
||||
moveTab(ev);
|
||||
}
|
||||
|
||||
// leave if dragging is not active
|
||||
if (m_DragStartMousePosition.isNull())
|
||||
{
|
||||
QFrame::mouseMoveEvent(ev);
|
||||
return;
|
||||
}
|
||||
|
||||
// Begin to drag/float the SectionContent.
|
||||
if (!sectionwidget->titleAreaGeometry().contains(sectionwidget->mapFromGlobal(ev->globalPos())))
|
||||
{
|
||||
startFloating(ev, MainContainerWidget, sectionwidget);
|
||||
return;
|
||||
}
|
||||
// Begin to drag title inside the title area to switch its position inside the SectionWidget.
|
||||
else if ((ev->pos() - m_DragStartMousePosition).manhattanLength() >= QApplication::startDragDistance() // Wait a few pixels before start moving
|
||||
&& sectionwidget->titleAreaGeometry().contains(sectionwidget->mapFromGlobal(ev->globalPos())))
|
||||
{
|
||||
m_TabMoving = true;
|
||||
//raise(); // Raise current title-widget above other tabs
|
||||
return;
|
||||
}
|
||||
QFrame::mouseMoveEvent(ev);
|
||||
}
|
||||
|
||||
} // namespace ads
|
@ -1,80 +0,0 @@
|
||||
#ifndef SECTION_TITLE_WIDGET_H
|
||||
#define SECTION_TITLE_WIDGET_H
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
#include <QPointer>
|
||||
#include <QPoint>
|
||||
#include <QFrame>
|
||||
|
||||
#include "API.h"
|
||||
#include "SectionContent.h"
|
||||
|
||||
class QPushButton;
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
class CMainContainerWidget;
|
||||
class SectionWidget;
|
||||
class FloatingWidget;
|
||||
|
||||
class SectionTitleWidget : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool activeTab READ isActiveTab WRITE setActiveTab NOTIFY activeTabChanged)
|
||||
|
||||
friend class CMainContainerWidget;
|
||||
friend class SectionWidget;
|
||||
friend class CContainerWidget;
|
||||
|
||||
SectionContent::RefPtr m_Content;
|
||||
|
||||
// Drag & Drop (Floating)
|
||||
QPoint m_DragStartMousePosition;
|
||||
QPoint m_DragStartGlobalMousePosition;
|
||||
QPoint m_DragStartPosition;
|
||||
|
||||
// Drag & Drop (Title/Tabs)
|
||||
bool m_TabMoving;
|
||||
|
||||
// Property values
|
||||
bool m_IsActiveTab;
|
||||
|
||||
public:
|
||||
SectionTitleWidget(SectionContent::RefPtr content, QWidget* parent);
|
||||
virtual ~SectionTitleWidget();
|
||||
|
||||
bool isActiveTab() const;
|
||||
void setActiveTab(bool active);
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent* ev);
|
||||
virtual void mouseReleaseEvent(QMouseEvent* ev);
|
||||
virtual void mouseMoveEvent(QMouseEvent* ev);
|
||||
|
||||
private:
|
||||
void startFloating(QMouseEvent* ev, CMainContainerWidget* cw, SectionWidget* sectionwidget);
|
||||
void moveTab(QMouseEvent* ev);
|
||||
|
||||
signals:
|
||||
void activeTabChanged();
|
||||
void clicked();
|
||||
};
|
||||
|
||||
} // namepsace ads
|
||||
#endif
|
@ -1,495 +0,0 @@
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "SectionWidget.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QBoxLayout>
|
||||
#include <QStackedLayout>
|
||||
#include <QMouseEvent>
|
||||
#include <QWheelEvent>
|
||||
#include <QDragEnterEvent>
|
||||
#include <QMimeData>
|
||||
#include <QPainter>
|
||||
#include <QStyle>
|
||||
#include <QSplitter>
|
||||
#include <QPushButton>
|
||||
#include <QScrollBar>
|
||||
#include <QMenu>
|
||||
#include <QtGlobal>
|
||||
#include <QTabBar>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "Internal.h"
|
||||
#include "DropOverlay.h"
|
||||
#include "SectionContent.h"
|
||||
#include "SectionTitleWidget.h"
|
||||
#include "SectionContentWidget.h"
|
||||
#include "FloatingWidget.h"
|
||||
#include "MainContainerWidget.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
SectionWidget::SectionWidget(CMainContainerWidget* MainContainer, CContainerWidget* parent) :
|
||||
QFrame(parent),
|
||||
_uid(GetNextUid()),
|
||||
m_MainContainerWidget(MainContainer),
|
||||
_tabsLayout(NULL),
|
||||
_tabsLayoutInitCount(0),
|
||||
_contentsLayout(NULL),
|
||||
_mousePressTitleWidget(NULL)
|
||||
{
|
||||
QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
|
||||
l->setContentsMargins(0, 0, 0, 0);
|
||||
l->setSpacing(0);
|
||||
setLayout(l);
|
||||
|
||||
/* top area with tabs and close button */
|
||||
_topLayout = new QBoxLayout(QBoxLayout::LeftToRight);
|
||||
_topLayout->setContentsMargins(0, 0, 0, 0);
|
||||
_topLayout->setSpacing(0);
|
||||
l->addLayout(_topLayout);
|
||||
|
||||
_tabsScrollArea = new SectionWidgetTabsScrollArea(this);
|
||||
_topLayout->addWidget(_tabsScrollArea, 1);
|
||||
|
||||
_tabsContainerWidget = new QWidget();
|
||||
_tabsContainerWidget->setObjectName("tabsContainerWidget");
|
||||
_tabsScrollArea->setWidget(_tabsContainerWidget);
|
||||
|
||||
_tabsLayout = new QBoxLayout(QBoxLayout::LeftToRight);
|
||||
_tabsLayout->setContentsMargins(0, 0, 0, 0);
|
||||
_tabsLayout->setSpacing(0);
|
||||
_tabsLayout->addStretch(1);
|
||||
_tabsContainerWidget->setLayout(_tabsLayout);
|
||||
|
||||
_tabsMenuButton = new QPushButton();
|
||||
_tabsMenuButton->setObjectName("tabsMenuButton");
|
||||
_tabsMenuButton->setFlat(true);
|
||||
_tabsMenuButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarUnshadeButton));
|
||||
_tabsMenuButton->setMaximumWidth(_tabsMenuButton->iconSize().width());
|
||||
_topLayout->addWidget(_tabsMenuButton, 0);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
//QObject::connect(_tabsMenuButton, &QPushButton::clicked, this, &SectionWidget::onTabsMenuButtonClicked);
|
||||
#else
|
||||
//QObject::connect(_tabsMenuButton, SIGNAL(clicked()), this, SLOT(onTabsMenuButtonClicked()));
|
||||
#endif
|
||||
|
||||
_closeButton = new QPushButton();
|
||||
_closeButton->setObjectName("closeButton");
|
||||
_closeButton->setFlat(true);
|
||||
_closeButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton));
|
||||
_closeButton->setToolTip(tr("Close"));
|
||||
_closeButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
_topLayout->addWidget(_closeButton, 0);
|
||||
connect(_closeButton, SIGNAL(clicked(bool)), this, SLOT(onCloseButtonClicked()));
|
||||
|
||||
_tabsLayoutInitCount = _tabsLayout->count();
|
||||
|
||||
/* central area with contents */
|
||||
|
||||
_contentsLayout = new QStackedLayout();
|
||||
_contentsLayout->setContentsMargins(0, 0, 0, 0);
|
||||
_contentsLayout->setSpacing(0);
|
||||
l->addLayout(_contentsLayout, 1);
|
||||
|
||||
m_MainContainerWidget->m_SectionWidgetIdMap.insert(_uid, this);
|
||||
}
|
||||
|
||||
SectionWidget::~SectionWidget()
|
||||
{
|
||||
if (m_MainContainerWidget)
|
||||
{
|
||||
m_MainContainerWidget->m_SectionWidgetIdMap.remove(_uid);
|
||||
m_MainContainerWidget->m_Sections.removeAll(this); // Note: I don't like this here, but we have to remove it from list...
|
||||
}
|
||||
|
||||
// Delete empty QSplitter.
|
||||
QSplitter* splitter = findParentSplitter(this);
|
||||
if (splitter && splitter->count() == 0)
|
||||
{
|
||||
splitter->deleteLater();
|
||||
}
|
||||
|
||||
std::cout << "SectionWidget::~SectionWidget()" << std::endl;
|
||||
}
|
||||
|
||||
int SectionWidget::uid() const
|
||||
{
|
||||
return _uid;
|
||||
}
|
||||
|
||||
CContainerWidget* SectionWidget::containerWidget() const
|
||||
{
|
||||
QWidget* Parent = parentWidget();
|
||||
while (Parent)
|
||||
{
|
||||
CContainerWidget* Container = dynamic_cast<CContainerWidget*>(Parent);
|
||||
if (Container)
|
||||
{
|
||||
return Container;
|
||||
}
|
||||
Parent = Parent->parentWidget();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QRect SectionWidget::titleAreaGeometry() const
|
||||
{
|
||||
return _topLayout->geometry();
|
||||
}
|
||||
|
||||
QRect SectionWidget::contentAreaGeometry() const
|
||||
{
|
||||
return _contentsLayout->geometry();
|
||||
}
|
||||
|
||||
void SectionWidget::addContent(const SectionContent::RefPtr& c)
|
||||
{
|
||||
m_Contents.append(c);
|
||||
|
||||
SectionTitleWidget* title = new SectionTitleWidget(c, NULL);
|
||||
m_TitleWidgets.append(title);
|
||||
_tabsLayout->insertWidget(_tabsLayout->count() - _tabsLayoutInitCount, title);
|
||||
QObject::connect(title, SIGNAL(clicked()), this, SLOT(onSectionTitleClicked()));
|
||||
|
||||
CSectionContentWidget* content = new CSectionContentWidget(c, NULL);
|
||||
m_ContentWidgets.append(content);
|
||||
_contentsLayout->addWidget(content);
|
||||
|
||||
// Active first TAB.
|
||||
if (m_Contents.size() == 1)
|
||||
setCurrentIndex(0);
|
||||
// Switch to newest.
|
||||
// else
|
||||
// setCurrentIndex(_contentsLayout->count() - 1);
|
||||
|
||||
updateTabsMenu();
|
||||
}
|
||||
|
||||
void SectionWidget::addContent(const InternalContentData& data, bool autoActivate)
|
||||
{
|
||||
m_Contents.append(data.content);
|
||||
|
||||
// Add title-widget to tab-bar
|
||||
// #FIX: Make it visible, since it is possible that it was hidden previously.
|
||||
m_TitleWidgets.append(data.titleWidget);
|
||||
_tabsLayout->insertWidget(_tabsLayout->count() - _tabsLayoutInitCount, data.titleWidget);
|
||||
data.titleWidget->setVisible(true);
|
||||
QObject::connect(data.titleWidget, SIGNAL(clicked()), this, SLOT(onSectionTitleClicked()));
|
||||
|
||||
// Add content-widget to stack.
|
||||
// Visibility is managed by QStackedWidget.
|
||||
m_ContentWidgets.append(data.contentWidget);
|
||||
_contentsLayout->addWidget(data.contentWidget);
|
||||
|
||||
// Activate first TAB.
|
||||
if (m_Contents.size() == 1)
|
||||
setCurrentIndex(0);
|
||||
// Switch to just added TAB.
|
||||
else if (autoActivate)
|
||||
setCurrentIndex(m_Contents.count() - 1);
|
||||
// Mark it as inactive tab.
|
||||
else
|
||||
data.titleWidget->setActiveTab(false); // or: setCurrentIndex(currentIndex())
|
||||
|
||||
updateTabsMenu();
|
||||
}
|
||||
|
||||
bool SectionWidget::takeContent(int uid, InternalContentData& data)
|
||||
{
|
||||
for (int i = 0; i < m_Contents.count(); i++)
|
||||
{
|
||||
if (m_Contents[i]->uid() != uid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return takeContentAt(i, data);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SectionWidget::takeContentAt(int index, InternalContentData& data)
|
||||
{
|
||||
SectionContent::RefPtr sc = m_Contents.takeAt(index);
|
||||
if (!sc)
|
||||
return false;
|
||||
|
||||
// Title wrapper widget (TAB)
|
||||
SectionTitleWidget* title = m_TitleWidgets.takeAt(index);
|
||||
if (title)
|
||||
{
|
||||
_tabsLayout->removeWidget(title);
|
||||
title->disconnect(this);
|
||||
title->setParent(m_MainContainerWidget);
|
||||
}
|
||||
|
||||
// Content wrapper widget (CONTENT)
|
||||
CSectionContentWidget* content = m_ContentWidgets.takeAt(index);
|
||||
if (content)
|
||||
{
|
||||
_contentsLayout->removeWidget(content);
|
||||
content->disconnect(this);
|
||||
content->setParent(m_MainContainerWidget);
|
||||
}
|
||||
|
||||
// Select the previous tab as activeTab.
|
||||
if (m_Contents.size() > 0 && title->isActiveTab())
|
||||
{
|
||||
if (index > 0)
|
||||
setCurrentIndex(index - 1);
|
||||
else
|
||||
setCurrentIndex(0);
|
||||
}
|
||||
|
||||
updateTabsMenu();
|
||||
|
||||
data.content = sc;
|
||||
data.titleWidget = title;
|
||||
data.contentWidget = content;
|
||||
return !data.content.isNull();
|
||||
}
|
||||
|
||||
|
||||
int SectionWidget::indexOfContent(const SectionContent::RefPtr& c) const
|
||||
{
|
||||
return m_Contents.indexOf(c);
|
||||
}
|
||||
|
||||
int SectionWidget::indexOfContentByUid(int uid) const
|
||||
{
|
||||
for (int i = 0; i < m_Contents.count(); ++i)
|
||||
{
|
||||
if (m_Contents[i]->uid() == uid)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SectionWidget::indexOfContentByTitlePos(const QPoint& p, QWidget* exclude) const
|
||||
{
|
||||
int index = -1;
|
||||
for (int i = 0; i < m_TitleWidgets.size(); ++i)
|
||||
{
|
||||
if (m_TitleWidgets[i]->geometry().contains(p) && (exclude == NULL || m_TitleWidgets[i] != exclude))
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
int SectionWidget::currentIndex() const
|
||||
{
|
||||
return _contentsLayout->currentIndex();
|
||||
}
|
||||
|
||||
void SectionWidget::moveContent(int from, int to)
|
||||
{
|
||||
if (from >= m_Contents.size() || from < 0 || to >= m_Contents.size() || to < 0 || from == to)
|
||||
{
|
||||
qDebug() << "Invalid index for tab movement" << from << to;
|
||||
_tabsLayout->update();
|
||||
return;
|
||||
}
|
||||
|
||||
m_Contents.move(from, to);
|
||||
m_TitleWidgets.move(from, to);
|
||||
m_ContentWidgets.move(from, to);
|
||||
|
||||
QLayoutItem* liFrom = NULL;
|
||||
liFrom = _tabsLayout->takeAt(from);
|
||||
_tabsLayout->insertItem(to, liFrom);
|
||||
liFrom = _contentsLayout->takeAt(from);
|
||||
_contentsLayout->insertWidget(to, liFrom->widget());
|
||||
delete liFrom;
|
||||
|
||||
updateTabsMenu();
|
||||
}
|
||||
|
||||
void SectionWidget::showEvent(QShowEvent*)
|
||||
{
|
||||
_tabsScrollArea->ensureWidgetVisible(m_TitleWidgets.at(currentIndex()));
|
||||
}
|
||||
|
||||
void SectionWidget::setCurrentIndex(int index)
|
||||
{
|
||||
if (index < 0 || index > m_Contents.count() - 1)
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO << "Invalid index" << index;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set active TAB
|
||||
for (int i = 0; i < _tabsLayout->count(); ++i)
|
||||
{
|
||||
QLayoutItem* item = _tabsLayout->itemAt(i);
|
||||
if (item->widget())
|
||||
{
|
||||
SectionTitleWidget* stw = dynamic_cast<SectionTitleWidget*>(item->widget());
|
||||
if (stw)
|
||||
{
|
||||
if (i == index)
|
||||
{
|
||||
stw->setActiveTab(true);
|
||||
_tabsScrollArea->ensureWidgetVisible(stw);
|
||||
if (stw->m_Content->flags().testFlag(SectionContent::Closeable))
|
||||
_closeButton->setEnabled(true);
|
||||
else
|
||||
_closeButton->setEnabled(false);
|
||||
}
|
||||
else
|
||||
stw->setActiveTab(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set active CONTENT
|
||||
_contentsLayout->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void SectionWidget::onSectionTitleClicked()
|
||||
{
|
||||
SectionTitleWidget* stw = qobject_cast<SectionTitleWidget*>(sender());
|
||||
if (stw)
|
||||
{
|
||||
int index = _tabsLayout->indexOf(stw);
|
||||
setCurrentIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
void SectionWidget::onCloseButtonClicked()
|
||||
{
|
||||
const int index = currentIndex();
|
||||
if (index < 0 || index > m_Contents.size() - 1)
|
||||
return;
|
||||
SectionContent::RefPtr sc = m_Contents.at(index);
|
||||
if (sc.isNull())
|
||||
return;
|
||||
m_MainContainerWidget->hideSectionContent(sc);
|
||||
}
|
||||
|
||||
void SectionWidget::onTabsMenuActionTriggered(bool)
|
||||
{
|
||||
QAction* a = qobject_cast<QAction*>(sender());
|
||||
if (a)
|
||||
{
|
||||
const int uid = a->data().toInt();
|
||||
const int index = indexOfContentByUid(uid);
|
||||
if (index >= 0)
|
||||
setCurrentIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
void SectionWidget::updateTabsMenu()
|
||||
{
|
||||
QMenu* m = new QMenu();
|
||||
for (int i = 0; i < m_Contents.count(); ++i)
|
||||
{
|
||||
const SectionContent::RefPtr& sc = m_Contents.at(i);
|
||||
QAction* a = m->addAction(QIcon(), sc->visibleTitle());
|
||||
a->setData(sc->uid());
|
||||
QObject::connect(a, SIGNAL(triggered(bool)), this, SLOT(onTabsMenuActionTriggered(bool)));
|
||||
}
|
||||
QMenu* old = _tabsMenuButton->menu();
|
||||
_tabsMenuButton->setMenu(m);
|
||||
delete old;
|
||||
}
|
||||
|
||||
int SectionWidget::GetNextUid()
|
||||
{
|
||||
static int NextUid = 0;
|
||||
return ++NextUid;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
SectionWidgetTabsScrollArea::SectionWidgetTabsScrollArea(SectionWidget*,
|
||||
QWidget* parent) :
|
||||
QScrollArea(parent)
|
||||
{
|
||||
/* Important: QSizePolicy::Ignored makes the QScrollArea behaves
|
||||
like a QLabel and automatically fits into the layout. */
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
|
||||
setFrameStyle(QFrame::NoFrame);
|
||||
setWidgetResizable(true);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
}
|
||||
|
||||
SectionWidgetTabsScrollArea::~SectionWidgetTabsScrollArea()
|
||||
{
|
||||
}
|
||||
|
||||
void SectionWidgetTabsScrollArea::wheelEvent(QWheelEvent* e)
|
||||
{
|
||||
e->accept();
|
||||
const int direction = e->angleDelta().y();
|
||||
if (direction < 0)
|
||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + 20);
|
||||
else
|
||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - 20);
|
||||
}
|
||||
|
||||
|
||||
void SectionWidgetTabsScrollArea::mousePressEvent(QMouseEvent* ev)
|
||||
{
|
||||
qInfo() << "mousePressEvent " << ev->type();
|
||||
if (ev->button() == Qt::LeftButton)
|
||||
{
|
||||
ev->accept();
|
||||
_dragStartPos = ev->pos();
|
||||
return;
|
||||
}
|
||||
QScrollArea::mousePressEvent(ev);
|
||||
}
|
||||
|
||||
void SectionWidgetTabsScrollArea::mouseMoveEvent(QMouseEvent* ev)
|
||||
{
|
||||
/*if (_fw)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ContainerWidget* cw = findParentContainerWidget(this);
|
||||
SectionWidget* sectionWidget = findParentSectionWidget(this);
|
||||
|
||||
qInfo() << "mousePressEvent " << ev->type();
|
||||
ev->accept();
|
||||
|
||||
_fw = new FloatingWidget(sectionWidget);
|
||||
_fw->resize(sectionWidget->size());
|
||||
cw->_floatings.append(_fw); // Note: I don't like this...
|
||||
|
||||
const QPoint moveToPos = ev->globalPos() - (_dragStartPos + QPoint(ADS_WINDOW_FRAME_BORDER_WIDTH, ADS_WINDOW_FRAME_BORDER_WIDTH));
|
||||
_fw->move(moveToPos);
|
||||
_fw->show();
|
||||
|
||||
//delete sectionWidget;
|
||||
deleteEmptySplitter(cw);*/
|
||||
QScrollArea::mouseMoveEvent(ev);
|
||||
return;
|
||||
}
|
||||
|
||||
} // namespace ads
|
@ -1,130 +0,0 @@
|
||||
#ifndef SECTION_WIDGET_H
|
||||
#define SECTION_WIDGET_H
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
#include <QDebug>
|
||||
#include <QPointer>
|
||||
#include <QList>
|
||||
#include <QFrame>
|
||||
#include <QScrollArea>
|
||||
|
||||
class QBoxLayout;
|
||||
class QStackedLayout;
|
||||
class QPushButton;
|
||||
class QMenu;
|
||||
|
||||
#include "API.h"
|
||||
#include "Internal.h"
|
||||
#include "SectionContent.h"
|
||||
#include "FloatingWidget.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
class CMainContainerWidget;
|
||||
class SectionTitleWidget;
|
||||
class CSectionContentWidget;
|
||||
|
||||
// SectionWidget manages multiple instances of SectionContent.
|
||||
// It displays a title TAB, which is clickable and will switch to
|
||||
// the contents associated to the title when clicked.
|
||||
class ADS_EXPORT_API SectionWidget : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class CMainContainerWidget;
|
||||
friend class CContainerWidget;
|
||||
|
||||
explicit SectionWidget(CMainContainerWidget* MainContainer, CContainerWidget* parent);
|
||||
|
||||
public:
|
||||
virtual ~SectionWidget();
|
||||
|
||||
int uid() const;
|
||||
CContainerWidget* containerWidget() const;
|
||||
|
||||
QRect titleAreaGeometry() const;
|
||||
QRect contentAreaGeometry() const;
|
||||
|
||||
const QList<SectionContent::RefPtr>& contents() const { return m_Contents; }
|
||||
void addContent(const SectionContent::RefPtr& c);
|
||||
void addContent(const InternalContentData& data, bool autoActivate);
|
||||
bool takeContent(int uid, InternalContentData& data);
|
||||
bool takeContentAt(int Index, InternalContentData& data);
|
||||
int indexOfContent(const SectionContent::RefPtr& c) const;
|
||||
int indexOfContentByUid(int uid) const;
|
||||
int indexOfContentByTitlePos(const QPoint& pos, QWidget* exclude = NULL) const;
|
||||
|
||||
int currentIndex() const;
|
||||
void moveContent(int from, int to);
|
||||
|
||||
inline int contentCount() const {return m_ContentWidgets.size();}
|
||||
|
||||
protected:
|
||||
virtual void showEvent(QShowEvent*);
|
||||
|
||||
public slots:
|
||||
void setCurrentIndex(int index);
|
||||
|
||||
private slots:
|
||||
void onSectionTitleClicked();
|
||||
void onCloseButtonClicked();
|
||||
void onTabsMenuActionTriggered(bool);
|
||||
void updateTabsMenu();
|
||||
|
||||
|
||||
private:
|
||||
const int _uid;
|
||||
QPointer<CMainContainerWidget> m_MainContainerWidget;
|
||||
QList<SectionContent::RefPtr> m_Contents;
|
||||
QList<SectionTitleWidget*> m_TitleWidgets;
|
||||
QList<CSectionContentWidget*> m_ContentWidgets;
|
||||
|
||||
QBoxLayout* _topLayout;
|
||||
QScrollArea* _tabsScrollArea;
|
||||
QWidget* _tabsContainerWidget;
|
||||
QBoxLayout* _tabsLayout;
|
||||
QPushButton* _tabsMenuButton;
|
||||
QPushButton* _closeButton;
|
||||
int _tabsLayoutInitCount; // used for calculations on _tabsLayout modification calls.
|
||||
|
||||
QStackedLayout *_contentsLayout;
|
||||
|
||||
QPoint _mousePressPoint;
|
||||
SectionContent::RefPtr _mousePressContent;
|
||||
SectionTitleWidget* _mousePressTitleWidget;
|
||||
|
||||
static int GetNextUid();
|
||||
};
|
||||
|
||||
/* Custom scrollable implementation for tabs */
|
||||
class SectionWidgetTabsScrollArea : public QScrollArea
|
||||
{
|
||||
public:
|
||||
SectionWidgetTabsScrollArea(SectionWidget* sectionWidget, QWidget* parent = NULL);
|
||||
virtual ~SectionWidgetTabsScrollArea();
|
||||
|
||||
protected:
|
||||
QPoint _dragStartPos;
|
||||
QPointer<FloatingWidget> _fw;
|
||||
virtual void wheelEvent(QWheelEvent*);
|
||||
virtual void mousePressEvent(QMouseEvent* ev);
|
||||
virtual void mouseMoveEvent(QMouseEvent* ev);
|
||||
};
|
||||
|
||||
} // namespace ads
|
||||
#endif
|
@ -1,459 +0,0 @@
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "Serialization.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
/*
|
||||
\namespace ads::serialization
|
||||
|
||||
Serialization of ContainerWidget
|
||||
--------------------------------
|
||||
|
||||
# Data Format Header
|
||||
|
||||
quint32 Magic
|
||||
quint32 Major Version
|
||||
quint32 Minor Version
|
||||
|
||||
# Offsets of available contents
|
||||
|
||||
qint32 Number of offset headers
|
||||
LOOP
|
||||
qint32 Type (e.g. Hierachy, SectionIndex)
|
||||
qint64 Offset
|
||||
qint64 Length
|
||||
|
||||
# Type: Hierachy
|
||||
# Used to recreate the GUI geometry and state.
|
||||
|
||||
int Number of floating widgets
|
||||
LOOP Floating widgets
|
||||
QString Unique name of content
|
||||
QByteArray Geometry of floating widget
|
||||
bool Visibility
|
||||
|
||||
int Number of layout items (Valid values: 0, 1)
|
||||
IF 0
|
||||
int Number of hidden contents
|
||||
LOOP Contents
|
||||
QString Unique name of content
|
||||
ELSEIF 1
|
||||
... todo ...
|
||||
ENDIF
|
||||
|
||||
# Type: SectionIndex
|
||||
# Can be used for quick lookups on details for SectionWidgets.
|
||||
# It includes sizes and its contents.
|
||||
|
||||
qint32 Number of section-widgets
|
||||
LOOP
|
||||
qint32 Width
|
||||
qint32 Height
|
||||
qint32 Current active tab index
|
||||
qint32 Number of contents
|
||||
LOOP
|
||||
QString Unique name of content
|
||||
bool Visibility
|
||||
qint32 Preferred tab index
|
||||
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
qint32 HeaderEntity::MAGIC = 0x00001337;
|
||||
qint32 HeaderEntity::MAJOR_VERSION = 2;
|
||||
qint32 HeaderEntity::MINOR_VERSION = 0;
|
||||
|
||||
HeaderEntity::HeaderEntity() :
|
||||
magic(0), majorVersion(0), minorVersion(0)
|
||||
{
|
||||
}
|
||||
|
||||
QDataStream& operator<<(QDataStream& out, const HeaderEntity& data)
|
||||
{
|
||||
out << data.magic;
|
||||
out << data.majorVersion;
|
||||
out << data.minorVersion;
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream& operator>>(QDataStream& in, HeaderEntity& data)
|
||||
{
|
||||
in >> data.magic;
|
||||
in >> data.majorVersion;
|
||||
in >> data.minorVersion;
|
||||
return in;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OffsetsHeaderEntity::OffsetsHeaderEntity() :
|
||||
entriesCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
QDataStream& operator<<(QDataStream& out, const OffsetsHeaderEntity& data)
|
||||
{
|
||||
out << data.entriesCount;
|
||||
for (int i = 0; i < data.entriesCount; ++i)
|
||||
{
|
||||
out << data.entries.at(i);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream& operator>>(QDataStream& in, OffsetsHeaderEntity& data)
|
||||
{
|
||||
in >> data.entriesCount;
|
||||
for (int i = 0; i < data.entriesCount; ++i)
|
||||
{
|
||||
OffsetsHeaderEntryEntity entry;
|
||||
in >> entry;
|
||||
data.entries.append(entry);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OffsetsHeaderEntryEntity::OffsetsHeaderEntryEntity() :
|
||||
type(ET_Unknown), offset(0), contentSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
QDataStream& operator<<(QDataStream& out, const OffsetsHeaderEntryEntity& data)
|
||||
{
|
||||
out << data.type;
|
||||
out << data.offset;
|
||||
out << data.contentSize;
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream& operator>>(QDataStream& in, OffsetsHeaderEntryEntity& data)
|
||||
{
|
||||
in >> data.type;
|
||||
in >> data.offset;
|
||||
in >> data.contentSize;
|
||||
return in;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SectionEntity::SectionEntity() :
|
||||
x(0), y(0), width(0), height(0), currentIndex(0), sectionContentsCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
QDataStream& operator<<(QDataStream& out, const SectionEntity& data)
|
||||
{
|
||||
out << data.x;
|
||||
out << data.y;
|
||||
out << data.width;
|
||||
out << data.height;
|
||||
out << data.currentIndex;
|
||||
out << data.sectionContentsCount;
|
||||
for (int i = 0; i < data.sectionContentsCount; ++i)
|
||||
{
|
||||
out << data.sectionContents.at(i);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream& operator>>(QDataStream& in, SectionEntity& data)
|
||||
{
|
||||
in >> data.x;
|
||||
in >> data.y;
|
||||
in >> data.width;
|
||||
in >> data.height;
|
||||
in >> data.currentIndex;
|
||||
in >> data.sectionContentsCount;
|
||||
for (int i = 0; i < data.sectionContentsCount; ++i)
|
||||
{
|
||||
SectionContentEntity sc;
|
||||
in >> sc;
|
||||
data.sectionContents.append(sc);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SectionContentEntity::SectionContentEntity() :
|
||||
visible(false), preferredIndex(0)
|
||||
{
|
||||
}
|
||||
|
||||
QDataStream& operator<<(QDataStream& out, const SectionContentEntity& data)
|
||||
{
|
||||
out << data.uniqueName;
|
||||
out << data.visible;
|
||||
out << data.preferredIndex;
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream& operator>>(QDataStream& in, SectionContentEntity& data)
|
||||
{
|
||||
in >> data.uniqueName;
|
||||
in >> data.visible;
|
||||
in >> data.preferredIndex;
|
||||
return in;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FloatingContentEntity::FloatingContentEntity() :
|
||||
xpos(0), ypos(0), width(0), height(0), visible(false)
|
||||
{
|
||||
}
|
||||
|
||||
QDataStream& operator<<(QDataStream& out, const FloatingContentEntity& data)
|
||||
{
|
||||
out << data.uniqueName;
|
||||
out << data.xpos;
|
||||
out << data.ypos;
|
||||
out << data.width;
|
||||
out << data.height;
|
||||
out << data.visible;
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream& operator>>(QDataStream& in, FloatingContentEntity& data)
|
||||
{
|
||||
in >> data.uniqueName;
|
||||
in >> data.xpos;
|
||||
in >> data.ypos;
|
||||
in >> data.width;
|
||||
in >> data.height;
|
||||
in >> data.visible;
|
||||
return in;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HierarchyData::HierarchyData()
|
||||
{
|
||||
}
|
||||
|
||||
QDataStream& operator<<(QDataStream& out, const HierarchyData& data)
|
||||
{
|
||||
out << data.data;
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream& operator>>(QDataStream& in, HierarchyData& data)
|
||||
{
|
||||
in >> data.data;
|
||||
return in;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SectionIndexData::SectionIndexData() :
|
||||
sectionsCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
QDataStream& operator<<(QDataStream& out, const SectionIndexData& data)
|
||||
{
|
||||
out << data.sectionsCount;
|
||||
for (int i = 0; i < data.sectionsCount; ++i)
|
||||
{
|
||||
out << data.sections.at(i);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream& operator>>(QDataStream& in, SectionIndexData& data)
|
||||
{
|
||||
in >> data.sectionsCount;
|
||||
for (int i = 0; i < data.sectionsCount; ++i)
|
||||
{
|
||||
SectionEntity s;
|
||||
in >> s;
|
||||
data.sections.append(s);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
InMemoryWriter::InMemoryWriter()
|
||||
{
|
||||
_contentBuffer.open(QIODevice::ReadWrite);
|
||||
}
|
||||
|
||||
bool InMemoryWriter::write(qint32 entryType, const QByteArray& data)
|
||||
{
|
||||
OffsetsHeaderEntryEntity entry;
|
||||
entry.type = entryType;
|
||||
entry.offset = _contentBuffer.pos(); // Relative offset!
|
||||
entry.contentSize = data.size();
|
||||
|
||||
_contentBuffer.write(data);
|
||||
|
||||
_offsetsHeader.entries.append(entry);
|
||||
_offsetsHeader.entriesCount += 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InMemoryWriter::write(const SectionIndexData& data)
|
||||
{
|
||||
OffsetsHeaderEntryEntity entry;
|
||||
entry.type = ET_SectionIndex;
|
||||
entry.offset = _contentBuffer.pos(); // Relative offset!
|
||||
|
||||
QDataStream out(&_contentBuffer);
|
||||
out.setVersion(QDataStream::Qt_4_5);
|
||||
out << data;
|
||||
|
||||
entry.contentSize = _contentBuffer.size() - entry.offset;
|
||||
|
||||
_offsetsHeader.entries.append(entry);
|
||||
_offsetsHeader.entriesCount += 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QByteArray InMemoryWriter::toByteArray() const
|
||||
{
|
||||
QByteArray data;
|
||||
QDataStream out(&data, QIODevice::ReadWrite);
|
||||
out.setVersion(QDataStream::Qt_4_5);
|
||||
|
||||
// Basic format header.
|
||||
HeaderEntity header;
|
||||
header.magic = HeaderEntity::MAGIC;
|
||||
header.majorVersion = HeaderEntity::MAJOR_VERSION;
|
||||
header.minorVersion = HeaderEntity::MINOR_VERSION;
|
||||
out << header;
|
||||
|
||||
// Offsets-Header
|
||||
// - Save begin pos
|
||||
// - Write OffsetsHeader
|
||||
// - Convert relative- to absolute-offsets
|
||||
// - Seek back to begin-pos and write OffsetsHeader again.
|
||||
// Use a copy of OffsetsHeader to keep the _offsetsHeader relative.
|
||||
const qint64 posOffsetHeaders = out.device()->pos();
|
||||
OffsetsHeaderEntity offsetsHeader = _offsetsHeader;
|
||||
out << offsetsHeader;
|
||||
|
||||
// Now we know the size of the entire header.
|
||||
// We can update the relative- to absolute-offsets now.
|
||||
const qint64 allHeaderSize = out.device()->pos();
|
||||
for (int i = 0; i < offsetsHeader.entriesCount; ++i)
|
||||
{
|
||||
offsetsHeader.entries[i].offset += allHeaderSize; // Absolute offset!
|
||||
}
|
||||
|
||||
// Seek back and write again with absolute offsets.
|
||||
// TODO Thats not nice, but it works...
|
||||
out.device()->seek(posOffsetHeaders);
|
||||
out << offsetsHeader;
|
||||
|
||||
// Write contents.
|
||||
out.writeRawData(_contentBuffer.data().constData(), _contentBuffer.size());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
InMemoryReader::InMemoryReader(const QByteArray& data) :
|
||||
_data(data)
|
||||
{
|
||||
}
|
||||
|
||||
bool InMemoryReader::initReadHeader()
|
||||
{
|
||||
QDataStream in(_data);
|
||||
in.setVersion(QDataStream::Qt_4_5);
|
||||
|
||||
// Basic format header.
|
||||
HeaderEntity header;
|
||||
in >> header;
|
||||
if (header.magic != HeaderEntity::MAGIC)
|
||||
{
|
||||
qWarning() << QString("invalid format (magic=%1)").arg(header.magic);
|
||||
return false;
|
||||
}
|
||||
if (header.majorVersion != HeaderEntity::MAJOR_VERSION)
|
||||
{
|
||||
qWarning() << QString("format is too new (major=%1; minor=%2)")
|
||||
.arg(header.majorVersion).arg(header.minorVersion);
|
||||
return false;
|
||||
}
|
||||
|
||||
// OffsetsHeader.
|
||||
in >> _offsetsHeader;
|
||||
|
||||
return !in.atEnd();
|
||||
}
|
||||
|
||||
bool InMemoryReader::read(qint32 entryType, QByteArray& data)
|
||||
{
|
||||
// Find offset for "type".
|
||||
int index = -1;
|
||||
for (int i = 0; i < _offsetsHeader.entriesCount; ++i)
|
||||
{
|
||||
if (_offsetsHeader.entries.at(i).type == entryType)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index < 0)
|
||||
return false;
|
||||
else if (_offsetsHeader.entries.at(index).offset == 0)
|
||||
return false;
|
||||
|
||||
const OffsetsHeaderEntryEntity& entry = _offsetsHeader.entries.at(index);
|
||||
|
||||
QDataStream in(_data);
|
||||
in.setVersion(QDataStream::Qt_4_5);
|
||||
in.device()->seek(entry.offset);
|
||||
|
||||
char* buff = new char[entry.contentSize];
|
||||
in.readRawData(buff, entry.contentSize);
|
||||
data.append(buff, entry.contentSize);
|
||||
delete[] buff;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InMemoryReader::read(SectionIndexData& sid)
|
||||
{
|
||||
QByteArray sidData;
|
||||
if (!read(ET_SectionIndex, sidData) || sidData.isEmpty())
|
||||
return false;
|
||||
|
||||
QDataStream in(sidData);
|
||||
in.setVersion(QDataStream::Qt_4_5);
|
||||
in >> sid;
|
||||
|
||||
return in.atEnd();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace ads
|
@ -1,182 +0,0 @@
|
||||
#ifndef ADS_SERIALIZATION_H
|
||||
#define ADS_SERIALIZATION_H
|
||||
/*******************************************************************************
|
||||
** QtAdcancedDockingSystem
|
||||
** Copyright (C) 2017 Uwe Kindler
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
#include <QtGlobal>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QDataStream>
|
||||
#include <QBuffer>
|
||||
|
||||
#include "API.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
enum EntryType
|
||||
{
|
||||
ET_Unknown = 0x00000000,
|
||||
ET_Hierarchy = 0x00000001,
|
||||
ET_SectionIndex = 0x00000002,
|
||||
|
||||
// Begin of custom entry types (e.g. CustomType + 42)
|
||||
ET_Custom = 0x0000ffff
|
||||
};
|
||||
|
||||
class ADS_EXPORT_API HeaderEntity
|
||||
{
|
||||
public:
|
||||
static qint32 MAGIC;
|
||||
static qint32 MAJOR_VERSION;
|
||||
static qint32 MINOR_VERSION;
|
||||
|
||||
HeaderEntity();
|
||||
qint32 magic;
|
||||
qint32 majorVersion;
|
||||
qint32 minorVersion;
|
||||
};
|
||||
QDataStream& operator<<(QDataStream& out, const HeaderEntity& data);
|
||||
QDataStream& operator>>(QDataStream& in, HeaderEntity& data);
|
||||
|
||||
|
||||
class ADS_EXPORT_API OffsetsHeaderEntity
|
||||
{
|
||||
public:
|
||||
OffsetsHeaderEntity();
|
||||
|
||||
qint64 entriesCount;
|
||||
QList<class OffsetsHeaderEntryEntity> entries;
|
||||
};
|
||||
QDataStream& operator<<(QDataStream& out, const OffsetsHeaderEntity& data);
|
||||
QDataStream& operator>>(QDataStream& in, OffsetsHeaderEntity& data);
|
||||
|
||||
|
||||
class ADS_EXPORT_API OffsetsHeaderEntryEntity
|
||||
{
|
||||
public:
|
||||
OffsetsHeaderEntryEntity();
|
||||
qint32 type;
|
||||
qint64 offset;
|
||||
qint64 contentSize;
|
||||
};
|
||||
QDataStream& operator<<(QDataStream& out, const OffsetsHeaderEntryEntity& data);
|
||||
QDataStream& operator>>(QDataStream& in, OffsetsHeaderEntryEntity& data);
|
||||
|
||||
|
||||
class ADS_EXPORT_API SectionEntity
|
||||
{
|
||||
public:
|
||||
SectionEntity();
|
||||
qint32 x;
|
||||
qint32 y;
|
||||
qint32 width;
|
||||
qint32 height;
|
||||
qint32 currentIndex;
|
||||
qint32 sectionContentsCount;
|
||||
QList<class SectionContentEntity> sectionContents;
|
||||
};
|
||||
QDataStream& operator<<(QDataStream& out, const SectionEntity& data);
|
||||
QDataStream& operator>>(QDataStream& in, SectionEntity& data);
|
||||
|
||||
|
||||
class ADS_EXPORT_API SectionContentEntity
|
||||
{
|
||||
public:
|
||||
SectionContentEntity();
|
||||
QString uniqueName;
|
||||
bool visible;
|
||||
qint32 preferredIndex;
|
||||
};
|
||||
QDataStream& operator<<(QDataStream& out, const SectionContentEntity& data);
|
||||
QDataStream& operator>>(QDataStream& in, SectionContentEntity& data);
|
||||
|
||||
|
||||
class ADS_EXPORT_API FloatingContentEntity
|
||||
{
|
||||
public:
|
||||
FloatingContentEntity();
|
||||
QString uniqueName;
|
||||
qint32 xpos;
|
||||
qint32 ypos;
|
||||
qint32 width;
|
||||
qint32 height;
|
||||
bool visible;
|
||||
};
|
||||
QDataStream& operator<<(QDataStream& out, const FloatingContentEntity& data);
|
||||
QDataStream& operator>>(QDataStream& in, FloatingContentEntity& data);
|
||||
|
||||
|
||||
// Type: OffsetHeaderEntry::Hierarchy
|
||||
class ADS_EXPORT_API HierarchyData
|
||||
{
|
||||
public:
|
||||
HierarchyData();
|
||||
QByteArray data;
|
||||
};
|
||||
QDataStream& operator<<(QDataStream& out, const HierarchyData& data);
|
||||
QDataStream& operator>>(QDataStream& in, HierarchyData& data);
|
||||
|
||||
|
||||
// Type: OffsetHeaderEntry::SectionIndex
|
||||
class ADS_EXPORT_API SectionIndexData
|
||||
{
|
||||
public:
|
||||
SectionIndexData();
|
||||
qint32 sectionsCount;
|
||||
QList<SectionEntity> sections;
|
||||
};
|
||||
QDataStream& operator<<(QDataStream& out, const SectionIndexData& data);
|
||||
QDataStream& operator>>(QDataStream& in, SectionIndexData& data);
|
||||
|
||||
|
||||
/*!
|
||||
* \brief The InMemoryWriter class writes into a QByteArray.
|
||||
*/
|
||||
class ADS_EXPORT_API InMemoryWriter
|
||||
{
|
||||
public:
|
||||
InMemoryWriter();
|
||||
bool write(qint32 entryType, const QByteArray& data);
|
||||
bool write(const SectionIndexData& data);
|
||||
QByteArray toByteArray() const;
|
||||
qint32 offsetsCount() const { return _offsetsHeader.entriesCount; }
|
||||
|
||||
private:
|
||||
QBuffer _contentBuffer;
|
||||
OffsetsHeaderEntity _offsetsHeader;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief The InMemoryReader class
|
||||
*/
|
||||
class ADS_EXPORT_API InMemoryReader
|
||||
{
|
||||
public:
|
||||
InMemoryReader(const QByteArray& data);
|
||||
bool initReadHeader();
|
||||
bool read(qint32 entryType, QByteArray &data);
|
||||
bool read(SectionIndexData& sid);
|
||||
qint32 offsetsCount() const { return _offsetsHeader.entriesCount; }
|
||||
|
||||
private:
|
||||
QByteArray _data;
|
||||
OffsetsHeaderEntity _offsetsHeader;
|
||||
};
|
||||
|
||||
} // namespace ads
|
||||
#endif
|
@ -1,22 +0,0 @@
|
||||
DEPENDPATH *= $$PWD
|
||||
HEADERS += \
|
||||
$$PWD/ads_globals.h \
|
||||
$$PWD/DockAreaWidget.h \
|
||||
$$PWD/DockContainerWidget.h \
|
||||
$$PWD/DockManager.h \
|
||||
$$PWD/DockWidget.h \
|
||||
$$PWD/DockWidgetTitleBar.h \
|
||||
$$PWD/FloatingDockContainer.h \
|
||||
$$PWD/DockOverlay.h
|
||||
|
||||
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/ads_globals.cpp \
|
||||
$$PWD/DockAreaWidget.cpp \
|
||||
$$PWD/DockContainerWidget.cpp \
|
||||
$$PWD/DockManager.cpp \
|
||||
$$PWD/DockWidget.cpp \
|
||||
$$PWD/DockWidgetTitleBar.cpp \
|
||||
$$PWD/FloatingDockContainer.cpp \
|
||||
$$PWD/DockOverlay.cpp
|
@ -1,57 +0,0 @@
|
||||
include($$(cetoni_repository)/build/qt/qtprojectsettings/common.pri)
|
||||
|
||||
TARGET = AdvancedDockingSystemDemo
|
||||
|
||||
QT += core gui
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
greaterThan(QT_MAJOR_VERSION, 4): DEFINES += ADS_NAMESPACE_ENABLED
|
||||
|
||||
windows {
|
||||
# MinGW
|
||||
*-g++* {
|
||||
QMAKE_CXXFLAGS += -std=c++11
|
||||
}
|
||||
# MSVC
|
||||
*-msvc* {
|
||||
}
|
||||
}
|
||||
|
||||
SOURCES += \
|
||||
src/main.cpp \
|
||||
src/mainwindow.cpp \
|
||||
src/icontitlewidget.cpp \
|
||||
src/dialogs/SectionContentListModel.cpp \
|
||||
src/dialogs/SectionContentListWidget.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/mainwindow.h \
|
||||
src/icontitlewidget.h \
|
||||
src/dialogs/SectionContentListModel.h \
|
||||
src/dialogs/SectionContentListWidget.h
|
||||
|
||||
FORMS += \
|
||||
src/mainwindow.ui \
|
||||
src/dialogs/SectionContentListWidget.ui
|
||||
|
||||
|
||||
# Dependency: AdvancedDockingSystem (staticlib)
|
||||
#win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../AdvancedDockingSystem/release/ -lAdvancedDockingSystem
|
||||
#else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../AdvancedDockingSystem/debug/ -lAdvancedDockingSystem
|
||||
#else:unix: LIBS += -L$$OUT_PWD/../AdvancedDockingSystem/ -lAdvancedDockingSystem
|
||||
|
||||
#INCLUDEPATH += $$PWD/../AdvancedDockingSystem/include
|
||||
#DEPENDPATH += $$PWD/../AdvancedDockingSystem/include
|
||||
|
||||
#win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../AdvancedDockingSystem/release/libAdvancedDockingSystem.a
|
||||
#else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../AdvancedDockingSystem/debug/libAdvancedDockingSystem.a
|
||||
#else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../AdvancedDockingSystem/release/AdvancedDockingSystem.lib
|
||||
#else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../AdvancedDockingSystem/debug/AdvancedDockingSystem.lib
|
||||
#else:unix: PRE_TARGETDEPS += $$OUT_PWD/../AdvancedDockingSystem/libAdvancedDockingSystem.a
|
||||
|
||||
# Dependency: AdvancedDockingSystem (shared)
|
||||
win32:CONFIG(release, debug|release): LIBS += -l$$qtLinkLibrary(AdvancedDockingSystem)
|
||||
else:win32:CONFIG(debug, debug|release): LIBS += -l$$qtLinkLibrary(AdvancedDockingSystem)
|
||||
else:unix: LIBS += -L$$OUT_PWD/../AdvancedDockingSystem/ -lAdvancedDockingSystem
|
||||
|
||||
INCLUDEPATH += $$PWD/../AdvancedDockingSystem/src
|
||||
DEPENDPATH += $$PWD/../AdvancedDockingSystem/src
|
@ -1,90 +0,0 @@
|
||||
#include "SectionContentListModel.h"
|
||||
|
||||
SectionContentListModel::SectionContentListModel(QObject* parent) :
|
||||
QAbstractTableModel(parent)
|
||||
{
|
||||
_headers.insert(UidColumn, "UID");
|
||||
_headers.insert(UniqueNameColumn, "Unique Name");
|
||||
_headers.insert(TitleColumn, "Title");
|
||||
_headers.insert(VisibleColumn, "Visible");
|
||||
}
|
||||
|
||||
SectionContentListModel::~SectionContentListModel()
|
||||
{
|
||||
}
|
||||
|
||||
void SectionContentListModel::init(ads::CMainContainerWidget* cw)
|
||||
{
|
||||
beginResetModel();
|
||||
_cw = cw;
|
||||
_contents = _cw->contents();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
int SectionContentListModel::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return _headers.count();
|
||||
}
|
||||
|
||||
QVariant SectionContentListModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
return _headers.value(section);
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int SectionContentListModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return _contents.count();
|
||||
}
|
||||
|
||||
QVariant SectionContentListModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() > rowCount(index) - 1)
|
||||
return QVariant();
|
||||
|
||||
const ads::SectionContent::RefPtr sc = _contents.at(index.row());
|
||||
if (sc.isNull())
|
||||
return QVariant();
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case UidColumn:
|
||||
return sc->uid();
|
||||
case UniqueNameColumn:
|
||||
return sc->uniqueName();
|
||||
case TitleColumn:
|
||||
return sc->title();
|
||||
case VisibleColumn:
|
||||
return _cw->isSectionContentVisible(sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool SectionContentListModel::removeRows(int row, int count, const QModelIndex& parent)
|
||||
{
|
||||
if (row > rowCount(parent) - 1)
|
||||
return false;
|
||||
|
||||
const int first = row;
|
||||
const int last = row + count - 1;
|
||||
beginRemoveRows(parent, first, last);
|
||||
|
||||
for (int i = last; i >= first; --i)
|
||||
{
|
||||
const ads::SectionContent::RefPtr sc = _contents.at(i);
|
||||
_cw->removeSectionContent(sc);
|
||||
_contents.removeAt(i);
|
||||
}
|
||||
|
||||
endRemoveRows();
|
||||
return true;
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
#ifndef ADS_SECTIONCONTENTMODEL_H
|
||||
#define ADS_SECTIONCONTENTMODEL_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QAbstractTableModel>
|
||||
#include "../../../AdvancedDockingSystem/src/SectionContent.h"
|
||||
#include "MainContainerWidget.h"
|
||||
#include "API.h"
|
||||
namespace ads {class CMainContainerWidget;}
|
||||
|
||||
|
||||
class SectionContentListModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Column
|
||||
{
|
||||
UidColumn,
|
||||
UniqueNameColumn,
|
||||
TitleColumn,
|
||||
VisibleColumn
|
||||
};
|
||||
|
||||
SectionContentListModel(QObject* parent);
|
||||
virtual ~SectionContentListModel();
|
||||
void init(ads::CMainContainerWidget* cw);
|
||||
|
||||
virtual int columnCount(const QModelIndex &parent) const;
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
|
||||
virtual int rowCount(const QModelIndex &parent) const;
|
||||
virtual QVariant data(const QModelIndex &index, int role) const;
|
||||
|
||||
virtual bool removeRows(int row, int count, const QModelIndex &parent);
|
||||
|
||||
private:
|
||||
QHash<int, QString> _headers;
|
||||
|
||||
ads::CMainContainerWidget* _cw;
|
||||
QList<ads::SectionContent::RefPtr> _contents;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,38 +0,0 @@
|
||||
#include "SectionContentListWidget.h"
|
||||
#include "SectionContentListModel.h"
|
||||
|
||||
|
||||
SectionContentListWidget::SectionContentListWidget(QWidget* parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
_ui.setupUi(this);
|
||||
connect(_ui.deleteButton, SIGNAL(clicked(bool)), this, SLOT(onDeleteButtonClicked()));
|
||||
}
|
||||
|
||||
void SectionContentListWidget::setValues(const SectionContentListWidget::Values& v)
|
||||
{
|
||||
_v = v;
|
||||
|
||||
// Reset
|
||||
QAbstractItemModel* m = _ui.tableView->model();
|
||||
if (m)
|
||||
{
|
||||
_ui.tableView->setModel(NULL);
|
||||
delete m;
|
||||
m = NULL;
|
||||
}
|
||||
|
||||
// Fill.
|
||||
SectionContentListModel* sclm = new SectionContentListModel(this);
|
||||
sclm->init(_v.cw);
|
||||
_ui.tableView->setModel(sclm);
|
||||
}
|
||||
|
||||
void SectionContentListWidget::onDeleteButtonClicked()
|
||||
{
|
||||
const QModelIndex mi = _ui.tableView->currentIndex();
|
||||
if (!mi.isValid())
|
||||
return;
|
||||
|
||||
_ui.tableView->model()->removeRows(mi.row(), 1, mi.parent());
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
#ifndef SECTIONCONTENTLISTWIDGET
|
||||
#define SECTIONCONTENTLISTWIDGET
|
||||
|
||||
#include <QDialog>
|
||||
#include "../../../AdvancedDockingSystem/src/SectionContent.h"
|
||||
#include "MainContainerWidget.h"
|
||||
#include "ui_SectionContentListWidget.h"
|
||||
|
||||
#include "API.h"
|
||||
|
||||
class SectionContentListWidget : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
class Values
|
||||
{
|
||||
public:
|
||||
ads::CMainContainerWidget* cw;
|
||||
};
|
||||
|
||||
SectionContentListWidget(QWidget* parent);
|
||||
void setValues(const Values& v);
|
||||
|
||||
private slots:
|
||||
void onDeleteButtonClicked();
|
||||
|
||||
private:
|
||||
Ui::SectionContentListWidgetForm _ui;
|
||||
Values _v;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,61 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SectionContentListWidgetForm</class>
|
||||
<widget class="QWidget" name="SectionContentListWidgetForm">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>522</width>
|
||||
<height>258</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QTableView" name="tableView">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteButton">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -1,66 +0,0 @@
|
||||
#include "icontitlewidget.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QString>
|
||||
#include <QBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QStyle>
|
||||
|
||||
IconTitleWidget::IconTitleWidget(const QIcon& icon, const QString& title, QWidget *parent) :
|
||||
QFrame(parent)
|
||||
{
|
||||
QBoxLayout* l = new QBoxLayout(QBoxLayout::LeftToRight);
|
||||
l->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(l);
|
||||
|
||||
_iconLabel = new QLabel();
|
||||
_iconLabel->setAlignment(Qt::AlignVCenter);
|
||||
l->addWidget(_iconLabel, Qt::AlignVCenter);
|
||||
|
||||
_titleLabel = new QLabel();
|
||||
l->addWidget(_titleLabel, 1);
|
||||
|
||||
setIcon(icon);
|
||||
setTitle(title);
|
||||
}
|
||||
|
||||
void IconTitleWidget::setIcon(const QIcon& icon)
|
||||
{
|
||||
if (icon.isNull())
|
||||
{
|
||||
_iconLabel->setPixmap(QPixmap());
|
||||
_iconLabel->setVisible(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_iconLabel->setPixmap(icon.pixmap(16, 16));
|
||||
_iconLabel->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
void IconTitleWidget::setTitle(const QString& title)
|
||||
{
|
||||
if (title.isEmpty())
|
||||
{
|
||||
_titleLabel->setText(QString());
|
||||
_titleLabel->setVisible(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_titleLabel->setText(title);
|
||||
_titleLabel->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
void IconTitleWidget::polishUpdate()
|
||||
{
|
||||
QList<QWidget*> widgets;
|
||||
widgets.append(_iconLabel);
|
||||
widgets.append(_titleLabel);
|
||||
foreach (QWidget* w, widgets)
|
||||
{
|
||||
w->style()->unpolish(w);
|
||||
w->style()->polish(w);
|
||||
w->update();
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#ifndef ICONTITLEWIDGET_H
|
||||
#define ICONTITLEWIDGET_H
|
||||
|
||||
#include <QFrame>
|
||||
class QIcon;
|
||||
class QString;
|
||||
class QLabel;
|
||||
|
||||
class IconTitleWidget : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit IconTitleWidget(const QIcon& icon, const QString& title, QWidget *parent = 0);
|
||||
|
||||
public slots:
|
||||
void setIcon(const QIcon& icon);
|
||||
void setTitle(const QString& title);
|
||||
void polishUpdate();
|
||||
|
||||
public:
|
||||
QLabel* _iconLabel;
|
||||
QLabel* _titleLabel;
|
||||
};
|
||||
|
||||
#endif // ICONTITLEWIDGET_H
|
@ -1,28 +0,0 @@
|
||||
#include <QString>
|
||||
#include <QFile>
|
||||
#include <QApplication>
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
static void initStyleSheet(QApplication& a)
|
||||
{
|
||||
//Q_INIT_RESOURCE(ads); // If static linked.
|
||||
QFile f(":ads/stylesheets/default-windows.css");
|
||||
if (f.open(QFile::ReadOnly))
|
||||
{
|
||||
const QByteArray ba = f.readAll();
|
||||
f.close();
|
||||
a.setStyleSheet(QString(ba));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
a.setQuitOnLastWindowClosed(true);
|
||||
initStyleSheet(a);
|
||||
|
||||
MainWindow mw;
|
||||
mw.show();
|
||||
return a.exec();
|
||||
}
|
@ -1,195 +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 "SectionWidget.h"
|
||||
#include "DropOverlay.h"
|
||||
|
||||
#include "dialogs/SectionContentListWidget.h"
|
||||
|
||||
#include "icontitlewidget.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int CONTENT_COUNT = 0;
|
||||
|
||||
static ads::SectionContent::RefPtr createLongTextLabelSC(ads::CMainContainerWidget* container)
|
||||
{
|
||||
QWidget* w = new QWidget();
|
||||
QBoxLayout* bl = new QBoxLayout(QBoxLayout::TopToBottom);
|
||||
w->setLayout(bl);
|
||||
|
||||
QLabel* l = new QLabel();
|
||||
l->setWordWrap(true);
|
||||
l->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
||||
l->setText(QString("Lorem Ipsum ist ein einfacher Demo-Text für die Print- und Schriftindustrie. Lorem Ipsum ist in der Industrie bereits der Standard Demo-Text seit 1500, als ein unbekannter Schriftsteller eine Hand voll Wörter nahm und diese durcheinander warf um ein Musterbuch zu erstellen. Es hat nicht nur 5 Jahrhunderte überlebt, sondern auch in Spruch in die elektronische Schriftbearbeitung geschafft (bemerke, nahezu unverändert). Bekannt wurde es 1960, mit dem erscheinen von Letrase, welches Passagen von Lorem Ipsum enhielt, so wie Desktop Software wie Aldus PageMaker - ebenfalls mit Lorem Ipsum."));
|
||||
bl->addWidget(l);
|
||||
|
||||
const int index = ++CONTENT_COUNT;
|
||||
ads::SectionContent::RefPtr sc = ads::SectionContent::newSectionContent(QString("uname-%1").arg(index), container, new IconTitleWidget(QIcon(), QString("Label %1").arg(index)), w);
|
||||
sc->setTitle("Ein Label " + QString::number(index));
|
||||
return sc;
|
||||
}
|
||||
|
||||
static ads::SectionContent::RefPtr createCalendarSC(ads::CMainContainerWidget* container)
|
||||
{
|
||||
QCalendarWidget* w = new QCalendarWidget();
|
||||
|
||||
const int index = ++CONTENT_COUNT;
|
||||
return ads::SectionContent::newSectionContent(QString("uname-%1").arg(index), container, new IconTitleWidget(QIcon(), QString("Calendar %1").arg(index)), w);
|
||||
}
|
||||
|
||||
static ads::SectionContent::RefPtr createFileSystemTreeSC(ads::CMainContainerWidget* container)
|
||||
{
|
||||
QTreeView* w = new QTreeView();
|
||||
w->setFrameShape(QFrame::NoFrame);
|
||||
// QFileSystemModel* m = new QFileSystemModel(w);
|
||||
// m->setRootPath(QDir::currentPath());
|
||||
// w->setModel(m);
|
||||
|
||||
const int index = ++CONTENT_COUNT;
|
||||
return ads::SectionContent::newSectionContent(QString("uname-%1").arg(index), container, new IconTitleWidget(QIcon(), QString("Filesystem %1").arg(index)), w);
|
||||
}
|
||||
|
||||
static void storeDataHelper(const QString& fname, const QByteArray& ba)
|
||||
{
|
||||
QFile f(fname + QString(".dat"));
|
||||
if (f.open(QFile::WriteOnly))
|
||||
{
|
||||
f.write(ba);
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
|
||||
static QByteArray loadDataHelper(const QString& fname)
|
||||
{
|
||||
QFile f(fname + QString(".dat"));
|
||||
if (f.open(QFile::ReadOnly))
|
||||
{
|
||||
QByteArray ba = f.readAll();
|
||||
f.close();
|
||||
return ba;
|
||||
}
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
// Setup actions.
|
||||
connect(ui->actionContentList, SIGNAL(triggered()), this, SLOT(showSectionContentListDialog()));
|
||||
|
||||
// ADS - Create main container (ContainerWidget).
|
||||
_container = new ads::CMainContainerWidget();
|
||||
connect(_container, SIGNAL(activeTabChanged(const SectionContent::RefPtr&, bool)), this, SLOT(onActiveTabChanged(const SectionContent::RefPtr&, bool)));
|
||||
connect(_container, SIGNAL(sectionContentVisibilityChanged(SectionContent::RefPtr,bool)), this, SLOT(onSectionContentVisibilityChanged(SectionContent::RefPtr,bool)));
|
||||
setCentralWidget(_container);
|
||||
createContent();
|
||||
// Default window geometry
|
||||
resize(800, 600);
|
||||
restoreGeometry(loadDataHelper("MainWindow"));
|
||||
|
||||
// ADS - Restore geometries and states of contents.
|
||||
//_container->restoreState(loadDataHelper("ContainerWidget"));
|
||||
_container->dumpLayout();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::createContent()
|
||||
{
|
||||
// ADS - Adding some contents.
|
||||
// Test #1: Use high-level public API
|
||||
ads::CMainContainerWidget* cw = _container;
|
||||
ads::SectionWidget* sw = nullptr;
|
||||
|
||||
sw = _container->addSectionContent(createLongTextLabelSC(cw), nullptr, ads::CenterDropArea);
|
||||
sw = _container->addSectionContent(createCalendarSC(cw), nullptr, ads::LeftDropArea);
|
||||
sw = _container->addSectionContent(createFileSystemTreeSC(cw), nullptr, ads::BottomDropArea);
|
||||
sw = _container->addSectionContent(createCalendarSC(cw), nullptr, ads::BottomDropArea);
|
||||
|
||||
/*_container->addSectionContent(createCalendarSC(_container));
|
||||
_container->addSectionContent(createLongTextLabelSC(_container));
|
||||
_container->addSectionContent(createLongTextLabelSC(_container));
|
||||
_container->addSectionContent(createLongTextLabelSC(_container));
|
||||
|
||||
ads::SectionContent::RefPtr sc = createLongTextLabelSC(cw);
|
||||
sc->setFlags(ads::SectionContent::AllFlags ^ ads::SectionContent::Closeable);
|
||||
_container->addSectionContent(sc);*/
|
||||
|
||||
#if 0
|
||||
// Issue #2: If the first drop is not into CenterDropArea, the application crashes.
|
||||
ads::CMainContainerWidget* cw = _container;
|
||||
ads::SectionWidget* sw = NULL;
|
||||
|
||||
sw = _container->addSectionContent(createLongTextLabelSC(cw), sw, ads::LeftDropArea);
|
||||
sw = _container->addSectionContent(createCalendarSC(cw), sw, ads::LeftDropArea);
|
||||
sw = _container->addSectionContent(createLongTextLabelSC(cw), sw, ads::CenterDropArea);
|
||||
sw = _container->addSectionContent(createLongTextLabelSC(cw), sw, ads::CenterDropArea);
|
||||
sw = _container->addSectionContent(createLongTextLabelSC(cw), sw, ads::CenterDropArea);
|
||||
sw = _container->addSectionContent(createLongTextLabelSC(cw), sw, ads::RightDropArea);
|
||||
sw = _container->addSectionContent(createLongTextLabelSC(cw), sw, ads::BottomDropArea);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::showSectionContentListDialog()
|
||||
{
|
||||
SectionContentListWidget::Values v;
|
||||
v.cw = _container;
|
||||
|
||||
SectionContentListWidget w(this);
|
||||
w.setValues(v);
|
||||
w.exec();
|
||||
}
|
||||
|
||||
void MainWindow::onActiveTabChanged(const ads::SectionContent::RefPtr& sc, bool active)
|
||||
{
|
||||
Q_UNUSED(active);
|
||||
IconTitleWidget* itw = dynamic_cast<IconTitleWidget*>(sc->titleWidgetContent());
|
||||
if (itw)
|
||||
{
|
||||
itw->polishUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onSectionContentVisibilityChanged(const ads::SectionContent::RefPtr& sc, bool visible)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << sc->uniqueName() << visible;
|
||||
}
|
||||
|
||||
void MainWindow::onActionAddSectionContentTriggered()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void MainWindow::contextMenuEvent(QContextMenuEvent* e)
|
||||
{
|
||||
Q_UNUSED(e);
|
||||
QMenu* m = _container->createContextMenu();
|
||||
m->exec(QCursor::pos());
|
||||
delete m;
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent* e)
|
||||
{
|
||||
Q_UNUSED(e);
|
||||
storeDataHelper("MainWindow", saveGeometry());
|
||||
storeDataHelper("ContainerWidget", _container->saveState());
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include "../../AdvancedDockingSystem/src/MainContainerWidget.h"
|
||||
#include "../../AdvancedDockingSystem/src/SectionContent.h"
|
||||
#include "API.h"
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
virtual ~MainWindow();
|
||||
|
||||
public slots:
|
||||
|
||||
private slots:
|
||||
void onActiveTabChanged(const ads::SectionContent::RefPtr& sc, bool active);
|
||||
void onSectionContentVisibilityChanged(const ads::SectionContent::RefPtr& sc, bool visible);
|
||||
void onActionAddSectionContentTriggered();
|
||||
|
||||
protected:
|
||||
virtual void contextMenuEvent(QContextMenuEvent* e);
|
||||
virtual void closeEvent(QCloseEvent* e);
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
ads::CMainContainerWidget* _container;
|
||||
void createContent();
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
@ -1,79 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget"/>
|
||||
<widget class="QStatusBar" name="statusBar"/>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<addaction name="actionExit"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuView">
|
||||
<property name="title">
|
||||
<string>View</string>
|
||||
</property>
|
||||
<addaction name="actionContentList"/>
|
||||
<addaction name="actionDemo_2"/>
|
||||
<addaction name="actionDemo_3"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuAbout">
|
||||
<property name="title">
|
||||
<string>About</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuAbout"/>
|
||||
</widget>
|
||||
<action name="actionAddSectionContent">
|
||||
<property name="text">
|
||||
<string>Add SectionContent</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionContentList">
|
||||
<property name="text">
|
||||
<string>Contents...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDemo_2">
|
||||
<property name="text">
|
||||
<string>Demo 2</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDemo_3">
|
||||
<property name="text">
|
||||
<string>Demo 3</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExit">
|
||||
<property name="text">
|
||||
<string>Exit</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -1,90 +0,0 @@
|
||||
#include "SectionContentListModel.h"
|
||||
|
||||
SectionContentListModel::SectionContentListModel(QObject* parent) :
|
||||
QAbstractTableModel(parent)
|
||||
{
|
||||
_headers.insert(UidColumn, "UID");
|
||||
_headers.insert(UniqueNameColumn, "Unique Name");
|
||||
_headers.insert(TitleColumn, "Title");
|
||||
_headers.insert(VisibleColumn, "Visible");
|
||||
}
|
||||
|
||||
SectionContentListModel::~SectionContentListModel()
|
||||
{
|
||||
}
|
||||
|
||||
void SectionContentListModel::init(ads::CMainContainerWidget* cw)
|
||||
{
|
||||
beginResetModel();
|
||||
_cw = cw;
|
||||
_contents = _cw->contents();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
int SectionContentListModel::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return _headers.count();
|
||||
}
|
||||
|
||||
QVariant SectionContentListModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
return _headers.value(section);
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int SectionContentListModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return _contents.count();
|
||||
}
|
||||
|
||||
QVariant SectionContentListModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() > rowCount(index) - 1)
|
||||
return QVariant();
|
||||
|
||||
const ads::SectionContent::RefPtr sc = _contents.at(index.row());
|
||||
if (sc.isNull())
|
||||
return QVariant();
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case UidColumn:
|
||||
return sc->uid();
|
||||
case UniqueNameColumn:
|
||||
return sc->uniqueName();
|
||||
case TitleColumn:
|
||||
return sc->title();
|
||||
case VisibleColumn:
|
||||
return _cw->isSectionContentVisible(sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool SectionContentListModel::removeRows(int row, int count, const QModelIndex& parent)
|
||||
{
|
||||
if (row > rowCount(parent) - 1)
|
||||
return false;
|
||||
|
||||
const int first = row;
|
||||
const int last = row + count - 1;
|
||||
beginRemoveRows(parent, first, last);
|
||||
|
||||
for (int i = last; i >= first; --i)
|
||||
{
|
||||
const ads::SectionContent::RefPtr sc = _contents.at(i);
|
||||
_cw->removeSectionContent(sc);
|
||||
_contents.removeAt(i);
|
||||
}
|
||||
|
||||
endRemoveRows();
|
||||
return true;
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
#ifndef ADS_SECTIONCONTENTMODEL_H
|
||||
#define ADS_SECTIONCONTENTMODEL_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QAbstractTableModel>
|
||||
#include "../../../AdvancedDockingSystem/src/SectionContent.h"
|
||||
#include "MainContainerWidget.h"
|
||||
#include "API.h"
|
||||
namespace ads {class CMainContainerWidget;}
|
||||
|
||||
|
||||
class SectionContentListModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Column
|
||||
{
|
||||
UidColumn,
|
||||
UniqueNameColumn,
|
||||
TitleColumn,
|
||||
VisibleColumn
|
||||
};
|
||||
|
||||
SectionContentListModel(QObject* parent);
|
||||
virtual ~SectionContentListModel();
|
||||
void init(ads::CMainContainerWidget* cw);
|
||||
|
||||
virtual int columnCount(const QModelIndex &parent) const;
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
|
||||
virtual int rowCount(const QModelIndex &parent) const;
|
||||
virtual QVariant data(const QModelIndex &index, int role) const;
|
||||
|
||||
virtual bool removeRows(int row, int count, const QModelIndex &parent);
|
||||
|
||||
private:
|
||||
QHash<int, QString> _headers;
|
||||
|
||||
ads::CMainContainerWidget* _cw;
|
||||
QList<ads::SectionContent::RefPtr> _contents;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,38 +0,0 @@
|
||||
#include "SectionContentListWidget.h"
|
||||
#include "SectionContentListModel.h"
|
||||
|
||||
|
||||
SectionContentListWidget::SectionContentListWidget(QWidget* parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
_ui.setupUi(this);
|
||||
connect(_ui.deleteButton, SIGNAL(clicked(bool)), this, SLOT(onDeleteButtonClicked()));
|
||||
}
|
||||
|
||||
void SectionContentListWidget::setValues(const SectionContentListWidget::Values& v)
|
||||
{
|
||||
_v = v;
|
||||
|
||||
// Reset
|
||||
QAbstractItemModel* m = _ui.tableView->model();
|
||||
if (m)
|
||||
{
|
||||
_ui.tableView->setModel(NULL);
|
||||
delete m;
|
||||
m = NULL;
|
||||
}
|
||||
|
||||
// Fill.
|
||||
SectionContentListModel* sclm = new SectionContentListModel(this);
|
||||
sclm->init(_v.cw);
|
||||
_ui.tableView->setModel(sclm);
|
||||
}
|
||||
|
||||
void SectionContentListWidget::onDeleteButtonClicked()
|
||||
{
|
||||
const QModelIndex mi = _ui.tableView->currentIndex();
|
||||
if (!mi.isValid())
|
||||
return;
|
||||
|
||||
_ui.tableView->model()->removeRows(mi.row(), 1, mi.parent());
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
#ifndef SECTIONCONTENTLISTWIDGET
|
||||
#define SECTIONCONTENTLISTWIDGET
|
||||
|
||||
#include <QDialog>
|
||||
#include "../../../AdvancedDockingSystem/src/SectionContent.h"
|
||||
#include "MainContainerWidget.h"
|
||||
#include "ui_SectionContentListWidget.h"
|
||||
|
||||
#include "API.h"
|
||||
|
||||
class SectionContentListWidget : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
class Values
|
||||
{
|
||||
public:
|
||||
ads::CMainContainerWidget* cw;
|
||||
};
|
||||
|
||||
SectionContentListWidget(QWidget* parent);
|
||||
void setValues(const Values& v);
|
||||
|
||||
private slots:
|
||||
void onDeleteButtonClicked();
|
||||
|
||||
private:
|
||||
Ui::SectionContentListWidgetForm _ui;
|
||||
Values _v;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,61 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SectionContentListWidgetForm</class>
|
||||
<widget class="QWidget" name="SectionContentListWidgetForm">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>522</width>
|
||||
<height>258</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QTableView" name="tableView">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteButton">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -1,7 +0,0 @@
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/src/TestCore.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/src/main.cpp \
|
||||
$$PWD/src/TestCore.cpp
|
@ -1,16 +0,0 @@
|
||||
include($$(cetoni_repository)/build/qt/qtprojectsettings/common.pri)
|
||||
|
||||
TARGET = AdvancedDockingSystemUnitTests
|
||||
|
||||
QT += core gui testlib
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
greaterThan(QT_MAJOR_VERSION, 4): DEFINES += ADS_NAMESPACE_ENABLED
|
||||
DEFINES += ADS_IMPORT
|
||||
|
||||
INCLUDEPATH += $$PWD/src
|
||||
|
||||
INCLUDEPATH += $$PWD/../AdvancedDockingSystem/include
|
||||
DEPENDPATH += $$PWD/../AdvancedDockingSystem/include
|
||||
|
||||
include(AdvancedDockingSystemUnitTests.pri)
|
||||
include(../AdvancedDockingSystem/AdvancedDockingSystem.pri)
|
@ -1,68 +0,0 @@
|
||||
#include "TestCore.h"
|
||||
|
||||
#include "ads/API.h"
|
||||
#include "ads/Serialization.h"
|
||||
|
||||
void TestCore::serialization()
|
||||
{
|
||||
QList<QByteArray> datas;
|
||||
datas.append(QByteArray("Custom Data Here!!!"));
|
||||
datas.append(QByteArray("Even More..."));
|
||||
datas.append(QByteArray("lalalaalalalalalalal").toBase64());
|
||||
|
||||
// WRITE some data.
|
||||
ADS_NS_SER::InMemoryWriter writer;
|
||||
for (int i = 0; i < datas.count(); ++i)
|
||||
{
|
||||
QVERIFY(writer.write(ADS_NS_SER::ET_Custom + i, datas.at(i)));
|
||||
}
|
||||
|
||||
// Type: SectionIndexData
|
||||
ADS_NS_SER::SectionIndexData sid;
|
||||
for (int i = 0; i < 1; ++i)
|
||||
{
|
||||
ADS_NS_SER::SectionEntity se;
|
||||
se.x = i;
|
||||
se.y = i;
|
||||
se.width = 100 + i;
|
||||
se.height = 100 + i;
|
||||
se.currentIndex = i;
|
||||
|
||||
for (int j = 0; j < 1; ++j)
|
||||
{
|
||||
ADS_NS_SER::SectionContentEntity sce;
|
||||
sce.uniqueName = QString("uname-%1-%2").arg(i).arg(j);
|
||||
sce.preferredIndex = 8;
|
||||
sce.visible = true;
|
||||
se.sectionContents.append(sce);
|
||||
se.sectionContentsCount += 1;
|
||||
}
|
||||
|
||||
sid.sections.append(se);
|
||||
sid.sectionsCount += 1;
|
||||
}
|
||||
QVERIFY(writer.write(sid));
|
||||
|
||||
QVERIFY(writer.offsetsCount() == datas.count() + 1);
|
||||
const QByteArray writtenData = writer.toByteArray();
|
||||
QVERIFY(writtenData.size() > 0);
|
||||
|
||||
// READ and validate written data.
|
||||
ADS_NS_SER::InMemoryReader reader(writtenData);
|
||||
QVERIFY(reader.initReadHeader());
|
||||
QVERIFY(reader.offsetsCount() == datas.count() + 1);
|
||||
for (int i = 0; i < datas.count(); ++i)
|
||||
{
|
||||
QByteArray readData;
|
||||
QVERIFY(reader.read(ADS_NS_SER::ET_Custom + i, readData));
|
||||
QVERIFY(readData == datas.at(i));
|
||||
}
|
||||
|
||||
// Type: SectionIndexData
|
||||
ADS_NS_SER::SectionIndexData sidRead;
|
||||
QVERIFY(reader.read(sidRead));
|
||||
|
||||
// TODO compare sidRead with sid
|
||||
}
|
||||
|
||||
QTEST_MAIN(TestCore)
|
@ -1,14 +0,0 @@
|
||||
#ifndef TEST_CORE_H
|
||||
#define TEST_CORE_H
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
class TestCore : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void serialization();
|
||||
};
|
||||
|
||||
#endif
|
@ -1 +0,0 @@
|
||||
#include <QtTest/QtTest>
|
@ -1,7 +0,0 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS = \
|
||||
AdvancedDockingSystem \
|
||||
AdvancedDockingSystemDemo \
|
||||
AdvancedDockingSystemDemo_v2 \
|
||||
AdvancedDockingSystemUnitTests
|
@ -1,10 +1,9 @@
|
||||
include($$(cetoni_repository)/build/qt/qtprojectsettings/common.pri)
|
||||
|
||||
TARGET = AdvancedDockingSystemDemo_v2
|
||||
TARGET = AdvancedDockingSystemDemo
|
||||
|
||||
QT += core gui
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
greaterThan(QT_MAJOR_VERSION, 4): DEFINES += ADS_NAMESPACE_ENABLED
|
||||
QT += core gui widgets
|
||||
DEFINES += ADS_NAMESPACE_ENABLED
|
||||
|
||||
windows {
|
||||
# MinGW
|
||||
@ -17,15 +16,15 @@ windows {
|
||||
}
|
||||
|
||||
SOURCES += \
|
||||
src/main.cpp \
|
||||
src/mainwindow.cpp
|
||||
main.cpp \
|
||||
mainwindow.cpp
|
||||
|
||||
|
||||
HEADERS += \
|
||||
src/mainwindow.h
|
||||
mainwindow.h
|
||||
|
||||
FORMS += \
|
||||
src/mainwindow.ui
|
||||
mainwindow.ui
|
||||
|
||||
|
||||
# Dependency: AdvancedDockingSystem (shared)
|
||||
@ -33,8 +32,6 @@ win32:CONFIG(release, debug|release): LIBS += -l$$qtLinkLibrary(AdvancedDockingS
|
||||
else:win32:CONFIG(debug, debug|release): LIBS += -l$$qtLinkLibrary(AdvancedDockingSystem)
|
||||
else:unix: LIBS += -L$$OUT_PWD/../AdvancedDockingSystem/ -lAdvancedDockingSystem
|
||||
|
||||
INCLUDEPATH += $$PWD/../AdvancedDockingSystem/src \
|
||||
$$PWD/../AdvancedDockingSystem/src/v2
|
||||
INCLUDEPATH += ../src
|
||||
|
||||
DEPENDPATH += $$PWD/../AdvancedDockingSystem/src \
|
||||
$$PWD/../AdvancedDockingSystem/src/v2
|
||||
DEPENDPATH += ../src
|
@ -6,7 +6,6 @@
|
||||
|
||||
static void initStyleSheet(QApplication& a)
|
||||
{
|
||||
//Q_INIT_RESOURCE(ads); // If static linked.
|
||||
QFile f(":ads/stylesheets/default-windows2.css");
|
||||
if (f.open(QFile::ReadOnly))
|
||||
{
|
@ -1,4 +1,5 @@
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include <QTime>
|
@ -542,6 +542,7 @@ void CDockAreaWidget::setCurrentIndex(int index)
|
||||
}
|
||||
|
||||
d->ContentsLayout->setCurrentIndex(index);
|
||||
emit currentChanged(index);
|
||||
}
|
||||
|
||||
|
@ -159,6 +159,19 @@ public slots:
|
||||
* Updates the dock area layout and components visibility
|
||||
*/
|
||||
void updateDockArea();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* This signal is emitted when user clicks on a tab at an index.
|
||||
*/
|
||||
void tabBarClicked(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
|
||||
* @param index
|
||||
*/
|
||||
void currentChanged(int index);
|
||||
}; // class DockAreaWidget
|
||||
}
|
||||
// namespace ads
|
@ -117,6 +117,7 @@ struct DockWidgetTitleBarPrivate
|
||||
};
|
||||
// struct DockWidgetTitleBarPrivate
|
||||
|
||||
|
||||
//============================================================================
|
||||
DockWidgetTitleBarPrivate::DockWidgetTitleBarPrivate(CDockWidgetTitleBar* _public) :
|
||||
_this(_public)
|
54
src/src.pro
Normal file
54
src/src.pro
Normal file
@ -0,0 +1,54 @@
|
||||
include($$(cetoni_repository)/build/qt/qtprojectsettings/shared_library.pri)
|
||||
include(src/v2/v2.pri)
|
||||
|
||||
TARGET = $$qtLibraryTarget(AdvancedDockingSystem)
|
||||
TEMPLATE = lib
|
||||
#VERSION = 1.0.0
|
||||
|
||||
CONFIG += adsBuildShared
|
||||
|
||||
QT += core gui widgets
|
||||
DEFINES += ADS_NAMESPACE_ENABLED
|
||||
|
||||
adsBuildShared {
|
||||
CONFIG += shared
|
||||
DEFINES += ADS_EXPORT
|
||||
}
|
||||
!adsBuildShared {
|
||||
CONFIG += staticlib
|
||||
}
|
||||
|
||||
windows {
|
||||
# MinGW
|
||||
*-g++* {
|
||||
QMAKE_CXXFLAGS += -std=c++11
|
||||
QMAKE_CXXFLAGS += -Wall -Wextra -pedantic
|
||||
}
|
||||
# MSVC
|
||||
*-msvc* {
|
||||
}
|
||||
}
|
||||
|
||||
RESOURCES += ads.qrc
|
||||
|
||||
HEADERS += \
|
||||
ads_globals.h \
|
||||
DockAreaWidget.h \
|
||||
DockContainerWidget.h \
|
||||
DockManager.h \
|
||||
DockWidget.h \
|
||||
DockWidgetTitleBar.h \
|
||||
FloatingDockContainer.h \
|
||||
DockOverlay.h
|
||||
|
||||
|
||||
|
||||
SOURCES += \
|
||||
ads_globals.cpp \
|
||||
DockAreaWidget.cpp \
|
||||
DockContainerWidget.cpp \
|
||||
DockManager.cpp \
|
||||
DockWidget.cpp \
|
||||
DockWidgetTitleBar.cpp \
|
||||
FloatingDockContainer.cpp \
|
||||
DockOverlay.cpp
|
Loading…
Reference in New Issue
Block a user