265 lines
6.8 KiB
C++
Raw Normal View History

/*
Copyright 2006-2014 The QElectroTech Team
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
QElectroTech is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "partpolygon.h"
/**
* @brief PartPolygon::PartPolygon
* Constructor
* @param editor : editor of this item
* @param parent : parent item
*/
PartPolygon::PartPolygon(QETElementEditor *editor, QGraphicsItem *parent) :
CustomElementGraphicPart(editor, parent),
m_closed(false)
{}
/**
* @brief PartPolygon::~PartPolygon
*/
PartPolygon::~PartPolygon() {}
/**
* @brief PartPolygon::paint
* Draw this polygon
* @param painter
* @param options
* @param widget
*/
void PartPolygon::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, QWidget *widget)
{
Q_UNUSED(widget);
applyStylesToQPainter(*painter);
QPen t = painter -> pen();
t.setCosmetic(options && options -> levelOfDetail < 1.0);
if (isSelected()) t.setColor(Qt::red);
painter -> setPen(t);
m_closed ? painter -> drawPolygon (m_polygon) :
painter -> drawPolyline(m_polygon);
if (m_hovered)
drawShadowShape(painter);
}
/**
* @brief PartPolygon::fromXml
* Import the properties of this polygon from a xml element
* @param qde : Xml document to use
*/
void PartPolygon::fromXml(const QDomElement &qde)
{
stylesFromXml(qde);
int i = 1;
while(true)
{
if (QET::attributeIsAReal(qde, QString("x%1").arg(i)) &&\
QET::attributeIsAReal(qde, QString("y%1").arg(i)))
++ i;
else break;
}
QPolygonF temp_polygon;
for (int j = 1 ; j < i ; ++ j)
{
temp_polygon << QPointF(qde.attribute(QString("x%1").arg(j)).toDouble(),
qde.attribute(QString("y%1").arg(j)).toDouble());
}
m_polygon = temp_polygon;
m_closed = qde.attribute("closed") != "false";
}
/**
* @brief PartPolygon::toXml
* Export this polygin in xml
* @param xml_document : Xml document to use for create the xml element
* @return an xml element that describe this polygon
*/
const QDomElement PartPolygon::toXml(QDomDocument &xml_document) const
{
QDomElement xml_element = xml_document.createElement("polygon");
int i = 1;
foreach(QPointF point, m_polygon) {
point = mapToScene(point);
xml_element.setAttribute(QString("x%1").arg(i), QString("%1").arg(point.x()));
xml_element.setAttribute(QString("y%1").arg(i), QString("%1").arg(point.y()));
++ i;
}
if (!m_closed) xml_element.setAttribute("closed", "false");
stylesToXml(xml_element);
return(xml_element);
}
/**
* @brief PartPolygon::isUseless
* @return true if this part is irrelevant and does not deserve to be Retained / registered.
* A polygon is relevant when he have 2 differents points
*/
bool PartPolygon::isUseless() const
{
if (m_polygon.count() < 2) return(true);
for (int i = 1 ; i < m_polygon.count() ; ++ i)
if (m_polygon[i] != m_polygon[i-1]) return(false);
return(true);
}
/**
* @brief PartPolygon::sceneGeometricRect
* @return the minimum, margin-less rectangle this part can fit into, in scene
* coordinates. It is different from boundingRect() because it is not supposed
* to imply any margin, and it is different from shape because it is a regular
* rectangle, not a complex shape.
*/
QRectF PartPolygon::sceneGeometricRect() const {
return(mapToScene(m_polygon.boundingRect()).boundingRect());
}
/**
* @brief PartPolygon::startUserTransformation
* Start the user-induced transformation, provided this primitive is contained
* within the initial_selection_rect bounding rectangle.
* @param initial_selection_rect
*/
void PartPolygon::startUserTransformation(const QRectF &initial_selection_rect)
{
Q_UNUSED(initial_selection_rect)
saved_points_ = mapToScene(m_polygon).toList();
}
/**
* @brief PartPolygon::handleUserTransformation
* Handle the user-induced transformation from initial_selection_rect to new_selection_rect
* @param initial_selection_rect
* @param new_selection_rect
*/
void PartPolygon::handleUserTransformation(const QRectF &initial_selection_rect, const QRectF &new_selection_rect)
{
QList<QPointF> mapped_points = mapPoints(initial_selection_rect, new_selection_rect, saved_points_);
m_polygon = (mapFromScene(QPolygonF(mapped_points.toVector())));
}
/**
* @brief PartPolygon::preferredScalingMethod
* This method is called by the decorator when it needs to determine the best
* way to interactively scale a primitive. It is typically called when only a
* single primitive is being scaled.
* @return : This reimplementation systematically returns QET::RoundScaleRatios.
*/
QET::ScalingMethod PartPolygon::preferredScalingMethod() const {
return(QET::RoundScaleRatios);
}
/**
* @brief PartPolygon::polygon
* @return the item's polygon, or an empty polygon if no polygon has been set.
*/
QPolygonF PartPolygon::polygon() const {
return m_polygon;
}
/**
* @brief PartPolygon::setPolygon
* Sets the item's polygon to be the given polygon.
* @param polygon
*/
void PartPolygon::setPolygon(const QPolygonF &polygon)
{
if (m_polygon == polygon) return;
prepareGeometryChange();
m_polygon = polygon;
}
/**
* @brief PartPolygon::addPoint
* Add new point to polygon
* @param point
*/
void PartPolygon::addPoint(const QPointF &point)
{
prepareGeometryChange();
m_polygon << point;
}
/**
* @brief PartPolygon::setLastPoint
* Set the last point of polygon to @point
* @param point
*/
void PartPolygon::setLastPoint(const QPointF &point)
{
if (m_polygon.size())
m_polygon.pop_back();
prepareGeometryChange();
m_polygon << point;
}
/**
* @brief PartPolygon::removeLastPoint
* Remove the last point of polygon
*/
void PartPolygon::removeLastPoint()
{
if (m_polygon.size())
{
prepareGeometryChange();
m_polygon.pop_back();
}
}
/**
* @brief PartPolygon::shape
* @return the shape of this item
*/
QPainterPath PartPolygon::shape() const
{
QPainterPath shape;
shape.addPolygon(m_polygon);
if (m_closed)
shape.lineTo(m_polygon.first());
QPainterPathStroker pps;
pps.setWidth(penWeight());
return (pps.createStroke(shape));
}
/**
* @brief PartPolygon::boundingRect
* @return the bounding rect of this item
*/
QRectF PartPolygon::boundingRect() const
{
QRectF r = m_polygon.boundingRect();
qreal adjust = (SHADOWS_HEIGHT + penWeight()) / 2;
//We add 0.5 because CustomElementGraphicPart::drawShadowShape
//draw a shape bigger of 0.5 when pen weight is to 0.
if (penWeight() == 0) adjust += 0.5;
r.adjust(-adjust, -adjust, adjust, adjust);
return(r);
}