File indexing completed on 2024-05-12 03:47:30
0001 /* 0002 File : Segment.cpp 0003 Project : LabPlot 0004 Description : Graphics-item for curve of Datapicker 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2015 Ankit Wagadre <wagadre.ankit@gmail.com> 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include "Segment.h" 0011 #include "SegmentPrivate.h" 0012 #include "backend/datapicker/Datapicker.h" 0013 #include "backend/datapicker/DatapickerImage.h" 0014 #include "backend/datapicker/DatapickerPoint.h" 0015 #include "backend/worksheet/Worksheet.h" 0016 0017 #include <QGraphicsScene> 0018 #include <QPainter> 0019 #include <QPalette> 0020 #include <QScreen> 0021 0022 #include <KLocalizedString> 0023 0024 /** 0025 * \class Segment 0026 * \brief graphics-item class for curve-segment 0027 */ 0028 0029 Segment::Segment(DatapickerImage* image) 0030 : m_image(image) 0031 , d_ptr(new SegmentPrivate(this)) { 0032 m_image->scene()->addItem(this->graphicsItem()); 0033 } 0034 0035 QGraphicsItem* Segment::graphicsItem() const { 0036 return d_ptr; 0037 } 0038 0039 void Segment::setParentGraphicsItem(QGraphicsItem* item) { 0040 Q_D(Segment); 0041 d->setParentItem(item); 0042 } 0043 0044 void Segment::retransform() { 0045 Q_D(Segment); 0046 d->retransform(); 0047 } 0048 0049 bool Segment::isVisible() const { 0050 Q_D(const Segment); 0051 return d->isVisible(); 0052 } 0053 0054 void Segment::setVisible(bool on) { 0055 Q_D(Segment); 0056 d->setVisible(on); 0057 } 0058 0059 // ############################################################################## 0060 // ####################### Private implementation ############################### 0061 // ############################################################################## 0062 SegmentPrivate::SegmentPrivate(Segment* owner) 0063 : scaleFactor(Worksheet::convertToSceneUnits(1, Worksheet::Unit::Inch) / QApplication::primaryScreen()->physicalDotsPerInchX()) 0064 , q(owner) { 0065 setFlag(QGraphicsItem::ItemIsSelectable); 0066 setFlag(QGraphicsItem::ItemSendsGeometryChanges); 0067 setAcceptHoverEvents(true); 0068 setVisible(false); 0069 0070 pen = QPen(Qt::green, 3, Qt::SolidLine); 0071 } 0072 0073 /*! 0074 calculates the position and the bounding box of the item. Called on geometry or properties changes. 0075 */ 0076 void SegmentPrivate::retransform() { 0077 QTransform matrix; 0078 matrix.scale(scaleFactor, scaleFactor); 0079 for (auto* line : q->path) { 0080 const QLine& scaledLine = matrix.map(*line); 0081 linePath.moveTo(scaledLine.p1()); 0082 linePath.lineTo(scaledLine.p2()); 0083 } 0084 recalcShapeAndBoundingRect(); 0085 } 0086 0087 /*! 0088 Returns the outer bounds of the item as a rectangle. 0089 */ 0090 QRectF SegmentPrivate::boundingRect() const { 0091 return boundingRectangle; 0092 } 0093 0094 /*! 0095 Returns the shape of this item as a QPainterPath in local coordinates. 0096 */ 0097 QPainterPath SegmentPrivate::shape() const { 0098 return itemShape; 0099 } 0100 0101 /*! 0102 recalculates the outer bounds and the shape of the item. 0103 */ 0104 void SegmentPrivate::recalcShapeAndBoundingRect() { 0105 prepareGeometryChange(); 0106 boundingRectangle = linePath.boundingRect(); 0107 itemShape = QPainterPath(); 0108 itemShape.addRect(boundingRectangle); 0109 } 0110 0111 void SegmentPrivate::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget*) { 0112 painter->setPen(pen); 0113 painter->drawPath(linePath); 0114 0115 if (m_hovered && !isSelected()) { 0116 painter->setPen(QPen(QApplication::palette().color(QPalette::Highlight), 2, Qt::SolidLine)); 0117 painter->drawPath(linePath); 0118 } 0119 0120 // if (isSelected()) { 0121 // painter->setPen(QPen(QApplication::palette().color(QPalette::Highlight), 2, Qt::SolidLine)); 0122 // painter->setOpacity(selectedOpacity); 0123 // painter->drawPath(itemShape); 0124 // } 0125 } 0126 0127 void SegmentPrivate::hoverEnterEvent(QGraphicsSceneHoverEvent*) { 0128 if (!isSelected()) { 0129 m_hovered = true; 0130 update(); 0131 } 0132 } 0133 0134 void SegmentPrivate::hoverLeaveEvent(QGraphicsSceneHoverEvent*) { 0135 if (m_hovered) { 0136 m_hovered = false; 0137 update(); 0138 } 0139 } 0140 0141 QVariant SegmentPrivate::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant& value) { 0142 if (change == QGraphicsItem::ItemSelectedChange && value == true) { 0143 auto* datapicker = static_cast<Datapicker*>(q->m_image->parentAspect()); 0144 if (datapicker->activeCurve()) { 0145 int count = 0; 0146 QList<QPointF> posList; 0147 posList.clear(); 0148 for (QLine* line : q->path) { 0149 const int l = (line->y1() > line->y2()) ? line->y2() : line->y1(); 0150 const int h = (line->y1() > line->y2()) ? line->y1() : line->y2(); 0151 0152 for (int i = l; i <= h; ++i) { 0153 if (count % q->m_image->pointSeparation() == 0) { 0154 bool positionUsed = false; 0155 const auto points = datapicker->activeCurve()->children<DatapickerPoint>(AbstractAspect::ChildIndexFlag::IncludeHidden); 0156 for (const auto* point : points) { 0157 if (point->position() == QPoint(line->x1(), i) * scaleFactor) 0158 positionUsed = true; 0159 } 0160 0161 if (!positionUsed) 0162 posList << QPoint(line->x1(), i) * scaleFactor; 0163 } 0164 count++; 0165 } 0166 } 0167 0168 if (!posList.isEmpty()) { 0169 auto* curve = datapicker->activeCurve(); 0170 curve->beginMacro(i18n("%1: draw points over segment", datapicker->activeCurve()->name())); 0171 curve->suppressUpdatePoint(true); 0172 for (const QPointF& pos : posList) 0173 datapicker->addNewPoint(pos, curve); 0174 curve->suppressUpdatePoint(false); 0175 curve->endMacro(); 0176 } 0177 } 0178 0179 // no need to keep segment selected 0180 return false; 0181 } 0182 0183 return QGraphicsItem::itemChange(change, value); 0184 }