File indexing completed on 2024-05-12 15:26:42
0001 /*************************************************************************** 0002 File : DatapickerPoint.cpp 0003 Project : LabPlot 0004 Description : Graphic Item for coordinate points of Datapicker 0005 -------------------------------------------------------------------- 0006 Copyright : (C) 2015 by Ankit Wagadre (wagadre.ankit@gmail.com) 0007 Copyright : (C) 2015-2019 Alexander Semke (alexander.semke@web.de) 0008 ***************************************************************************/ 0009 /*************************************************************************** 0010 * * 0011 * This program is free software; you can redistribute it and/or modify * 0012 * it under the terms of the GNU General Public License as published by * 0013 * the Free Software Foundation; either version 2 of the License, or * 0014 * (at your option) any later version. * 0015 * * 0016 * This program is distributed in the hope that it will be useful, * 0017 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0019 * GNU General Public License for more details. * 0020 * * 0021 * You should have received a copy of the GNU General Public License * 0022 * along with this program; if not, write to the Free Software * 0023 * Foundation, Inc., 51 Franklin Street, Fifth Floor, * 0024 * Boston, MA 02110-1301 USA * 0025 * * 0026 ***************************************************************************/ 0027 0028 #include "DatapickerPoint.h" 0029 #include "backend/worksheet/Worksheet.h" 0030 #include "DatapickerPointPrivate.h" 0031 #include "backend/lib/commandtemplates.h" 0032 #include "backend/lib/XmlStreamReader.h" 0033 #include "backend/datapicker/DatapickerCurve.h" 0034 0035 #include <QPainter> 0036 #include <QGraphicsScene> 0037 #include <QMenu> 0038 #include <QGraphicsSceneMouseEvent> 0039 0040 #include <KConfig> 0041 #include <KConfigGroup> 0042 #include <KLocalizedString> 0043 0044 /** 0045 * \class ErrorBarItem 0046 * \brief A customizable error-bar for DatapickerPoint. 0047 */ 0048 0049 ErrorBarItem::ErrorBarItem(DatapickerPoint* parent, ErrorBarType type) : 0050 QGraphicsRectItem(parent->graphicsItem()), 0051 barLineItem(new QGraphicsLineItem(parent->graphicsItem())), 0052 m_type(type), 0053 m_parentItem(parent) { 0054 setFlag(QGraphicsItem::ItemIsMovable); 0055 setFlag(QGraphicsItem::ItemIsSelectable); 0056 setFlag(QGraphicsItem::ItemSendsGeometryChanges); 0057 initRect(); 0058 setAcceptHoverEvents(true); 0059 } 0060 0061 void ErrorBarItem::initRect() { 0062 QRectF xBarRect(-0.15, -0.5, 0.3, 1); 0063 QRectF yBarRect(-0.5, -0.15, 1, 0.3); 0064 0065 if (m_type == ErrorBarType::PlusDeltaX || m_type == ErrorBarType::MinusDeltaX) 0066 m_rect = xBarRect; 0067 else 0068 m_rect = yBarRect; 0069 } 0070 0071 void ErrorBarItem::setPosition(QPointF position) { 0072 setPos(position); 0073 barLineItem->setLine(0, 0, position.x(), position.y()); 0074 } 0075 0076 void ErrorBarItem::setRectSize(qreal size) { 0077 QMatrix matrix; 0078 matrix.scale(size, size); 0079 setRect(matrix.mapRect(m_rect)); 0080 } 0081 0082 void ErrorBarItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) { 0083 if (m_type == ErrorBarType::PlusDeltaX) 0084 m_parentItem->setPlusDeltaXPos(pos()); 0085 else if (m_type == ErrorBarType::MinusDeltaX) 0086 m_parentItem->setMinusDeltaXPos(pos()); 0087 else if (m_type == ErrorBarType::PlusDeltaY) 0088 m_parentItem->setPlusDeltaYPos(pos()); 0089 else if (m_type == ErrorBarType::MinusDeltaY) 0090 m_parentItem->setMinusDeltaYPos(pos()); 0091 0092 QGraphicsItem::mouseReleaseEvent(event); 0093 } 0094 0095 void ErrorBarItem::hoverEnterEvent(QGraphicsSceneHoverEvent*) { 0096 if (m_type == ErrorBarType::PlusDeltaX ||m_type == ErrorBarType::MinusDeltaX) 0097 setCursor(Qt::SizeHorCursor); 0098 else 0099 setCursor(Qt::SizeVerCursor); 0100 } 0101 0102 QVariant ErrorBarItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { 0103 if (change == QGraphicsItem::ItemPositionChange) { 0104 QPointF newPos = value.toPointF(); 0105 if (m_type == ErrorBarType::PlusDeltaX || m_type == ErrorBarType::MinusDeltaX) { 0106 newPos.setY(0); 0107 barLineItem->setLine(0, 0, newPos.x(), 0); 0108 } else { 0109 newPos.setX(0); 0110 barLineItem->setLine(0, 0, 0, newPos.y()); 0111 } 0112 return QGraphicsRectItem::itemChange(change, newPos); 0113 } 0114 0115 return QGraphicsRectItem::itemChange(change, value); 0116 } 0117 0118 /** 0119 * \class Datapicker-Point 0120 * \brief A customizable symbol supports error-bars. 0121 * 0122 * The datapicker-Point is aligned relative to the specified position. 0123 * The position can be either specified by mouse events or by providing the 0124 * x- and y- coordinates in parent's coordinate system, or by specifying one 0125 * of the predefined position flags (\c HorizontalPosition, \c VerticalPosition). 0126 */ 0127 0128 DatapickerPoint::DatapickerPoint(const QString& name) 0129 : AbstractAspect(name, AspectType::DatapickerPoint), d_ptr(new DatapickerPointPrivate(this)) { 0130 0131 init(); 0132 } 0133 0134 DatapickerPoint::DatapickerPoint(const QString& name, DatapickerPointPrivate *dd) 0135 : AbstractAspect(name, AspectType::DatapickerPoint), d_ptr(dd) { 0136 0137 init(); 0138 } 0139 0140 //no need to delete the d-pointer here - it inherits from QGraphicsItem 0141 //and is deleted during the cleanup in QGraphicsScene 0142 DatapickerPoint::~DatapickerPoint() = default; 0143 0144 void DatapickerPoint::init() { 0145 Q_D(DatapickerPoint); 0146 0147 KConfig config; 0148 KConfigGroup group; 0149 group = config.group("DatapickerPoint"); 0150 d->position.setX( group.readEntry("PositionXValue", Worksheet::convertToSceneUnits(1, Worksheet::Unit::Centimeter)) ); 0151 d->position.setY( group.readEntry("PositionYValue", Worksheet::convertToSceneUnits(1, Worksheet::Unit::Centimeter)) ); 0152 d->plusDeltaXPos = group.readEntry("PlusDeltaXPos", QPointF(30, 0)); 0153 d->minusDeltaXPos = group.readEntry("MinusDeltaXPos", QPointF(-30, 0)); 0154 d->plusDeltaYPos = group.readEntry("PlusDeltaYPos", QPointF(0, -30)); 0155 d->minusDeltaYPos = group.readEntry("MinusDeltaYPos", QPointF(0, 30)); 0156 } 0157 0158 void DatapickerPoint::initErrorBar(DatapickerCurve::Errors errors) { 0159 m_errorBarItemList.clear(); 0160 if (errors.x != DatapickerCurve::ErrorType::NoError) { 0161 auto* plusDeltaXItem = new ErrorBarItem(this, ErrorBarItem::ErrorBarType::PlusDeltaX); 0162 plusDeltaXItem->setPosition(plusDeltaXPos()); 0163 connect(this, &DatapickerPoint::plusDeltaXPosChanged, plusDeltaXItem, &ErrorBarItem::setPosition); 0164 0165 auto* minusDeltaXItem = new ErrorBarItem(this, ErrorBarItem::ErrorBarType::MinusDeltaX); 0166 minusDeltaXItem->setPosition(minusDeltaXPos()); 0167 connect(this, &DatapickerPoint::minusDeltaXPosChanged, minusDeltaXItem, &ErrorBarItem::setPosition); 0168 0169 m_errorBarItemList<<plusDeltaXItem<<minusDeltaXItem; 0170 } 0171 0172 if (errors.y != DatapickerCurve::ErrorType::NoError) { 0173 auto* plusDeltaYItem = new ErrorBarItem(this, ErrorBarItem::ErrorBarType::PlusDeltaY); 0174 plusDeltaYItem->setPosition(plusDeltaYPos()); 0175 connect(this, &DatapickerPoint::plusDeltaYPosChanged, plusDeltaYItem, &ErrorBarItem::setPosition); 0176 0177 auto* minusDeltaYItem = new ErrorBarItem(this, ErrorBarItem::ErrorBarType::MinusDeltaY); 0178 minusDeltaYItem->setPosition(minusDeltaYPos()); 0179 connect(this, &DatapickerPoint::minusDeltaYPosChanged, minusDeltaYItem, &ErrorBarItem::setPosition); 0180 0181 m_errorBarItemList<<plusDeltaYItem<<minusDeltaYItem; 0182 } 0183 0184 retransform(); 0185 } 0186 0187 /*! 0188 Returns an icon to be used in the project explorer. 0189 */ 0190 QIcon DatapickerPoint::icon() const { 0191 return QIcon::fromTheme("draw-cross"); 0192 } 0193 0194 QMenu* DatapickerPoint::createContextMenu() { 0195 QMenu* menu = AbstractAspect::createContextMenu(); 0196 return menu; 0197 } 0198 0199 QGraphicsItem* DatapickerPoint::graphicsItem() const { 0200 return d_ptr; 0201 } 0202 0203 void DatapickerPoint::setParentGraphicsItem(QGraphicsItem* item) { 0204 Q_D(DatapickerPoint); 0205 d->setParentItem(item); 0206 } 0207 0208 void DatapickerPoint::retransform() { 0209 Q_D(DatapickerPoint); 0210 d->retransform(); 0211 } 0212 0213 /* ============================ getter methods ================= */ 0214 //point 0215 CLASS_SHARED_D_READER_IMPL(DatapickerPoint, QPointF, position, position) 0216 //error-bar 0217 CLASS_SHARED_D_READER_IMPL(DatapickerPoint, QPointF, plusDeltaXPos, plusDeltaXPos) 0218 CLASS_SHARED_D_READER_IMPL(DatapickerPoint, QPointF, minusDeltaXPos, minusDeltaXPos) 0219 CLASS_SHARED_D_READER_IMPL(DatapickerPoint, QPointF, plusDeltaYPos, plusDeltaYPos) 0220 CLASS_SHARED_D_READER_IMPL(DatapickerPoint, QPointF, minusDeltaYPos, minusDeltaYPos) 0221 0222 /* ============================ setter methods and undo commands ================= */ 0223 STD_SETTER_CMD_IMPL_F_S(DatapickerPoint, SetPosition, QPointF, position, retransform) 0224 void DatapickerPoint::setPosition(QPointF pos) { 0225 Q_D(DatapickerPoint); 0226 if (pos != d->position) 0227 exec(new DatapickerPointSetPositionCmd(d, pos, ki18n("%1: set position"))); 0228 } 0229 0230 STD_SETTER_CMD_IMPL_F_S(DatapickerPoint, SetPlusDeltaXPos, QPointF, plusDeltaXPos, updatePoint) 0231 void DatapickerPoint::setPlusDeltaXPos(QPointF pos) { 0232 Q_D(DatapickerPoint); 0233 if (pos != d->plusDeltaXPos) { 0234 auto* curve = dynamic_cast<DatapickerCurve*>(parentAspect()); 0235 if (!curve) 0236 return; 0237 0238 beginMacro(i18n("%1: set +delta_X position", name())); 0239 if (curve->curveErrorTypes().x == DatapickerCurve::ErrorType::SymmetricError) { 0240 exec(new DatapickerPointSetPlusDeltaXPosCmd(d, pos, ki18n("%1: set +delta X position"))); 0241 setMinusDeltaXPos(QPointF(-qAbs(pos.x()), pos.y())); 0242 } else 0243 exec(new DatapickerPointSetPlusDeltaXPosCmd(d, pos, ki18n("%1: set +delta X position"))); 0244 endMacro(); 0245 } 0246 } 0247 0248 STD_SETTER_CMD_IMPL_F_S(DatapickerPoint, SetMinusDeltaXPos, QPointF, minusDeltaXPos, updatePoint) 0249 void DatapickerPoint::setMinusDeltaXPos(QPointF pos) { 0250 Q_D(DatapickerPoint); 0251 if (pos != d->minusDeltaXPos) { 0252 auto* curve = dynamic_cast<DatapickerCurve*>(parentAspect()); 0253 if (!curve) 0254 return; 0255 0256 beginMacro(i18n("%1: set -delta_X position", name())); 0257 if (curve->curveErrorTypes().x == DatapickerCurve::ErrorType::SymmetricError) { 0258 exec(new DatapickerPointSetMinusDeltaXPosCmd(d, pos, ki18n("%1: set -delta_X position"))); 0259 setPlusDeltaXPos(QPointF(qAbs(pos.x()), pos.y())); 0260 } else 0261 exec(new DatapickerPointSetMinusDeltaXPosCmd(d, pos, ki18n("%1: set -delta_X position"))); 0262 endMacro(); 0263 } 0264 } 0265 0266 STD_SETTER_CMD_IMPL_F_S(DatapickerPoint, SetPlusDeltaYPos, QPointF, plusDeltaYPos, updatePoint) 0267 void DatapickerPoint::setPlusDeltaYPos(QPointF pos) { 0268 Q_D(DatapickerPoint); 0269 if (pos != d->plusDeltaYPos) { 0270 auto* curve = dynamic_cast<DatapickerCurve*>(parentAspect()); 0271 if (!curve) 0272 return; 0273 0274 beginMacro(i18n("%1: set +delta_Y position", name())); 0275 if (curve->curveErrorTypes().y == DatapickerCurve::ErrorType::SymmetricError) { 0276 exec(new DatapickerPointSetPlusDeltaYPosCmd(d, pos, ki18n("%1: set +delta_Y position"))); 0277 setMinusDeltaYPos(QPointF(pos.x(), qAbs(pos.y()))); 0278 } else 0279 exec(new DatapickerPointSetPlusDeltaYPosCmd(d, pos, ki18n("%1: set +delta_Y position"))); 0280 endMacro(); 0281 } 0282 } 0283 0284 STD_SETTER_CMD_IMPL_F_S(DatapickerPoint, SetMinusDeltaYPos, QPointF, minusDeltaYPos, updatePoint) 0285 void DatapickerPoint::setMinusDeltaYPos(QPointF pos) { 0286 Q_D(DatapickerPoint); 0287 if (pos != d->minusDeltaYPos) { 0288 auto* curve = dynamic_cast<DatapickerCurve*>(parentAspect()); 0289 if (!curve) 0290 return; 0291 0292 beginMacro(i18n("%1: set -delta_Y position", name())); 0293 if (curve->curveErrorTypes().y == DatapickerCurve::ErrorType::SymmetricError) { 0294 exec(new DatapickerPointSetMinusDeltaYPosCmd(d, pos, ki18n("%1: set -delta_Y position"))); 0295 setPlusDeltaYPos(QPointF(pos.x(), -qAbs(pos.y()))); 0296 } else 0297 exec(new DatapickerPointSetMinusDeltaYPosCmd(d, pos, ki18n("%1: set -delta_Y position"))); 0298 endMacro(); 0299 } 0300 } 0301 0302 void DatapickerPoint::setPrinting(bool on) { 0303 Q_D(DatapickerPoint); 0304 d->m_printing = on; 0305 } 0306 0307 //############################################################################## 0308 //####################### Private implementation ############################### 0309 //############################################################################## 0310 DatapickerPointPrivate::DatapickerPointPrivate(DatapickerPoint* owner) : q(owner) { 0311 setFlag(QGraphicsItem::ItemIsMovable); 0312 setFlag(QGraphicsItem::ItemSendsGeometryChanges); 0313 setFlag(QGraphicsItem::ItemIsSelectable); 0314 setAcceptHoverEvents(true); 0315 } 0316 0317 QString DatapickerPointPrivate::name() const { 0318 return q->name(); 0319 } 0320 0321 /*! 0322 calculates the position and the bounding box of the item/point. Called on geometry or properties changes. 0323 */ 0324 void DatapickerPointPrivate::retransform() { 0325 updatePropeties(); 0326 setPos(position); 0327 QPainterPath path = Symbol::pathFromStyle(pointStyle); 0328 boundingRectangle = path.boundingRect(); 0329 recalcShapeAndBoundingRect(); 0330 retransformErrorBar(); 0331 updatePoint(); 0332 } 0333 0334 /*! 0335 update color and size of all error-bar. 0336 */ 0337 void DatapickerPointPrivate::retransformErrorBar() { 0338 for (auto* item : q->m_errorBarItemList) { 0339 if (item) { 0340 item->setBrush(errorBarBrush); 0341 item->setPen(errorBarPen); 0342 item->setRectSize(errorBarSize); 0343 } 0344 } 0345 } 0346 0347 /*! 0348 update datasheet on any change in position of Datapicker-Point or it's error-bar. 0349 */ 0350 void DatapickerPointPrivate::updatePoint() { 0351 auto* curve = dynamic_cast<DatapickerCurve*>(q->parentAspect()); 0352 if (curve) 0353 curve->updatePoint(q); 0354 } 0355 0356 void DatapickerPointPrivate::updatePropeties() { 0357 auto* curve = dynamic_cast<DatapickerCurve*>(q->parentAspect()); 0358 auto* image = dynamic_cast<DatapickerImage*>(q->parentAspect()); 0359 if (image) { 0360 rotationAngle = image->pointRotationAngle(); 0361 pointStyle = image->pointStyle(); 0362 brush = image->pointBrush(); 0363 pen = image->pointPen(); 0364 opacity = image->pointOpacity(); 0365 size = image->pointSize(); 0366 setVisible(image->pointVisibility()); 0367 } else if (curve) { 0368 rotationAngle = curve->pointRotationAngle(); 0369 pointStyle = curve->pointStyle(); 0370 brush = curve->pointBrush(); 0371 pen = curve->pointPen(); 0372 opacity = curve->pointOpacity(); 0373 size = curve->pointSize(); 0374 errorBarBrush = curve->pointErrorBarBrush(); 0375 errorBarPen = curve->pointErrorBarPen(); 0376 errorBarSize = curve->pointErrorBarSize(); 0377 setVisible(curve->pointVisibility()); 0378 } 0379 } 0380 0381 /*! 0382 Returns the outer bounds of the item as a rectangle. 0383 */ 0384 QRectF DatapickerPointPrivate::boundingRect() const { 0385 return transformedBoundingRectangle; 0386 } 0387 0388 /*! 0389 Returns the shape of this item as a QPainterPath in local coordinates. 0390 */ 0391 QPainterPath DatapickerPointPrivate::shape() const { 0392 return itemShape; 0393 } 0394 0395 /*! 0396 recalculates the outer bounds and the shape of the item. 0397 */ 0398 void DatapickerPointPrivate::recalcShapeAndBoundingRect() { 0399 prepareGeometryChange(); 0400 0401 QMatrix matrix; 0402 matrix.scale(size, size); 0403 matrix.rotate(-rotationAngle); 0404 transformedBoundingRectangle = matrix.mapRect(boundingRectangle); 0405 itemShape = QPainterPath(); 0406 itemShape.addRect(transformedBoundingRectangle); 0407 itemShape = WorksheetElement::shapeFromPath(itemShape, pen); 0408 } 0409 0410 void DatapickerPointPrivate::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) { 0411 q->setPosition(pos()); 0412 QGraphicsItem::mouseReleaseEvent(event); 0413 } 0414 0415 void DatapickerPointPrivate::hoverEnterEvent(QGraphicsSceneHoverEvent*) { 0416 setCursor(Qt::ArrowCursor); 0417 } 0418 0419 void DatapickerPointPrivate::hoverLeaveEvent(QGraphicsSceneHoverEvent*) { 0420 setCursor(Qt::CrossCursor); 0421 } 0422 0423 void DatapickerPointPrivate::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { 0424 Q_UNUSED(option) 0425 Q_UNUSED(widget) 0426 0427 QPainterPath path = Symbol::pathFromStyle(pointStyle); 0428 QTransform trafo; 0429 trafo.scale(size, size); 0430 path = trafo.map(path); 0431 trafo.reset(); 0432 if (rotationAngle != 0) { 0433 trafo.rotate(-rotationAngle); 0434 path = trafo.map(path); 0435 } 0436 painter->save(); 0437 painter->setPen(pen); 0438 painter->setBrush(brush); 0439 painter->setOpacity(opacity); 0440 painter->drawPath(path); 0441 painter->restore(); 0442 0443 if (isSelected() && !m_printing) { 0444 //TODO: move the initialization of QPen to a parent class later so we don't 0445 //need to create it in every paint() call. 0446 painter->setPen(QPen(QApplication::palette().color(QPalette::Highlight), 1, Qt::SolidLine)); 0447 painter->drawPath(itemShape); 0448 } 0449 } 0450 0451 void DatapickerPointPrivate::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) { 0452 q->createContextMenu()->exec(event->screenPos()); 0453 } 0454 0455 //############################################################################## 0456 //################## Serialization/Deserialization ########################### 0457 //############################################################################## 0458 //! Save as XML 0459 void DatapickerPoint::save(QXmlStreamWriter* writer) const { 0460 Q_D(const DatapickerPoint); 0461 0462 writer->writeStartElement( "datapickerPoint" ); 0463 writeBasicAttributes(writer); 0464 0465 //geometry 0466 writer->writeStartElement( "geometry" ); 0467 writer->writeAttribute( "x", QString::number(d->position.x()) ); 0468 writer->writeAttribute( "y", QString::number(d->position.y()) ); 0469 writer->writeEndElement(); 0470 0471 auto* curve = dynamic_cast<DatapickerCurve*>(parentAspect()); 0472 if (curve && (curve->curveErrorTypes().x != DatapickerCurve::ErrorType::NoError 0473 || curve->curveErrorTypes().y != DatapickerCurve::ErrorType::NoError)) { 0474 0475 writer->writeStartElement( "errorBar" ); 0476 writer->writeAttribute( "plusDeltaXPos_x", QString::number(d->plusDeltaXPos.x()) ); 0477 writer->writeAttribute( "plusDeltaXPos_y", QString::number(d->plusDeltaXPos.y()) ); 0478 writer->writeAttribute( "minusDeltaXPos_x", QString::number(d->minusDeltaXPos.x()) ); 0479 writer->writeAttribute( "minusDeltaXPos_y", QString::number(d->minusDeltaXPos.y()) ); 0480 writer->writeAttribute( "plusDeltaYPos_x", QString::number(d->plusDeltaYPos.x()) ); 0481 writer->writeAttribute( "plusDeltaYPos_y", QString::number(d->plusDeltaYPos.y()) ); 0482 writer->writeAttribute( "minusDeltaYPos_x", QString::number(d->minusDeltaYPos.x()) ); 0483 writer->writeAttribute( "minusDeltaYPos_y", QString::number(d->minusDeltaYPos.y()) ); 0484 writer->writeEndElement(); 0485 } 0486 0487 writer->writeEndElement(); // close "DatapickerPoint" section 0488 } 0489 0490 //! Load from XML 0491 bool DatapickerPoint::load(XmlStreamReader* reader, bool preview) { 0492 Q_D(DatapickerPoint); 0493 0494 if (!readBasicAttributes(reader)) 0495 return false; 0496 0497 KLocalizedString attributeWarning = ki18n("Attribute '%1' missing or empty, default value is used"); 0498 QXmlStreamAttributes attribs; 0499 QString str; 0500 0501 while (!reader->atEnd()) { 0502 reader->readNext(); 0503 if (reader->isEndElement() && reader->name() == "datapickerPoint") 0504 break; 0505 0506 if (!reader->isStartElement()) 0507 continue; 0508 0509 if (!preview && reader->name() == "geometry") { 0510 attribs = reader->attributes(); 0511 0512 str = attribs.value("x").toString(); 0513 if (str.isEmpty()) 0514 reader->raiseWarning(attributeWarning.subs("x").toString()); 0515 else 0516 d->position.setX(str.toDouble()); 0517 0518 str = attribs.value("y").toString(); 0519 if (str.isEmpty()) 0520 reader->raiseWarning(attributeWarning.subs("y").toString()); 0521 else 0522 d->position.setY(str.toDouble()); 0523 } else if (!preview && reader->name() == "errorBar") { 0524 attribs = reader->attributes(); 0525 0526 str = attribs.value("plusDeltaXPos_x").toString(); 0527 if (str.isEmpty()) 0528 reader->raiseWarning(attributeWarning.subs("plusDeltaXPos_x").toString()); 0529 else 0530 d->plusDeltaXPos.setX(str.toDouble()); 0531 0532 str = attribs.value("plusDeltaXPos_y").toString(); 0533 if (str.isEmpty()) 0534 reader->raiseWarning(attributeWarning.subs("plusDeltaXPos_y").toString()); 0535 else 0536 d->plusDeltaXPos.setY(str.toDouble()); 0537 0538 str = attribs.value("minusDeltaXPos_x").toString(); 0539 if (str.isEmpty()) 0540 reader->raiseWarning(attributeWarning.subs("minusDeltaXPos_x").toString()); 0541 else 0542 d->minusDeltaXPos.setX(str.toDouble()); 0543 0544 str = attribs.value("minusDeltaXPos_y").toString(); 0545 if (str.isEmpty()) 0546 reader->raiseWarning(attributeWarning.subs("minusDeltaXPos_y").toString()); 0547 else 0548 d->minusDeltaXPos.setY(str.toDouble()); 0549 0550 str = attribs.value("plusDeltaYPos_x").toString(); 0551 if (str.isEmpty()) 0552 reader->raiseWarning(attributeWarning.subs("plusDeltaYPos_x").toString()); 0553 else 0554 d->plusDeltaYPos.setX(str.toDouble()); 0555 0556 str = attribs.value("plusDeltaYPos_y").toString(); 0557 if (str.isEmpty()) 0558 reader->raiseWarning(attributeWarning.subs("plusDeltaYPos_y").toString()); 0559 else 0560 d->plusDeltaYPos.setY(str.toDouble()); 0561 0562 str = attribs.value("minusDeltaYPos_x").toString(); 0563 if (str.isEmpty()) 0564 reader->raiseWarning(attributeWarning.subs("minusDeltaYPos_x").toString()); 0565 else 0566 d->minusDeltaYPos.setX(str.toDouble()); 0567 0568 str = attribs.value("minusDeltaYPos_y").toString(); 0569 if (str.isEmpty()) 0570 reader->raiseWarning(attributeWarning.subs("minusDeltaYPos_y").toString()); 0571 else 0572 d->minusDeltaYPos.setY(str.toDouble()); 0573 } else { // unknown element 0574 reader->raiseWarning(i18n("unknown element '%1'", reader->name().toString())); 0575 if (!reader->skipToEndElement()) return false; 0576 } 0577 } 0578 0579 retransform(); 0580 return true; 0581 }