Adds function to generate context menu with available contents.

Refactors some auto-keywords to its real class names.
Paints drop location based on cursors drop area indicator.
Waits a few pixel before moving tab from SectionWidget.
This commit is contained in:
mfreiholz 2016-02-02 13:49:10 +01:00
parent 1336118e09
commit 19b5f57610
9 changed files with 117 additions and 59 deletions

View File

@ -216,9 +216,8 @@ void ContainerWidget::splitSections(SectionWidget* s1, SectionWidget* s2, Qt::Or
{
addSection(s1);
addSection(s2);
//_sections.append(s2);
auto currentSplitter = findParentSplitter(s1);
QSplitter* currentSplitter = findParentSplitter(s1);
if (currentSplitter)
{
const int index = currentSplitter->indexOf(s1);
@ -229,14 +228,11 @@ void ContainerWidget::splitSections(SectionWidget* s1, SectionWidget* s2, Qt::Or
splitter->addWidget(s2);
currentSplitter->insertWidget(index, splitter);
}
// _mainLayout->replaceWidget(section1, splitter);
// splitter->addWidget(section1);
// splitter->addWidget(section2);
}
SectionWidget* ContainerWidget::sectionAt(const QPoint& pos) const
{
auto gpos = mapToGlobal(pos);
const QPoint gpos = mapToGlobal(pos);
for (int i = 0; i < _sections.size(); ++i)
{
auto sw = _sections[i];
@ -297,34 +293,35 @@ bool ContainerWidget::restoreGeometry(const QByteArray& data)
return false;
}
void ContainerWidget::paintEvent(QPaintEvent* e)
QMenu* ContainerWidget::createContextMenu() const
{
QFrame::paintEvent(e);
QMenu* m = new QMenu(const_cast<ContainerWidget*>(this));
// QPainter p(this);
// p.fillRect(outerTopDropRect(), QBrush(QColor(Qt::red)));
// p.fillRect(outerRightDropRect(), QBrush(QColor(Qt::green)));
// p.fillRect(outerBottomDropRect(), QBrush(QColor(Qt::blue)));
// p.fillRect(outerLeftDropRect(), QBrush(QColor(Qt::yellow)));
// Contents of SectionWidgets
for (int i = 0; i < _sections.size(); ++i)
{
SectionWidget* sw = _sections.at(i);
QList<SectionContent::RefPtr> contents = sw->contents();
foreach (const SectionContent::RefPtr& c, contents)
{
m->addAction(QIcon(), QString("Content %1").arg(c->uid()));
}
}
void ContainerWidget::contextMenuEvent(QContextMenuEvent*)
// Contents of FloatingWidgets
if (_floatingWidgets.size())
{
qDebug() << Q_FUNC_INFO;
// if (_contents.size() <= 0)
// {
// QFrame::contextMenuEvent(e);
// return;
// }
if (m->actions().size())
m->addSeparator();
for (int i = 0; i < _floatingWidgets.size(); ++i)
{
FloatingWidget* fw = _floatingWidgets.at(i);
SectionContent::RefPtr c = fw->content();
m->addAction(QIcon(), QString("Floating %1").arg(c->uid()));
}
}
// // Menu with all available contents.
// QMenu m;
// for (int i = 0; i < _contents.size(); ++i)
// {
// auto c = _contents[i];
// m.addAction(QIcon(), QString("Content %1").arg(c->uid()));
// }
// m.exec();
return m;
}
ADS_NAMESPACE_END

View File

@ -6,6 +6,7 @@
#include <QPoint>
#include <QList>
class QSplitter;
class QMenu;
#include "ads.h"
#include "section_content.h"
@ -22,6 +23,7 @@ class ContainerWidget : public QFrame
Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
friend class SectionWidget;
friend class FloatingWidget;
public:
explicit ContainerWidget(QWidget *parent = NULL);
@ -45,9 +47,7 @@ public:
QByteArray saveGeometry() const;
bool restoreGeometry(const QByteArray& data);
protected:
virtual void paintEvent(QPaintEvent*);
virtual void contextMenuEvent(QContextMenuEvent*);
QMenu* createContextMenu() const;
private: // Make private!

View File

@ -29,12 +29,12 @@ DropOverlay::DropOverlay(QWidget *parent) :
QFrame(parent),
_splitAreas(NULL)
{
setAttribute(Qt::WA_TransparentForMouseEvents);
//setAttribute(Qt::WA_TransparentForMouseEvents);
setWindowFlags(windowFlags() | Qt::Tool);
setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
setWindowOpacity(0.2);
auto l = new QBoxLayout(QBoxLayout::TopToBottom);
QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
l->setContentsMargins(0, 0, 0, 0);
l->setSpacing(0);
setLayout(l);
@ -68,16 +68,46 @@ void DropOverlay::paintEvent(QPaintEvent*)
{
QPainter p(this);
// Draw rect over the entire size + border.
auto r = rect();
r.setWidth(r.width() - 1);
r.setHeight(r.height() - 1);
// Draw rect based on location
QRect r = rect();
const DropArea da = cursorLocation();
switch (da)
{
case DropArea::TopDropArea:
r.setHeight(r.height() / 2);
break;
case DropArea::RightDropArea:
r.setX(r.width() / 2);
break;
case DropArea::BottomDropArea:
r.setY(r.height() / 2);
break;
case DropArea::LeftDropArea:
r.setWidth(r.width() / 2);
break;
case DropArea::CenterDropArea:
r = rect();
break;
default:
r = QRect();
}
if (!r.isNull())
{
p.fillRect(r, QBrush(QColor(0, 100, 255), Qt::Dense4Pattern));
p.setBrush(QBrush(QColor(0, 100, 255)));
p.drawRect(r);
}
// Draw rect over the entire size + border.
// auto r = rect();
// r.setWidth(r.width() - 1);
// r.setHeight(r.height() - 1);
// p.fillRect(r, QBrush(QColor(0, 100, 255), Qt::Dense4Pattern));
// p.setBrush(QBrush(QColor(0, 100, 255)));
// p.drawRect(r);
}
void DropOverlay::resizeEvent(QResizeEvent* e)
{
// Keep it in center of DropOverlay
@ -169,6 +199,7 @@ DropArea DropSplitAreas::cursorLocation() const
static QPointer<DropOverlay> MyOverlay;
static QPointer<QWidget> MyOverlayParent;
static QRect MyOverlayParentRect;
static DropArea MyOverlayLastLocation = InvalidDropArea;
DropArea showDropOverlay(QWidget* parent)
{
@ -177,7 +208,13 @@ DropArea showDropOverlay(QWidget* parent)
if (MyOverlayParent == parent)
{
// Hint: We could update geometry of overlay here.
return MyOverlay->cursorLocation();
DropArea da = MyOverlay->cursorLocation();
if (da != MyOverlayLastLocation)
{
MyOverlay->repaint();
MyOverlayLastLocation = da;
}
return da;
}
hideDropOverlay();
}
@ -220,6 +257,7 @@ void hideDropOverlay()
delete MyOverlay;
MyOverlayParent.clear();
MyOverlayParentRect = QRect();
MyOverlayLastLocation = InvalidDropArea;
}
}

View File

@ -7,13 +7,15 @@
#include <QMouseEvent>
#include <QStyle>
#include "container_widget.h"
#include "section_title_widget.h"
#include "section_content_widget.h"
ADS_NAMESPACE_BEGIN
FloatingWidget::FloatingWidget(SectionContent::RefPtr sc, SectionTitleWidget* titleWidget, SectionContentWidget* contentWidget, QWidget* parent) :
FloatingWidget::FloatingWidget(ContainerWidget* container, SectionContent::RefPtr sc, SectionTitleWidget* titleWidget, SectionContentWidget* contentWidget, QWidget* parent) :
QWidget(parent, Qt::CustomizeWindowHint | Qt::Tool),
_container(container),
_content(sc),
_titleWidget(titleWidget),
_contentWidget(contentWidget)
@ -47,6 +49,14 @@ FloatingWidget::FloatingWidget(SectionContent::RefPtr sc, SectionTitleWidget* ti
// Content
l->addWidget(contentWidget, 1);
contentWidget->show();
_container->_floatingWidgets.append(this);
}
FloatingWidget::~FloatingWidget()
{
qDebug() << Q_FUNC_INFO;
_container->_floatingWidgets.removeAll(this);
}
InternalContentData FloatingWidget::takeContent()

View File

@ -11,6 +11,7 @@ class QBoxLayout;
ADS_NAMESPACE_BEGIN
class ContainerWidget;
class SectionTitleWidget;
class SectionContentWidget;
@ -21,13 +22,17 @@ class FloatingWidget : public QWidget
Q_OBJECT
public:
FloatingWidget(SectionContent::RefPtr sc, SectionTitleWidget* titleWidget, SectionContentWidget* contentWidget, QWidget* parent = nullptr);
FloatingWidget(ContainerWidget* container, SectionContent::RefPtr sc, SectionTitleWidget* titleWidget, SectionContentWidget* contentWidget, QWidget* parent = nullptr);
virtual ~FloatingWidget();
InternalContentData takeContent();
SectionContent::RefPtr content() const { return _content; }
protected:
virtual void closeEvent(QCloseEvent* e);
private:
ContainerWidget* _container;
SectionContent::RefPtr _content;
SectionTitleWidget* _titleWidget;
SectionContentWidget* _contentWidget;

View File

@ -226,14 +226,13 @@ void SectionTitleWidget::mouseMoveEvent(QMouseEvent* ev)
}
// Begin to drag/float the SectionContent.
else if (!_fw && !_dragStartPos.isNull() && (ev->buttons() & Qt::LeftButton)
//&& (ev->globalPos() - _dragStartPos).manhattanLength() >= QApplication::startDragDistance()
&& (section = findParentSectionWidget(this)) != NULL
&& !section->titleAreaGeometry().contains(section->mapFromGlobal(ev->globalPos())))
{
// Create floating widget.
auto data = section->take(_content->uid(), false);
_fw = new FloatingWidget(data.content, data.titleWidget, data.contentWidget, cw);
_fw = new FloatingWidget(cw, data.content, data.titleWidget, data.contentWidget, cw);
_fw->resize(section->size());
setActiveTab(false);
@ -267,6 +266,7 @@ void SectionTitleWidget::mouseMoveEvent(QMouseEvent* ev)
}
// Begin to drag title inside the title area to switch its position inside the SectionWidget.
else if (!_dragStartPos.isNull() && (ev->buttons() & Qt::LeftButton)
&& (ev->pos() - _dragStartPos).manhattanLength() >= QApplication::startDragDistance() // Wait a few pixels before start moving
&& (section = findParentSectionWidget(this)) != NULL
&& section->titleAreaGeometry().contains(section->mapFromGlobal(ev->globalPos())))
{

View File

@ -13,17 +13,21 @@ IconTitleWidget::IconTitleWidget(const QIcon& icon, const QString& title, QWidge
l->setContentsMargins(0, 0, 0, 0);
setLayout(l);
auto titleIcon = new QLabel();
// Icon label
if (icon.isNull())
{
titleIcon->setPixmap(style()->standardIcon(QStyle::SP_MessageBoxInformation).pixmap(16, 16));
// auto titleIcon = new QLabel();
// titleIcon->setPixmap(style()->standardIcon(QStyle::SP_MessageBoxInformation).pixmap(16, 16));
// l->addWidget(titleIcon);
}
else
{
auto titleIcon = new QLabel();
titleIcon->setPixmap(icon.pixmap(16, 16));
}
l->addWidget(titleIcon);
}
// Title label
auto titleText = new QLabel(title);
auto titleFont = titleText->font();
titleFont.setBold(true);

View File

@ -57,6 +57,7 @@ MainWindow::MainWindow(QWidget *parent) :
{
ui->setupUi(this);
ui->mainToolBar->hide();
ui->statusBar->hide();
QObject::connect(ui->actionAddSectionContent, &QAction::triggered, this, &MainWindow::onActionAddSectionContentTriggered);
// CREATE SOME TESTING DOCKS

View File

@ -9,12 +9,15 @@
- PerCent: Resize in proportion to other widgets.
- Fixed: Width or height are fixed (based on orientation).
## TODO / Issues
List of tasks sorted by priority.
- [] Serialize state/size/positions of dockings #FEATURE
- [] Deserialize state/size/positions of dockings #FEATURE
- [] Drop indicator images should be fully visible over the DropOverlay rectangle #FEATURE
- [DONE] Clean up of unused e.g. count()<=1 QSplitters doesn't work well #BUG
## TODOs
- [] Serialize state/size/positions of dockings
- [] Deserialize state/size/positions of dockings
- [] Drop indicator images should be fully visible over the DropOverlay rectangle
## Bugs
- Working with outer-edge-drops sometimes leaves empty splitters
- [DONE] Clean up of unused e.g. count()<=1 QSplitters doesn't work well
## License notes
- Copied drop images from http://www.codeproject.com/Articles/140209/Building-a-Docking-Window-Management-Solution-in-W
- Copied drop images from
http://www.codeproject.com/Articles/140209/Building-a-Docking-Window-Management-Solution-in-W