File indexing completed on 2024-04-28 04:42:10
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2001-2007 by OpenMFG, LLC (info@openmfg.com) 0003 * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk) 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Lesser General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2.1 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Lesser General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Lesser General Public 0016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 0017 */ 0018 0019 #include "KReportDesignerItemRectBase.h" 0020 #include "KReportDesignerSectionView.h" 0021 #include "KReportDesigner.h" 0022 #include "KReportDesignerSectionScene.h" 0023 #include "KReportUtils_p.h" 0024 0025 #include <KPropertySet> 0026 #include <QGraphicsSceneMouseEvent> 0027 #include <QApplication> 0028 0029 class Q_DECL_HIDDEN KReportDesignerItemRectBase::Private 0030 { 0031 public: 0032 Private(); 0033 ~Private(); 0034 0035 int grabAction = 0; 0036 int dpiX = KReportPrivate::dpiX(); 0037 int dpiY = KReportPrivate::dpiY(); 0038 bool insideSetSceneRect = false; 0039 }; 0040 0041 KReportDesignerItemRectBase::Private::Private() 0042 { 0043 } 0044 0045 KReportDesignerItemRectBase::Private::~Private() 0046 { 0047 } 0048 0049 KReportDesignerItemRectBase::KReportDesignerItemRectBase(KReportDesigner *r, KReportItemBase *b) 0050 : QGraphicsRectItem(), KReportDesignerItemBase(r, b), d(new KReportDesignerItemRectBase::Private) 0051 { 0052 setAcceptHoverEvents(true); 0053 setFlags(ItemIsSelectable | ItemIsMovable | ItemSendsGeometryChanges); 0054 } 0055 0056 KReportDesignerItemRectBase::~KReportDesignerItemRectBase() 0057 { 0058 delete d; 0059 } 0060 0061 QRectF KReportDesignerItemRectBase::sceneRect() 0062 { 0063 return QRectF(KReportItemBase::scenePosition(item()->position()), KReportItemBase::sceneSize(item()->size())); 0064 } 0065 0066 QRectF KReportDesignerItemRectBase::pointRect() const 0067 { 0068 return QRectF(item()->position(), item()->size()); 0069 } 0070 0071 void KReportDesignerItemRectBase::setSceneRect(const QPointF& topLeft, const QSizeF& size, SceneRectFlag update) 0072 { 0073 setSceneRect(QRectF(topLeft, size), update); 0074 } 0075 0076 void KReportDesignerItemRectBase::setSceneRect(const QRectF& rect, SceneRectFlag update) 0077 { 0078 if (d->insideSetSceneRect) { 0079 return; 0080 } 0081 d->insideSetSceneRect = true; 0082 QGraphicsRectItem::setPos(rect.x(), rect.y()); 0083 setRect(0, 0, rect.width(), rect.height()); 0084 if (update == SceneRectFlag::UpdateProperty) { 0085 item()->setPosition(KReportItemBase::positionFromScene(QPointF(rect.x(), rect.y()))); 0086 item()->setSize(KReportItemBase::sizeFromScene(QSizeF(rect.width(), rect.height()))); 0087 } 0088 this->update(); 0089 d->insideSetSceneRect = false; 0090 } 0091 0092 void KReportDesignerItemRectBase::mousePressEvent(QGraphicsSceneMouseEvent * event) 0093 { 0094 //Update and show properties 0095 if (item()->dataSourceProperty()) { 0096 item()->dataSourceProperty()->setListData(designer()->fieldKeys(), designer()->fieldNames()); 0097 } 0098 item()->setPosition(KReportItemBase::positionFromScene(QPointF(sceneRect().x(), sceneRect().y()))); 0099 designer()->changeSet(item()->propertySet()); 0100 setSelected(true); 0101 scene()->update(); 0102 0103 QGraphicsItem::mousePressEvent(event); 0104 } 0105 0106 void KReportDesignerItemRectBase::mouseReleaseEvent(QGraphicsSceneMouseEvent * event) 0107 { 0108 //Keep the size and position in sync 0109 item()->setPosition(KReportItemBase::positionFromScene(pos())); 0110 item()->setSize(KReportItemBase::sizeFromScene(QSizeF(rect().width(), rect().height()))); 0111 0112 QGraphicsItem::mouseReleaseEvent(event); 0113 } 0114 0115 void KReportDesignerItemRectBase::mouseMoveEvent(QGraphicsSceneMouseEvent * event) 0116 { 0117 //kreportDebug() << m_grabAction; 0118 0119 qreal w, h; 0120 0121 KReportDesignerSectionScene *section = qobject_cast<KReportDesignerSectionScene*>(scene()); 0122 if (!section) { 0123 return; 0124 } 0125 0126 QPointF p = section->gridPoint(event->scenePos()); 0127 w = p.x() - scenePos().x(); 0128 h = p.y() - scenePos().y(); 0129 0130 //! @todo use an enum for the directions 0131 0132 switch (d->grabAction) { 0133 case 1: 0134 if (sceneRect().y() - p.y() + rect().height() > 0 && sceneRect().x() - p.x() + rect().width() >= 0) 0135 setSceneRect(QPointF(p.x(), p.y()), QSizeF(sceneRect().x() - p.x() + rect().width(), sceneRect().y() - p.y() + rect().height())); 0136 break; 0137 case 2: 0138 if (sceneRect().y() - p.y() + rect().height() >= 0) 0139 setSceneRect(QPointF(sceneRect().x(), p.y()), QSizeF(rect().width(), sceneRect().y() - p.y() + rect().height())); 0140 break; 0141 case 3: 0142 if (sceneRect().y() - p.y() + rect().height() >= 0 && w >= 0) 0143 setSceneRect(QPointF(sceneRect().x(), p.y()), QSizeF(w, sceneRect().y() - p.y() + rect().height())); 0144 break; 0145 case 4: 0146 if (w >= 0) 0147 setSceneRect(QPointF(sceneRect().x(), sceneRect().y()), QSizeF(w, (rect().height()))); 0148 break; 0149 case 5: 0150 if (h >= 0 && w >= 0) 0151 setSceneRect(QPointF(sceneRect().x(), sceneRect().y()), QSizeF(w, h)); 0152 break; 0153 case 6: 0154 if (h >= 0) 0155 setSceneRect(QPointF(sceneRect().x(), sceneRect().y()), QSizeF((rect().width()), h)); 0156 break; 0157 case 7: 0158 if (sceneRect().x() - p.x() + rect().width() >= 0 && h >= 0) 0159 setSceneRect(QPointF(p.x(), sceneRect().y()), QSizeF(sceneRect().x() - p.x() + rect().width(), h)); 0160 break; 0161 case 8: 0162 if (sceneRect().x() - p.x() + rect().width() >= 0) 0163 setSceneRect(QPointF(p.x(), sceneRect().y()), QSizeF(sceneRect().x() - p.x() + rect().width(), rect().height())); 0164 break; 0165 default: 0166 QGraphicsItem::mouseMoveEvent(event); 0167 } 0168 } 0169 0170 void KReportDesignerItemRectBase::hoverMoveEvent(QGraphicsSceneHoverEvent * event) 0171 { 0172 //m_grabAction = 0; 0173 0174 if (isSelected()) { 0175 d->grabAction = grabHandle(event->pos()); 0176 switch (d->grabAction) { 0177 case 1: 0178 setCursor(Qt::SizeFDiagCursor); 0179 break; 0180 case 2: 0181 setCursor(Qt::SizeVerCursor); 0182 break; 0183 case 3: 0184 setCursor(Qt::SizeBDiagCursor); 0185 break; 0186 case 4: 0187 setCursor(Qt::SizeHorCursor); 0188 break; 0189 case 5: 0190 setCursor(Qt::SizeFDiagCursor); 0191 break; 0192 case 6: 0193 setCursor(Qt::SizeVerCursor); 0194 break; 0195 case 7: 0196 setCursor(Qt::SizeBDiagCursor); 0197 break; 0198 case 8: 0199 setCursor(Qt::SizeHorCursor); 0200 break; 0201 default: 0202 unsetCursor(); 0203 } 0204 } 0205 //kreportDebug() << m_grabAction; 0206 } 0207 0208 void KReportDesignerItemRectBase::drawHandles(QPainter *painter) 0209 { 0210 if (isSelected()) { 0211 // draw a selected border for visual purposes 0212 painter->setPen(QPen(QColor(128, 128, 255), 0, Qt::DotLine)); 0213 0214 painter->drawRect(rect()); 0215 0216 const QRectF r = rect(); 0217 double halfW = (r.width() / 2); 0218 double halfH = (r.height() / 2); 0219 QPointF center = r.center(); 0220 0221 center += QPointF(0.75,0.75); 0222 0223 painter->fillRect(center.x() - halfW, center.y() - halfH , 5, 5, QColor(128, 128, 255)); 0224 painter->fillRect(center.x() - 2, center.y() - halfH , 5, 5, QColor(128, 128, 255)); 0225 painter->fillRect(center.x() + halfW - 4, center.y() - halfH, 5, 5, QColor(128, 128, 255)); 0226 0227 painter->fillRect(center.x() + (halfW - 4), center.y() - 2, 5, 5, QColor(128, 128, 255)); 0228 0229 painter->fillRect(center.x() + halfW - 4 , center.y() + halfH - 4 , 5, 5, QColor(128, 128, 255)); 0230 painter->fillRect(center.x() - 2, center.y() + halfH - 4, 5, 5, QColor(128, 128, 255)); 0231 painter->fillRect(center.x() - halfW, center.y() + halfH - 4 , 5, 5, QColor(128, 128, 255)); 0232 0233 painter->fillRect(center.x() - halfW, center.y() - 2, 5, 5, QColor(128, 128, 255)); 0234 0235 } 0236 } 0237 0238 /** 0239 @return 1 2 3 0240 8 0 4 0241 7 6 5 0242 */ 0243 int KReportDesignerItemRectBase::grabHandle(const QPointF &pos) 0244 { 0245 QRectF r = boundingRect(); 0246 int halfW = (int)(r.width() / 2); 0247 int halfH = (int)(r.height() / 2); 0248 QPointF center = r.center(); 0249 0250 if (QRectF(center.x() - (halfW), center.y() - (halfH), 5, 5).contains(pos)) { 0251 // we are over the top-left handle 0252 return 1; 0253 } else if (QRectF(center.x() - 2, center.y() - (halfH), 5, 5).contains(pos)) { 0254 // top-middle handle 0255 return 2; 0256 } else if (QRectF(center.x() + (halfW - 4), center.y() - (halfH), 5, 5).contains(pos)) { 0257 // top-right 0258 return 3; 0259 } else if (QRectF(center.x() + (halfW - 4), center.y() - 2, 5, 5).contains(pos)) { 0260 // middle-right 0261 return 4; 0262 } else if (QRectF(center.x() + (halfW - 4), center.y() + (halfH - 4), 5, 5).contains(pos)) { 0263 // bottom-left 0264 return 5; 0265 } else if (QRectF(center.x() - 2, center.y() + (halfH - 4), 5, 5).contains(pos)) { 0266 // bottom-middle 0267 return 6; 0268 } else if (QRectF(center.x() - (halfW), center.y() + (halfH - 4), 5, 5).contains(pos)) { 0269 // bottom-right 0270 return 7; 0271 } else if (QRectF(center.x() - (halfW), center.y() - 2, 5, 5).contains(pos)) { 0272 // middle-right 0273 return 8; 0274 } 0275 return 0; 0276 } 0277 0278 QVariant KReportDesignerItemRectBase::itemChange(GraphicsItemChange change, const QVariant &value) 0279 { 0280 KReportDesignerSectionScene *section = qobject_cast<KReportDesignerSectionScene*>(scene()); 0281 if (section) { 0282 0283 if (change == ItemPositionChange) { 0284 QPointF newPos = value.toPointF(); 0285 0286 newPos = section->gridPoint(newPos); 0287 if (newPos.x() < 0) 0288 newPos.setX(0); 0289 else if (newPos.x() > (scene()->width() - rect().width())) 0290 newPos.setX(scene()->width() - rect().width()); 0291 0292 if (newPos.y() < 0) 0293 newPos.setY(0); 0294 else if (newPos.y() > (scene()->height() - rect().height())) 0295 newPos.setY(scene()->height() - rect().height()); 0296 0297 return newPos; 0298 } else if (change == ItemPositionHasChanged) { 0299 setSceneRect(value.toPointF(), 0300 KReportItemBase::sceneSize(item()->size()), SceneRectFlag::UpdateProperty); 0301 } else if (change == ItemSceneHasChanged && item()) { 0302 QPointF newPos = pos(); 0303 0304 newPos = section->gridPoint(newPos); 0305 if (newPos.x() < 0) 0306 newPos.setX(0); 0307 else if (newPos.x() > (scene()->width() - rect().width())) 0308 newPos.setX(scene()->width() - rect().width()); 0309 0310 if (newPos.y() < 0) 0311 newPos.setY(0); 0312 else if (newPos.y() > (scene()->height() - rect().height())) 0313 newPos.setY(scene()->height() - rect().height()); 0314 0315 setSceneRect(newPos, KReportItemBase::sceneSize(item()->size()), 0316 KReportDesignerItemRectBase::SceneRectFlag::DontUpdateProperty); 0317 } 0318 } 0319 return QGraphicsItem::itemChange(change, value); 0320 } 0321 0322 void KReportDesignerItemRectBase::propertyChanged(const KPropertySet &s, const KProperty &p) 0323 { 0324 Q_UNUSED(s) 0325 Q_UNUSED(p) 0326 #if 0 0327 if (p.name() == "position") { 0328 item()->setPosition(item()->unit().convertToPoint(p.value().toPointF())); //TODO dont update property 0329 } else if (p.name() == "size") { 0330 item()->setSize(item()->unit().convertToPoint(p.value().toSizeF())); //TODO dont update property 0331 } 0332 #endif 0333 setSceneRect(KReportItemBase::scenePosition(item()->position()), 0334 KReportItemBase::sceneSize(item()->size()), SceneRectFlag::DontUpdateProperty); 0335 } 0336 0337 void KReportDesignerItemRectBase::move(const QPointF& /*m*/) 0338 { 0339 //! @todo 0340 } 0341 0342 QPointF KReportDesignerItemRectBase::properPressPoint(const KReportDesigner &d) const 0343 { 0344 const QPointF pressPoint = d.getPressPoint(); 0345 const QPointF releasePoint = d.getReleasePoint(); 0346 if (releasePoint.x() < pressPoint.x() && releasePoint.y() < pressPoint.y()) { 0347 return releasePoint; 0348 } 0349 if (releasePoint.x() < pressPoint.x() && releasePoint.y() > pressPoint.y()) { 0350 return QPointF(releasePoint.x(), pressPoint.y()); 0351 } 0352 if (releasePoint.x() > pressPoint.x() && releasePoint.y() < pressPoint.y()) { 0353 return QPointF(pressPoint.x(), releasePoint.y()); 0354 } 0355 return QPointF(pressPoint); 0356 } 0357 0358 QRectF KReportDesignerItemRectBase::properRect(const KReportDesigner &d, qreal minWidth, qreal minHeight) const 0359 { 0360 QPointF tempPressPoint = properPressPoint(d); 0361 qreal currentPressX = tempPressPoint.x(); 0362 qreal currentPressY = tempPressPoint.y(); 0363 const qreal width = qMax(d.countSelectionWidth(), minWidth); 0364 const qreal height = qMax(d.countSelectionHeight(), minHeight); 0365 0366 qreal tempReleasePointX = tempPressPoint.x() + width; 0367 qreal tempReleasePointY = tempPressPoint.y() + height; 0368 0369 if (tempReleasePointX > scene()->width()) { 0370 int offsetWidth = tempReleasePointX - scene()->width(); 0371 currentPressX = tempPressPoint.x() - offsetWidth; 0372 } 0373 if (tempReleasePointY > scene()->height()) { 0374 int offsetHeight = tempReleasePointY - scene()->height(); 0375 currentPressY = tempPressPoint.y() - offsetHeight; 0376 } 0377 return (QRectF(QPointF(currentPressX, currentPressY), QSizeF(width, height))); 0378 } 0379 0380 void KReportDesignerItemRectBase::enterInlineEditingMode() 0381 { 0382 } 0383 0384 void KReportDesignerItemRectBase::exitInlineEditingMode() 0385 { 0386 } 0387 0388 void KReportDesignerItemBase::updateRenderText(const QString &itemDataSource, const QString &itemStaticValue, const QString &itemType) 0389 { 0390 if (itemDataSource.isEmpty()) { 0391 if (itemType.isEmpty()) { 0392 setRenderText(itemStaticValue); 0393 } else { 0394 setRenderText(dataSourceAndObjectTypeName(itemStaticValue, itemType)); 0395 } 0396 } else { 0397 if (itemType.isEmpty()) { 0398 setRenderText(itemDataSource); 0399 } else { 0400 setRenderText(dataSourceAndObjectTypeName(itemDataSource, itemType)); 0401 } 0402 } 0403 } 0404 0405 int KReportDesignerItemRectBase::dpiX() const 0406 { 0407 return d->dpiX; 0408 } 0409 0410 int KReportDesignerItemRectBase::dpiY() const 0411 { 0412 return d->dpiY; 0413 }