File indexing completed on 2024-05-12 15:26:42
0001 /*************************************************************************** 0002 File : Segment.cpp 0003 Project : LabPlot 0004 Description : Graphics-item for curve of Datapicker 0005 -------------------------------------------------------------------- 0006 Copyright : (C) 2015 by Ankit Wagadre (wagadre.ankit@gmail.com) 0007 ***************************************************************************/ 0008 /*************************************************************************** 0009 * * 0010 * This program is free software; you can redistribute it and/or modify * 0011 * it under the terms of the GNU General Public License as published by * 0012 * the Free Software Foundation; either version 2 of the License, or * 0013 * (at your option) any later version. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program; if not, write to the Free Software * 0022 * Foundation, Inc., 51 Franklin Street, Fifth Floor, * 0023 * Boston, MA 02110-1301 USA * 0024 * * 0025 ***************************************************************************/ 0026 0027 #include "Segment.h" 0028 #include "SegmentPrivate.h" 0029 #include "backend/datapicker/DatapickerImage.h" 0030 #include "backend/datapicker/DatapickerPoint.h" 0031 #include "backend/worksheet/Worksheet.h" 0032 #include "backend/datapicker/Datapicker.h" 0033 0034 #include <QPainter> 0035 #include <QGraphicsScene> 0036 #include <QDesktopWidget> 0037 0038 #include <KLocalizedString> 0039 0040 /** 0041 * \class Segment 0042 * \brief graphics-item class for curve-segment 0043 */ 0044 0045 Segment::Segment(DatapickerImage* image) : m_image(image), d_ptr(new SegmentPrivate(this)) { 0046 m_image->scene()->addItem(this->graphicsItem()); 0047 } 0048 0049 QGraphicsItem* Segment::graphicsItem() const { 0050 return d_ptr; 0051 } 0052 0053 void Segment::setParentGraphicsItem(QGraphicsItem* item) { 0054 Q_D(Segment); 0055 d->setParentItem(item); 0056 } 0057 0058 void Segment::retransform() { 0059 Q_D(Segment); 0060 d->retransform(); 0061 } 0062 0063 bool Segment::isVisible() const { 0064 Q_D(const Segment); 0065 return d->isVisible(); 0066 } 0067 0068 void Segment::setVisible(bool on) { 0069 Q_D(Segment); 0070 d->setVisible(on); 0071 } 0072 0073 //############################################################################## 0074 //####################### Private implementation ############################### 0075 //############################################################################## 0076 SegmentPrivate::SegmentPrivate(Segment *owner) : 0077 scaleFactor(Worksheet::convertToSceneUnits(1, Worksheet::Unit::Inch)/QApplication::desktop()->physicalDpiX()), 0078 q(owner) { 0079 0080 setFlag(QGraphicsItem::ItemIsSelectable); 0081 setFlag(QGraphicsItem::ItemSendsGeometryChanges); 0082 setAcceptHoverEvents(true); 0083 setVisible(false); 0084 0085 pen = QPen(Qt::green, 3, Qt::SolidLine); 0086 } 0087 0088 /*! 0089 calculates the position and the bounding box of the item. Called on geometry or properties changes. 0090 */ 0091 void SegmentPrivate::retransform() { 0092 QMatrix matrix; 0093 matrix.scale(scaleFactor, scaleFactor); 0094 for (auto* line : q->path) { 0095 const QLine& scaledLine = matrix.map(*line); 0096 linePath.moveTo(scaledLine.p1()); 0097 linePath.lineTo(scaledLine.p2()); 0098 } 0099 recalcShapeAndBoundingRect(); 0100 } 0101 0102 /*! 0103 Returns the outer bounds of the item as a rectangle. 0104 */ 0105 QRectF SegmentPrivate::boundingRect() const { 0106 return boundingRectangle; 0107 } 0108 0109 /*! 0110 Returns the shape of this item as a QPainterPath in local coordinates. 0111 */ 0112 QPainterPath SegmentPrivate::shape() const { 0113 return itemShape; 0114 } 0115 0116 /*! 0117 recalculates the outer bounds and the shape of the item. 0118 */ 0119 void SegmentPrivate::recalcShapeAndBoundingRect() { 0120 prepareGeometryChange(); 0121 boundingRectangle = linePath.boundingRect(); 0122 itemShape = QPainterPath(); 0123 itemShape.addRect(boundingRectangle); 0124 } 0125 0126 void SegmentPrivate::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { 0127 Q_UNUSED(option) 0128 Q_UNUSED(widget) 0129 0130 painter->setPen(pen); 0131 painter->drawPath(linePath); 0132 0133 if (m_hovered && !isSelected()) { 0134 painter->setPen(QPen(QApplication::palette().color(QPalette::Highlight), 2, Qt::SolidLine)); 0135 painter->drawPath(linePath); 0136 } 0137 0138 // if (isSelected()) { 0139 // painter->setPen(QPen(QApplication::palette().color(QPalette::Highlight), 2, Qt::SolidLine)); 0140 // painter->setOpacity(selectedOpacity); 0141 // painter->drawPath(itemShape); 0142 // } 0143 } 0144 0145 void SegmentPrivate::hoverEnterEvent(QGraphicsSceneHoverEvent*) { 0146 if (!isSelected()) { 0147 m_hovered = true; 0148 update(); 0149 } 0150 } 0151 0152 void SegmentPrivate::hoverLeaveEvent(QGraphicsSceneHoverEvent*) { 0153 if (m_hovered) { 0154 m_hovered = false; 0155 update(); 0156 } 0157 } 0158 0159 QVariant SegmentPrivate::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { 0160 if (change == QGraphicsItem::ItemSelectedChange && value == true) { 0161 auto* datapicker = static_cast<Datapicker*>(q->m_image->parentAspect()); 0162 if (datapicker->activeCurve()) { 0163 int count = 0; 0164 QList<QPointF> posList; 0165 posList.clear(); 0166 for (QLine* line : q->path) { 0167 const int l = (line->y1() > line->y2())?line->y2():line->y1(); 0168 const int h = (line->y1() > line->y2())?line->y1():line->y2(); 0169 0170 for (int i = l; i <= h; ++i) { 0171 if (count%q->m_image->pointSeparation() == 0) { 0172 bool positionUsed = false; 0173 const auto points = datapicker->activeCurve()->children<DatapickerPoint>(AbstractAspect::ChildIndexFlag::IncludeHidden); 0174 for (const auto* point : points) { 0175 if (point->position() == QPoint(line->x1(), i)*scaleFactor) 0176 positionUsed = true; 0177 } 0178 0179 if (!positionUsed) 0180 posList<<QPoint(line->x1(), i)*scaleFactor; 0181 } 0182 count++; 0183 } 0184 } 0185 0186 if (!posList.isEmpty()) { 0187 datapicker->activeCurve()->beginMacro(i18n("%1: draw points over segment", datapicker->activeCurve()->name())); 0188 for (const QPointF& pos : posList) 0189 datapicker->addNewPoint(pos, datapicker->activeCurve()); 0190 datapicker->activeCurve()->endMacro(); 0191 } 0192 } 0193 0194 //no need to keep segment selected 0195 return false; 0196 } 0197 0198 return QGraphicsItem::itemChange(change, value); 0199 }