KDDockWidgets API Documentation  1.6
SegmentedIndicators.cpp
Go to the documentation of this file.
1 /*
2  This file is part of KDDockWidgets.
3 
4  SPDX-FileCopyrightText: 2019-2022 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
5  Author: SĂ©rgio Martins <sergio.martins@kdab.com>
6 
7  SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
8 
9  Contact KDAB at <info@kdab.com> for commercial licensing options.
10 */
11 
12 #include "SegmentedIndicators_p.h"
13 #include "../DropArea_p.h"
14 #include "Config.h"
15 
16 #include <QPainter>
17 #include <QPainterPath>
18 
19 using namespace KDDockWidgets;
20 
21 int SegmentedIndicators::s_segmentGirth = 50;
22 int SegmentedIndicators::s_segmentPenWidth = 4;
23 qreal SegmentedIndicators::s_draggedWindowOpacity = 0.7;
24 QColor SegmentedIndicators::s_segmentPenColor = Qt::black;
25 QColor SegmentedIndicators::s_segmentBrushColor = QColor(0xbb, 0xd5, 0xee, /*alpha=*/200);
26 QColor SegmentedIndicators::s_hoveredSegmentBrushColor = QColor(0x3574c5);
27 int SegmentedIndicators::s_centralIndicatorMaxWidth = 300;
28 int SegmentedIndicators::s_centralIndicatorMaxHeight = 160;
29 
30 
31 SegmentedIndicators::SegmentedIndicators(DropArea *dropArea)
32  : DropIndicatorOverlayInterface(dropArea)
33 {
34  // If the app didn't choose opacity then we choose a suitable default value.
35  // ClassicIndicators works fine with an opaque dragged window because the indicators have higher Z,
36  // However for SegmentedIndicators the indicators are in the main window, so lower Z. Make the
37  // dragged window translucent a bit, so we can see the indicators
38  const bool userChoseOpacity = !qIsNaN(Config::self().draggedWindowOpacity());
39  if (!userChoseOpacity)
40  Config::self().setDraggedWindowOpacity(s_draggedWindowOpacity);
41 }
42 
43 SegmentedIndicators::~SegmentedIndicators()
44 {
45 }
46 
47 DropLocation SegmentedIndicators::hover_impl(QPoint pt)
48 {
49  m_hoveredPt = mapFromGlobal(pt);
50  updateSegments();
51  setCurrentDropLocation(dropLocationForPos(m_hoveredPt));
52 
53  return currentDropLocation();
54 }
55 
56 DropLocation SegmentedIndicators::dropLocationForPos(QPoint pos) const
57 {
58  for (auto it = m_segments.cbegin(), end = m_segments.cend(); it != end; ++it) {
59  if (it.value().containsPoint(pos, Qt::OddEvenFill)) {
60  return it.key();
61  }
62  }
63 
64  return DropLocation_None;
65 }
66 
67 void SegmentedIndicators::paintEvent(QPaintEvent *)
68 {
69  QPainter p(this);
70  p.setRenderHint(QPainter::Antialiasing, true);
71  drawSegments(&p);
72 }
73 
74 QHash<DropLocation, QPolygon> SegmentedIndicators::segmentsForRect(QRect r, bool inner, bool useOffset) const
75 {
76  const int halfPenWidth = s_segmentPenWidth / 2;
77 
78  const int l = s_segmentGirth;
79  const int top = (r.y() == 0 && useOffset) ? l : r.y();
80  const int left = (r.x() == 0 && useOffset) ? l : r.x();
81  const int right = (rect().right() == r.right() && useOffset) ? r.right() - l : r.right();
82  const int bottom = (rect().bottom() == r.bottom() && useOffset) ? r.bottom() - l : r.bottom();
83  const QPoint topLeft = { left + halfPenWidth, top + halfPenWidth };
84  const QPoint topRight = { right, top + halfPenWidth };
85  const QPoint bottomLeft = { left + halfPenWidth, bottom };
86  const QPoint bottomRight = { right, bottom };
87 
88  const QVector<QPoint> leftPoints = { topLeft, bottomLeft,
89  QPoint(left, bottom) + QPoint(l, -l),
90  topLeft + QPoint(l, l), topLeft };
91 
92  const QVector<QPoint> rightPoints = { topRight, bottomRight,
93  bottomRight + QPoint(-l, -l),
94  topRight + QPoint(-l, l) };
95 
96  const QVector<QPoint> topPoints = { topLeft, topRight,
97  topRight + QPoint(-l, l),
98  topLeft + QPoint(l, l) };
99 
100  const QVector<QPoint> bottomPoints = { bottomLeft, bottomRight,
101  bottomRight + QPoint(-l, -l),
102  bottomLeft + QPoint(l, -l) };
103 
104  if (inner) {
105  QPolygon bounds = QVector<QPoint> { topLeft + QPoint(l, l),
106  topRight + QPoint(-l, l),
107  bottomRight + QPoint(-l, -l),
108  bottomLeft + QPoint(l, -l) };
109  const int maxWidth = bounds.boundingRect().width();
110  const QPoint centerPos = bounds.boundingRect().center();
111 
112  // Build the center
113  const int indicatorWidth = qMin(s_centralIndicatorMaxWidth, maxWidth - 100);
114  const int indicatorHeight = qMin(s_centralIndicatorMaxHeight, int(indicatorWidth * 0.60));
115  const int tabWidth = int(indicatorWidth * 0.267);
116  const int tabHeight = int(indicatorHeight * 0.187);
117  const int centerRectLeft = centerPos.x() - indicatorWidth / 2;
118  const int centerRectRight = centerPos.x() + indicatorWidth / 2;
119  const int centerRectBottom = centerPos.y() + indicatorHeight / 2;
120  const int centerRectTop = centerPos.y() - indicatorHeight / 2;
121 
122 
123  const auto center = QVector<QPoint> {
124  { centerRectLeft, centerRectTop },
125  { centerRectLeft + tabWidth, centerRectTop },
126  { centerRectLeft + tabWidth, centerRectTop + tabHeight },
127  { centerRectRight, centerRectTop + tabHeight },
128  { centerRectRight, centerRectBottom },
129  { centerRectLeft, centerRectBottom },
130  };
131 
132  return {
133  { DropLocation_Left, leftPoints },
134  { DropLocation_Top, topPoints },
135  { DropLocation_Right, rightPoints },
136  { DropLocation_Bottom, bottomPoints },
138  };
139  } else {
140  return {
141  { DropLocation_OutterLeft, leftPoints },
142  { DropLocation_OutterTop, topPoints },
143  { DropLocation_OutterRight, rightPoints },
144  { DropLocation_OutterBottom, bottomPoints }
145  };
146  }
147 }
148 
149 void SegmentedIndicators::updateSegments()
150 {
151  m_segments.clear();
152 
153  const auto outterSegments = segmentsForRect(rect(), /*inner=*/false);
154 
156  if (dropIndicatorVisible(indicator)) {
157  m_segments.insert(indicator, outterSegments.value(indicator));
158  }
159  }
160 
161  const bool hasOutter = !m_segments.isEmpty();
162  const bool useOffset = hasOutter;
163  const auto innerSegments = segmentsForRect(hoveredFrameRect(), /*inner=*/true, useOffset);
164 
166  if (dropIndicatorVisible(indicator)) {
167  m_segments.insert(indicator, innerSegments.value(indicator));
168  }
169  }
170 
171  update();
172 }
173 
174 void SegmentedIndicators::drawSegments(QPainter *p)
175 {
176  for (DropLocation loc : { DropLocation_Left,
185  drawSegment(p, m_segments.value(loc));
186 }
187 
188 void SegmentedIndicators::drawSegment(QPainter *p, const QPolygon &segment)
189 {
190  if (segment.isEmpty())
191  return;
192 
193  QPen pen(s_segmentPenColor);
194  pen.setWidth(s_segmentPenWidth);
195  p->setPen(pen);
196  QColor brush(s_segmentBrushColor);
197 
198  if (segment.containsPoint(m_hoveredPt, Qt::OddEvenFill))
199  brush = s_hoveredSegmentBrushColor;
200 
201  p->setBrush(brush);
202  p->drawPolygon(segment);
203 }
204 
205 QPoint KDDockWidgets::SegmentedIndicators::posForIndicator(DropLocation) const
206 {
208  return {};
209 }
QPainter::Antialiasing
Antialiasing
QColor
Qt::right
QTextStream & right(QTextStream &stream)
QVector::isEmpty
bool isEmpty() const const
QPainter::setPen
void setPen(const QColor &color)
KDDockWidgets::DropLocation_Top
@ DropLocation_Top
Definition: KDDockWidgets.h:232
QPolygon::containsPoint
bool containsPoint(const QPoint &point, Qt::FillRule fillRule) const const
QRect
QRect::right
int right() const const
KDDockWidgets::DropLocation_Center
@ DropLocation_Center
Definition: KDDockWidgets.h:235
Qt::left
QTextStream & left(QTextStream &stream)
QRect::width
int width() const const
QRect::x
int x() const const
QRect::y
int y() const const
QPoint::x
int x() const const
QPoint::y
int y() const const
QPolygon
QPainter
QPen
KDDockWidgets::DropLocation_Right
@ DropLocation_Right
Definition: KDDockWidgets.h:233
KDDockWidgets::DropLocation_Bottom
@ DropLocation_Bottom
Definition: KDDockWidgets.h:234
QPainter::drawPolygon
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
QRect::bottom
int bottom() const const
Qt::OddEvenFill
OddEvenFill
QVector::clear
void clear()
KDDockWidgets::DropLocation_OutterTop
@ DropLocation_OutterTop
Definition: KDDockWidgets.h:237
QRect::center
QPoint center() const const
KDDockWidgets::Config::setDraggedWindowOpacity
void setDraggedWindowOpacity(qreal opacity)
sets the dragged window opacity 1.0 is fully opaque while 0.0 is fully transparent
Definition: Config.cpp:165
QPolygon::boundingRect
QRect boundingRect() const const
QPainter::setBrush
void setBrush(const QBrush &brush)
Config.h
Application-wide config to tune certain behaviours of the framework.
KDDockWidgets::DropLocation_Left
@ DropLocation_Left
Definition: KDDockWidgets.h:231
QPaintEvent
KDDockWidgets::DropLocation_OutterLeft
@ DropLocation_OutterLeft
Definition: KDDockWidgets.h:236
KDDockWidgets
Definition: Config.cpp:37
KDDockWidgets::DropLocation_OutterRight
@ DropLocation_OutterRight
Definition: KDDockWidgets.h:238
Qt::center
QTextStream & center(QTextStream &stream)
KDDockWidgets::DropLocation
DropLocation
Enum describing the different drop indicator types.
Definition: KDDockWidgets.h:229
QVector
KDDockWidgets::DropLocation_None
@ DropLocation_None
Definition: KDDockWidgets.h:230
QHash
Qt::black
black
QPoint
KDDockWidgets::Config::self
static Config & self()
returns the singleton Config instance
Definition: Config.cpp:84
KDDockWidgets::DropLocation_OutterBottom
@ DropLocation_OutterBottom
Definition: KDDockWidgets.h:239

© 2019-2022 Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
KDDockWidgets
Advanced Dock Widget Framework for Qt
https://www.kdab.com/development-resources/qt-tools/kddockwidgets/
Generated on Thu Sep 15 2022 00:16:29 for KDDockWidgets API Documentation by doxygen 1.8.20