QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskSubWindowArea.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskSubWindowArea.h"
7#include "QskEvent.h"
8#include "QskPlatform.h"
9#include "QskSubWindow.h"
10
11#include <qtimer.h>
12
13QSK_SUBCONTROL( QskSubWindowArea, Panel )
14
15static void qskUpdateEventFilter( QskSubWindowArea* area )
16{
17 for ( auto child : area->children() )
18 {
19 if ( auto window = qobject_cast< QskSubWindow* >( child ) )
20 {
21 window->removeEventFilter( area );
22 window->installEventFilter( area );
23 }
24 }
25}
26
27static Qt::Edges qskSelectedEdges( const QskSubWindowArea* area,
28 const QRectF& rect, const QPointF& pos )
29{
30 const qreal tolerance = qskMMToPixels( area->window(), 3 );
31
32 Qt::Edges edges;
33 if ( pos.x() <= rect.left() + tolerance )
34 {
35 edges |= Qt::LeftEdge;
36 }
37 else if ( pos.x() >= rect.right() - tolerance )
38 {
39 edges |= Qt::RightEdge;
40 }
41
42 if ( pos.y() <= rect.top() + tolerance )
43 {
44 edges |= Qt::TopEdge;
45 }
46 else if ( pos.y() >= rect.bottom() - tolerance )
47 {
48 edges |= Qt::BottomEdge;
49 }
50
51 return edges;
52}
53
54static void qskDragWindow( const QPointF& off, Qt::Edges edges, QskSubWindow* window )
55{
56 if ( edges == 0 )
57 {
58 window->setPosition( window->position() + off );
59 }
60 else
61 {
62 QRectF rect( window->position(), window->size() );
63
64 if ( edges & Qt::LeftEdge )
65 rect.setLeft( rect.left() + off.x() );
66
67 if ( edges & Qt::RightEdge )
68 rect.setRight( rect.right() + off.x() );
69
70 if ( edges & Qt::TopEdge )
71 rect.setTop( rect.top() + off.y() );
72
73 if ( edges & Qt::BottomEdge )
74 rect.setBottom( rect.bottom() + off.y() );
75
76 window->setGeometry( rect );
77 }
78}
79
80class QskSubWindowArea::PrivateData
81{
82 public:
83 PrivateData()
84 : isDraggableByHeaderOnly( false )
85 , isDragging( false )
86 {
87 }
88
89 // data about the window being dragged
90
91 bool isDraggableByHeaderOnly : 1;
92 bool isDragging : 1;
93 Qt::Edges draggedEdges;
94 QPointF mousePos;
95};
96
97QskSubWindowArea::QskSubWindowArea( QQuickItem* parent )
98 : Inherited( parent )
99 , m_data( new PrivateData() )
100{
101 setMargins( 0 );
102 // setAcceptedMouseButtons( Qt::AllButtons );
103}
104
105QskSubWindowArea::~QskSubWindowArea()
106{
107}
108
110{
111 if ( event->isResized() )
112 {
113 // what to do with the windows ???
114 }
115
117}
118
119void QskSubWindowArea::itemChange(
120 QQuickItem::ItemChange change, const QQuickItem::ItemChangeData& value )
121{
122 Inherited::itemChange( change, value );
123
124 switch ( change )
125 {
126 case QQuickItem::ItemChildAddedChange:
127 {
128 // the child is not fully constructed
129 // and we have to delay checking for sub windows
130 QMetaObject::invokeMethod( this,
131 [ this ] { qskUpdateEventFilter( this ); }, Qt::QueuedConnection );
132
133 break;
134 }
135 case QQuickItem::ItemChildRemovedChange:
136 {
137 if ( qobject_cast< QskSubWindow* >( value.item ) )
138 value.item->removeEventFilter( this );
139
140 break;
141 }
142 default:
143 {
144 break;
145 }
146 }
147}
148
149bool QskSubWindowArea::eventFilter( QObject* object, QEvent* event )
150{
151 if ( QskSubWindow* window = qobject_cast< QskSubWindow* >( object ) )
152 {
153 switch ( event->type() )
154 {
155 case QEvent::MouseButtonPress:
156 case QEvent::MouseButtonRelease:
157 case QEvent::MouseMove:
158 {
159 bool ok = mouseEventFilter( window, static_cast< QMouseEvent* >( event ) );
160 if ( ok )
161 return true;
162
163 break;
164 }
165 case QEvent::Enter:
166 {
167 setActive( window, true );
168 break;
169 }
170 case QEvent::Leave:
171 {
172 setActive( window, false );
173 break;
174 }
175 default:
176 {
177 break;
178 }
179 }
180 }
181
182 return Inherited::eventFilter( object, event );
183}
184
185bool QskSubWindowArea::mouseEventFilter( QskSubWindow* window, const QMouseEvent* event )
186{
187 if ( window == nullptr || window->parentItem() != this )
188 return false;
189
190 const QRectF cr = window->contentsRect();
191
192 switch ( event->type() )
193 {
194 case QEvent::MouseButtonPress:
195 {
196 const auto mousePos = qskMousePosition( event );
197
198 if ( !( cr.contains( mousePos ) &&
199 event->button() == Qt::LeftButton ) )
200 {
201 return false;
202 }
203
204 if ( event->button() == Qt::LeftButton )
205 window->setFocus( true );
206
207#if 0
208 if ( window->titleBarRect().contains( qskMousePosition( event ) ) )
209 {
210 /*
211 block button press until we know it is no double click.
212 QGuiApplication::styleHints()->mouseDoubleClickInterval()
213 */
214 }
215#endif
216 bool doDrag = !m_data->isDraggableByHeaderOnly;
217 if ( !doDrag )
218 {
219 // dragging by title bar only
220 doDrag = window->titleBarRect().contains( mousePos );
221 }
222
223 if ( doDrag )
224 {
225 m_data->isDragging = true;
226 m_data->draggedEdges = qskSelectedEdges( this, cr, mousePos );
227 m_data->mousePos = qskMouseScenePosition( event );
228
229 setDragging( window, true );
230 return true;
231 }
232
233 break;
234 }
235 case QEvent::MouseMove:
236 {
237 if ( m_data->isDragging )
238 {
239 const auto scenePos = qskMouseScenePosition( event );
240
241 qskDragWindow( scenePos - m_data->mousePos,
242 m_data->draggedEdges, window );
243
244 m_data->mousePos = scenePos;
245 return true;
246 }
247 break;
248 }
249 case QEvent::MouseButtonRelease:
250 {
251 if ( m_data->isDragging )
252 {
253 setDragging( window, false );
254
255 m_data->mousePos = QPointF();
256 m_data->isDragging = false;
257
258 return true;
259 }
260 break;
261 }
262 default:
263 {
264 break;
265 }
266 }
267
268 return false;
269}
270
271void QskSubWindowArea::setDragging( QskSubWindow* window, bool on )
272{
273 window->setOpacity( on ? 0.6 : 1.0 );
274}
275
276void QskSubWindowArea::setActive( QskSubWindow* window, bool on )
277{
278 qDebug() << window << on;
279}
280
281#include "moc_QskSubWindowArea.cpp"
void itemChange(ItemChange, const ItemChangeData &) override
QRectF contentsRect() const
virtual void geometryChangeEvent(QskGeometryChangeEvent *)
Definition QskItem.cpp:855
void setGeometry(qreal x, qreal y, qreal width, qreal height)
Definition QskItem.cpp:330
void geometryChangeEvent(QskGeometryChangeEvent *) override