1 /* This file is part of the KDE project
2 * Copyright (C) 2001-2007 by OpenMFG, LLC (info@openmfg.com)
3 * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk)
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "KReportDesignerItemRectBase.h"
20 #include "KReportDesignerSectionView.h"
21 #include "KReportDesigner.h"
22 #include "KReportDesignerSectionScene.h"
23 #include "KReportUtils_p.h"
24
25 #include <KPropertySet>
26 #include <QGraphicsSceneMouseEvent>
27 #include <QApplication>
28
29 class Q_DECL_HIDDEN KReportDesignerItemRectBase::Private
30 {
31 public:
32 Private();
33 ~Private();
34
35 int grabAction = 0;
36 int dpiX = KReportPrivate::dpiX();
37 int dpiY = KReportPrivate::dpiY();
38 bool insideSetSceneRect = false;
39 };
40
Private()41 KReportDesignerItemRectBase::Private::Private()
42 {
43 }
44
~Private()45 KReportDesignerItemRectBase::Private::~Private()
46 {
47 }
48
KReportDesignerItemRectBase(KReportDesigner * r,KReportItemBase * b)49 KReportDesignerItemRectBase::KReportDesignerItemRectBase(KReportDesigner *r, KReportItemBase *b)
50 : QGraphicsRectItem(), KReportDesignerItemBase(r, b), d(new KReportDesignerItemRectBase::Private)
51 {
52 setAcceptHoverEvents(true);
53 setFlags(ItemIsSelectable | ItemIsMovable | ItemSendsGeometryChanges);
54 }
55
~KReportDesignerItemRectBase()56 KReportDesignerItemRectBase::~KReportDesignerItemRectBase()
57 {
58 delete d;
59 }
60
sceneRect()61 QRectF KReportDesignerItemRectBase::sceneRect()
62 {
63 return QRectF(KReportItemBase::scenePosition(item()->position()), KReportItemBase::sceneSize(item()->size()));
64 }
65
pointRect() const66 QRectF KReportDesignerItemRectBase::pointRect() const
67 {
68 return QRectF(item()->position(), item()->size());
69 }
70
setSceneRect(const QPointF & topLeft,const QSizeF & size,SceneRectFlag update)71 void KReportDesignerItemRectBase::setSceneRect(const QPointF& topLeft, const QSizeF& size, SceneRectFlag update)
72 {
73 setSceneRect(QRectF(topLeft, size), update);
74 }
75
setSceneRect(const QRectF & rect,SceneRectFlag update)76 void KReportDesignerItemRectBase::setSceneRect(const QRectF& rect, SceneRectFlag update)
77 {
78 if (d->insideSetSceneRect) {
79 return;
80 }
81 d->insideSetSceneRect = true;
82 QGraphicsRectItem::setPos(rect.x(), rect.y());
83 setRect(0, 0, rect.width(), rect.height());
84 if (update == SceneRectFlag::UpdateProperty) {
85 item()->setPosition(KReportItemBase::positionFromScene(QPointF(rect.x(), rect.y())));
86 item()->setSize(KReportItemBase::sizeFromScene(QSizeF(rect.width(), rect.height())));
87 }
88 this->update();
89 d->insideSetSceneRect = false;
90 }
91
mousePressEvent(QGraphicsSceneMouseEvent * event)92 void KReportDesignerItemRectBase::mousePressEvent(QGraphicsSceneMouseEvent * event)
93 {
94 //Update and show properties
95 if (item()->dataSourceProperty()) {
96 item()->dataSourceProperty()->setListData(designer()->fieldKeys(), designer()->fieldNames());
97 }
98 item()->setPosition(KReportItemBase::positionFromScene(QPointF(sceneRect().x(), sceneRect().y())));
99 designer()->changeSet(item()->propertySet());
100 setSelected(true);
101 scene()->update();
102
103 QGraphicsItem::mousePressEvent(event);
104 }
105
mouseReleaseEvent(QGraphicsSceneMouseEvent * event)106 void KReportDesignerItemRectBase::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
107 {
108 //Keep the size and position in sync
109 item()->setPosition(KReportItemBase::positionFromScene(pos()));
110 item()->setSize(KReportItemBase::sizeFromScene(QSizeF(rect().width(), rect().height())));
111
112 QGraphicsItem::mouseReleaseEvent(event);
113 }
114
mouseMoveEvent(QGraphicsSceneMouseEvent * event)115 void KReportDesignerItemRectBase::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
116 {
117 //kreportDebug() << m_grabAction;
118
119 qreal w, h;
120
121 KReportDesignerSectionScene *section = qobject_cast<KReportDesignerSectionScene*>(scene());
122 if (!section) {
123 return;
124 }
125
126 QPointF p = section->gridPoint(event->scenePos());
127 w = p.x() - scenePos().x();
128 h = p.y() - scenePos().y();
129
130 //! @todo use an enum for the directions
131
132 switch (d->grabAction) {
133 case 1:
134 if (sceneRect().y() - p.y() + rect().height() > 0 && sceneRect().x() - p.x() + rect().width() >= 0)
135 setSceneRect(QPointF(p.x(), p.y()), QSizeF(sceneRect().x() - p.x() + rect().width(), sceneRect().y() - p.y() + rect().height()));
136 break;
137 case 2:
138 if (sceneRect().y() - p.y() + rect().height() >= 0)
139 setSceneRect(QPointF(sceneRect().x(), p.y()), QSizeF(rect().width(), sceneRect().y() - p.y() + rect().height()));
140 break;
141 case 3:
142 if (sceneRect().y() - p.y() + rect().height() >= 0 && w >= 0)
143 setSceneRect(QPointF(sceneRect().x(), p.y()), QSizeF(w, sceneRect().y() - p.y() + rect().height()));
144 break;
145 case 4:
146 if (w >= 0)
147 setSceneRect(QPointF(sceneRect().x(), sceneRect().y()), QSizeF(w, (rect().height())));
148 break;
149 case 5:
150 if (h >= 0 && w >= 0)
151 setSceneRect(QPointF(sceneRect().x(), sceneRect().y()), QSizeF(w, h));
152 break;
153 case 6:
154 if (h >= 0)
155 setSceneRect(QPointF(sceneRect().x(), sceneRect().y()), QSizeF((rect().width()), h));
156 break;
157 case 7:
158 if (sceneRect().x() - p.x() + rect().width() >= 0 && h >= 0)
159 setSceneRect(QPointF(p.x(), sceneRect().y()), QSizeF(sceneRect().x() - p.x() + rect().width(), h));
160 break;
161 case 8:
162 if (sceneRect().x() - p.x() + rect().width() >= 0)
163 setSceneRect(QPointF(p.x(), sceneRect().y()), QSizeF(sceneRect().x() - p.x() + rect().width(), rect().height()));
164 break;
165 default:
166 QGraphicsItem::mouseMoveEvent(event);
167 }
168 }
169
hoverMoveEvent(QGraphicsSceneHoverEvent * event)170 void KReportDesignerItemRectBase::hoverMoveEvent(QGraphicsSceneHoverEvent * event)
171 {
172 //m_grabAction = 0;
173
174 if (isSelected()) {
175 d->grabAction = grabHandle(event->pos());
176 switch (d->grabAction) {
177 case 1:
178 setCursor(Qt::SizeFDiagCursor);
179 break;
180 case 2:
181 setCursor(Qt::SizeVerCursor);
182 break;
183 case 3:
184 setCursor(Qt::SizeBDiagCursor);
185 break;
186 case 4:
187 setCursor(Qt::SizeHorCursor);
188 break;
189 case 5:
190 setCursor(Qt::SizeFDiagCursor);
191 break;
192 case 6:
193 setCursor(Qt::SizeVerCursor);
194 break;
195 case 7:
196 setCursor(Qt::SizeBDiagCursor);
197 break;
198 case 8:
199 setCursor(Qt::SizeHorCursor);
200 break;
201 default:
202 unsetCursor();
203 }
204 }
205 //kreportDebug() << m_grabAction;
206 }
207
drawHandles(QPainter * painter)208 void KReportDesignerItemRectBase::drawHandles(QPainter *painter)
209 {
210 if (isSelected()) {
211 // draw a selected border for visual purposes
212 painter->setPen(QPen(QColor(128, 128, 255), 0, Qt::DotLine));
213
214 painter->drawRect(rect());
215
216 const QRectF r = rect();
217 double halfW = (r.width() / 2);
218 double halfH = (r.height() / 2);
219 QPointF center = r.center();
220
221 center += QPointF(0.75,0.75);
222
223 painter->fillRect(center.x() - halfW, center.y() - halfH , 5, 5, QColor(128, 128, 255));
224 painter->fillRect(center.x() - 2, center.y() - halfH , 5, 5, QColor(128, 128, 255));
225 painter->fillRect(center.x() + halfW - 4, center.y() - halfH, 5, 5, QColor(128, 128, 255));
226
227 painter->fillRect(center.x() + (halfW - 4), center.y() - 2, 5, 5, QColor(128, 128, 255));
228
229 painter->fillRect(center.x() + halfW - 4 , center.y() + halfH - 4 , 5, 5, QColor(128, 128, 255));
230 painter->fillRect(center.x() - 2, center.y() + halfH - 4, 5, 5, QColor(128, 128, 255));
231 painter->fillRect(center.x() - halfW, center.y() + halfH - 4 , 5, 5, QColor(128, 128, 255));
232
233 painter->fillRect(center.x() - halfW, center.y() - 2, 5, 5, QColor(128, 128, 255));
234
235 }
236 }
237
238 /**
239 @return 1 2 3
240 8 0 4
241 7 6 5
242 */
grabHandle(const QPointF & pos)243 int KReportDesignerItemRectBase::grabHandle(const QPointF &pos)
244 {
245 QRectF r = boundingRect();
246 int halfW = (int)(r.width() / 2);
247 int halfH = (int)(r.height() / 2);
248 QPointF center = r.center();
249
250 if (QRectF(center.x() - (halfW), center.y() - (halfH), 5, 5).contains(pos)) {
251 // we are over the top-left handle
252 return 1;
253 } else if (QRectF(center.x() - 2, center.y() - (halfH), 5, 5).contains(pos)) {
254 // top-middle handle
255 return 2;
256 } else if (QRectF(center.x() + (halfW - 4), center.y() - (halfH), 5, 5).contains(pos)) {
257 // top-right
258 return 3;
259 } else if (QRectF(center.x() + (halfW - 4), center.y() - 2, 5, 5).contains(pos)) {
260 // middle-right
261 return 4;
262 } else if (QRectF(center.x() + (halfW - 4), center.y() + (halfH - 4), 5, 5).contains(pos)) {
263 // bottom-left
264 return 5;
265 } else if (QRectF(center.x() - 2, center.y() + (halfH - 4), 5, 5).contains(pos)) {
266 // bottom-middle
267 return 6;
268 } else if (QRectF(center.x() - (halfW), center.y() + (halfH - 4), 5, 5).contains(pos)) {
269 // bottom-right
270 return 7;
271 } else if (QRectF(center.x() - (halfW), center.y() - 2, 5, 5).contains(pos)) {
272 // middle-right
273 return 8;
274 }
275 return 0;
276 }
277
itemChange(GraphicsItemChange change,const QVariant & value)278 QVariant KReportDesignerItemRectBase::itemChange(GraphicsItemChange change, const QVariant &value)
279 {
280 KReportDesignerSectionScene *section = qobject_cast<KReportDesignerSectionScene*>(scene());
281 if (section) {
282
283 if (change == ItemPositionChange) {
284 QPointF newPos = value.toPointF();
285
286 newPos = section->gridPoint(newPos);
287 if (newPos.x() < 0)
288 newPos.setX(0);
289 else if (newPos.x() > (scene()->width() - rect().width()))
290 newPos.setX(scene()->width() - rect().width());
291
292 if (newPos.y() < 0)
293 newPos.setY(0);
294 else if (newPos.y() > (scene()->height() - rect().height()))
295 newPos.setY(scene()->height() - rect().height());
296
297 return newPos;
298 } else if (change == ItemPositionHasChanged) {
299 setSceneRect(value.toPointF(),
300 KReportItemBase::sceneSize(item()->size()), SceneRectFlag::UpdateProperty);
301 } else if (change == ItemSceneHasChanged && item()) {
302 QPointF newPos = pos();
303
304 newPos = section->gridPoint(newPos);
305 if (newPos.x() < 0)
306 newPos.setX(0);
307 else if (newPos.x() > (scene()->width() - rect().width()))
308 newPos.setX(scene()->width() - rect().width());
309
310 if (newPos.y() < 0)
311 newPos.setY(0);
312 else if (newPos.y() > (scene()->height() - rect().height()))
313 newPos.setY(scene()->height() - rect().height());
314
315 setSceneRect(newPos, KReportItemBase::sceneSize(item()->size()),
316 KReportDesignerItemRectBase::SceneRectFlag::DontUpdateProperty);
317 }
318 }
319 return QGraphicsItem::itemChange(change, value);
320 }
321
propertyChanged(const KPropertySet & s,const KProperty & p)322 void KReportDesignerItemRectBase::propertyChanged(const KPropertySet &s, const KProperty &p)
323 {
324 Q_UNUSED(s)
325 Q_UNUSED(p)
326 #if 0
327 if (p.name() == "position") {
328 item()->setPosition(item()->unit().convertToPoint(p.value().toPointF())); //TODO dont update property
329 } else if (p.name() == "size") {
330 item()->setSize(item()->unit().convertToPoint(p.value().toSizeF())); //TODO dont update property
331 }
332 #endif
333 setSceneRect(KReportItemBase::scenePosition(item()->position()),
334 KReportItemBase::sceneSize(item()->size()), SceneRectFlag::DontUpdateProperty);
335 }
336
move(const QPointF &)337 void KReportDesignerItemRectBase::move(const QPointF& /*m*/)
338 {
339 //! @todo
340 }
341
properPressPoint(const KReportDesigner & d) const342 QPointF KReportDesignerItemRectBase::properPressPoint(const KReportDesigner &d) const
343 {
344 const QPointF pressPoint = d.getPressPoint();
345 const QPointF releasePoint = d.getReleasePoint();
346 if (releasePoint.x() < pressPoint.x() && releasePoint.y() < pressPoint.y()) {
347 return releasePoint;
348 }
349 if (releasePoint.x() < pressPoint.x() && releasePoint.y() > pressPoint.y()) {
350 return QPointF(releasePoint.x(), pressPoint.y());
351 }
352 if (releasePoint.x() > pressPoint.x() && releasePoint.y() < pressPoint.y()) {
353 return QPointF(pressPoint.x(), releasePoint.y());
354 }
355 return QPointF(pressPoint);
356 }
357
properRect(const KReportDesigner & d,qreal minWidth,qreal minHeight) const358 QRectF KReportDesignerItemRectBase::properRect(const KReportDesigner &d, qreal minWidth, qreal minHeight) const
359 {
360 QPointF tempPressPoint = properPressPoint(d);
361 qreal currentPressX = tempPressPoint.x();
362 qreal currentPressY = tempPressPoint.y();
363 const qreal width = qMax(d.countSelectionWidth(), minWidth);
364 const qreal height = qMax(d.countSelectionHeight(), minHeight);
365
366 qreal tempReleasePointX = tempPressPoint.x() + width;
367 qreal tempReleasePointY = tempPressPoint.y() + height;
368
369 if (tempReleasePointX > scene()->width()) {
370 int offsetWidth = tempReleasePointX - scene()->width();
371 currentPressX = tempPressPoint.x() - offsetWidth;
372 }
373 if (tempReleasePointY > scene()->height()) {
374 int offsetHeight = tempReleasePointY - scene()->height();
375 currentPressY = tempPressPoint.y() - offsetHeight;
376 }
377 return (QRectF(QPointF(currentPressX, currentPressY), QSizeF(width, height)));
378 }
379
enterInlineEditingMode()380 void KReportDesignerItemRectBase::enterInlineEditingMode()
381 {
382 }
383
exitInlineEditingMode()384 void KReportDesignerItemRectBase::exitInlineEditingMode()
385 {
386 }
387
updateRenderText(const QString & itemDataSource,const QString & itemStaticValue,const QString & itemType)388 void KReportDesignerItemBase::updateRenderText(const QString &itemDataSource, const QString &itemStaticValue, const QString &itemType)
389 {
390 if (itemDataSource.isEmpty()) {
391 if (itemType.isEmpty()) {
392 setRenderText(itemStaticValue);
393 } else {
394 setRenderText(dataSourceAndObjectTypeName(itemStaticValue, itemType));
395 }
396 } else {
397 if (itemType.isEmpty()) {
398 setRenderText(itemDataSource);
399 } else {
400 setRenderText(dataSourceAndObjectTypeName(itemDataSource, itemType));
401 }
402 }
403 }
404
dpiX() const405 int KReportDesignerItemRectBase::dpiX() const
406 {
407 return d->dpiX;
408 }
409
dpiY() const410 int KReportDesignerItemRectBase::dpiY() const
411 {
412 return d->dpiY;
413 }
414