1 /* BEGIN_COMMON_COPYRIGHT_HEADER
2  * (c)LGPL2+
3  *
4  * LXQt - a lightweight, Qt based, desktop toolset
5  * https://lxqt.org
6  *
7  * Copyright: 2010-2013 Razor team
8  * Authors:
9  *   Kuzma Shapran <kuzma.shapran@gmail.com>
10  *
11  * This program or library is free software; you can redistribute it
12  * and/or modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20 
21  * You should have received a copy of the GNU Lesser General
22  * Public License along with this library; if not, write to the
23  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  * Boston, MA 02110-1301 USA
25  *
26  * END_COMMON_COPYRIGHT_HEADER */
27 
28 
29 #include "lxqtrotatedwidget.h"
30 
31 #include <QPainter>
32 #include <QImage>
33 
34 #include <QApplication>
35 
36 #include <QMouseEvent>
37 
38 #ifndef QT_NO_WHEELEVENT
39 #include <QWheelEvent>
40 #endif
41 
42 #include <QResizeEvent>
43 
44 using namespace LXQt;
45 
RotatedWidget(QWidget & content,QWidget * parent,Qt::WindowFlags f)46 RotatedWidget::RotatedWidget(QWidget &content, QWidget *parent, Qt::WindowFlags f)
47     : QWidget(parent, f)
48     , mContent(&content)
49     , mOrigin(Qt::TopLeftCorner)
50     , mTransferMousePressEvent(false)
51     , mTransferMouseReleaseEvent(false)
52     , mTransferMouseDoubleClickEvent(false)
53     , mTransferMouseMoveEvent(false)
54 #ifndef QT_NO_WHEELEVENT
55     , mTransferWheelEvent(false)
56 #endif
57     , mTransferEnterEvent(false)
58     , mTransferLeaveEvent(false)
59 {
60     mContent->setParent(this);
61 }
62 
origin() const63 Qt::Corner RotatedWidget::origin() const
64 {
65     return mOrigin;
66 }
67 
setOrigin(Qt::Corner newOrigin)68 void RotatedWidget::setOrigin(Qt::Corner newOrigin)
69 {
70     if (mOrigin != newOrigin)
71     {
72         if (mOrigin == Qt::TopLeftCorner)
73             mContent->hide();
74 
75         mOrigin = newOrigin;
76         adjustContentSize();
77         update();
78 
79         if (mOrigin == Qt::TopLeftCorner)
80             mContent->show();
81     }
82 }
83 
content() const84 QWidget * RotatedWidget::content() const
85 {
86     return mContent;
87 }
88 
adjustContentSize()89 void RotatedWidget::adjustContentSize()
90 {
91     mContent->adjustSize();
92 
93     const QSize before = size();
94 
95     adjustSize();
96 
97     if (before != size())
98         updateGeometry();
99 }
100 
adjustedSize(QSize size) const101 QSize RotatedWidget::adjustedSize(QSize size) const
102 {
103     switch (mOrigin)
104     {
105     case Qt::TopLeftCorner:
106     case Qt::BottomRightCorner:
107         break;
108 
109     case Qt::TopRightCorner:
110     case Qt::BottomLeftCorner:
111         size.transpose();
112         break;
113     }
114 
115     return size;
116 }
117 
adjustedPoint(QPointF point) const118 QPointF RotatedWidget::adjustedPoint(QPointF point) const
119 {
120     switch (mOrigin)
121     {
122     case Qt::TopLeftCorner:
123     case Qt::BottomRightCorner:
124         break;
125 
126     case Qt::TopRightCorner:
127     case Qt::BottomLeftCorner:
128         point = QPointF(point.y(), point.x());
129         break;
130     }
131 
132     return point;
133 }
134 
minimumSizeHint() const135 QSize RotatedWidget::minimumSizeHint() const
136 {
137     return adjustedSize(mContent->minimumSizeHint());
138 }
139 
sizeHint() const140 QSize RotatedWidget::sizeHint() const
141 {
142     return adjustedSize(mContent->sizeHint());
143 }
144 
paintEvent(QPaintEvent *)145 void RotatedWidget::paintEvent(QPaintEvent */*event*/)
146 {
147     if (mOrigin == Qt::TopLeftCorner)
148         return;
149 
150     const QSize sz = mContent->size();
151 
152     QPainter painter(this);
153 
154     QTransform transform;
155     QPoint originPoint;
156     switch (mOrigin)
157     {
158     case Qt::TopLeftCorner:
159 //        transform.rotate(0.0);
160 //        originPoint = QPoint(0.0, 0.0);
161         break;
162 
163     case Qt::TopRightCorner:
164         transform.rotate(90.0);
165         originPoint = QPoint(0.0, -sz.height());
166         break;
167 
168     case Qt::BottomRightCorner:
169         transform.rotate(180.0);
170         originPoint = QPoint(-sz.width(), -sz.height());
171         break;
172 
173     case Qt::BottomLeftCorner:
174         transform.rotate(270.0);
175         originPoint = QPoint(-sz.width(), 0.0);
176         break;
177     }
178     painter.setTransform(transform);
179     mContent->render(&painter, originPoint, QRegion(), RenderFlags(DrawChildren));
180 }
181 
mousePressEvent(QMouseEvent * event)182 void RotatedWidget::mousePressEvent(QMouseEvent *event)
183 {
184     if (!mTransferMousePressEvent)
185     {
186         event->ignore();
187         return;
188     }
189 
190     static bool cascadeCall = false;
191     if (cascadeCall)
192         return;
193     cascadeCall = true;
194 
195     QMouseEvent contentEvent(event->type(), adjustedPoint(event->pos()), event->globalPos(), event->button(), event->buttons(), event->modifiers());
196     QApplication::sendEvent(mContent, &contentEvent);
197 
198     cascadeCall = false;
199 }
200 
mouseReleaseEvent(QMouseEvent * event)201 void RotatedWidget::mouseReleaseEvent(QMouseEvent *event)
202 {
203     if (!mTransferMouseReleaseEvent)
204     {
205         event->ignore();
206         return;
207     }
208 
209     static bool cascadeCall = false;
210     if (cascadeCall)
211         return;
212     cascadeCall = true;
213 
214     QMouseEvent contentEvent(event->type(), adjustedPoint(event->pos()), event->globalPos(), event->button(), event->buttons(), event->modifiers());
215     QApplication::sendEvent(mContent, &contentEvent);
216 
217     cascadeCall = false;
218 }
219 
mouseDoubleClickEvent(QMouseEvent * event)220 void RotatedWidget::mouseDoubleClickEvent(QMouseEvent *event)
221 {
222     if (!mTransferMouseDoubleClickEvent)
223     {
224         event->ignore();
225         return;
226     }
227 
228     static bool cascadeCall = false;
229     if (cascadeCall)
230         return;
231     cascadeCall = true;
232 
233     QMouseEvent contentEvent(event->type(), adjustedPoint(event->pos()), event->globalPos(), event->button(), event->buttons(), event->modifiers());
234     QApplication::sendEvent(mContent, &contentEvent);
235 
236     cascadeCall = false;
237 }
238 
mouseMoveEvent(QMouseEvent * event)239 void RotatedWidget::mouseMoveEvent(QMouseEvent *event)
240 {
241     if (!mTransferMouseMoveEvent)
242     {
243         event->ignore();
244         return;
245     }
246 
247     static bool cascadeCall = false;
248     if (cascadeCall)
249         return;
250     cascadeCall = true;
251 
252     QMouseEvent contentEvent(event->type(), adjustedPoint(event->pos()), event->globalPos(), event->button(), event->buttons(), event->modifiers());
253     QApplication::sendEvent(mContent, &contentEvent);
254 
255     cascadeCall = false;
256 }
257 
258 #ifndef QT_NO_WHEELEVENT
wheelEvent(QWheelEvent * event)259 void RotatedWidget::wheelEvent(QWheelEvent *event)
260 {
261     if (!mTransferWheelEvent)
262     {
263         event->ignore();
264         return;
265     }
266 
267     static bool cascadeCall = false;
268     if (cascadeCall)
269         return;
270     cascadeCall = true;
271 
272     QWheelEvent contentEvent(adjustedPoint(event->position()), event->globalPosition(), event->pixelDelta(), event->angleDelta(), event->buttons(), event->modifiers(), event->phase(), false);
273     QApplication::sendEvent(mContent, &contentEvent);
274 
275     cascadeCall = false;
276 }
277 #endif
278 
enterEvent(QEvent * event)279 void RotatedWidget::enterEvent(QEvent *event)
280 {
281     if (!mTransferEnterEvent)
282     {
283         event->ignore();
284         return;
285     }
286 
287     static bool cascadeCall = false;
288     if (cascadeCall)
289         return;
290     cascadeCall = true;
291 
292     QApplication::sendEvent(mContent, event);
293 
294     cascadeCall = false;
295 }
296 
leaveEvent(QEvent * event)297 void RotatedWidget::leaveEvent(QEvent *event)
298 {
299     if (!mTransferLeaveEvent)
300     {
301         event->ignore();
302         return;
303     }
304 
305     static bool cascadeCall = false;
306     if (cascadeCall)
307         return;
308     cascadeCall = true;
309 
310     QApplication::sendEvent(mContent, event);
311 
312     cascadeCall = false;
313 }
314 
resizeEvent(QResizeEvent * event)315 void RotatedWidget::resizeEvent(QResizeEvent *event)
316 {
317     static bool cascadeCall = false;
318     if (cascadeCall)
319         return;
320     cascadeCall = true;
321 
322     QResizeEvent contentEvent(adjustedSize(event->size()), adjustedSize(event->oldSize()));
323     QApplication::sendEvent(mContent, &contentEvent);
324 
325     cascadeCall = false;
326 }
327