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 }