32#include <QApplication>
34#include <QDragEnterEvent>
39#include "moc_qgsmodelgraphicsview.cpp"
43#define MIN_VIEW_SCALE 0.05
44#define MAX_VIEW_SCALE 1000.0
46QgsModelGraphicsView::QgsModelGraphicsView( QWidget *parent )
47 : QGraphicsView( parent )
49 setResizeAnchor( QGraphicsView::AnchorViewCenter );
50 setMouseTracking(
true );
51 viewport()->setMouseTracking(
true );
52 setAcceptDrops(
true );
58 connect( horizontalScrollBar(), &QScrollBar::valueChanged,
this, &QgsModelGraphicsView::friendlySetSceneRect );
59 connect( verticalScrollBar(), &QScrollBar::valueChanged,
this, &QgsModelGraphicsView::friendlySetSceneRect );
61 mSnapper.setSnapToGrid(
true );
64QgsModelGraphicsView::~QgsModelGraphicsView()
69void QgsModelGraphicsView::dragEnterEvent( QDragEnterEvent *event )
71 if ( event->mimeData()->hasFormat( QStringLiteral(
"application/x-vnd.qgis.qgis.algorithmid" ) )
72 || event->mimeData()->hasFormat( QStringLiteral(
"application/x-vnd.qgis.qgis.parametertypeid" ) )
73 || event->mimeData()->hasText() )
74 event->acceptProposedAction();
79void QgsModelGraphicsView::dropEvent( QDropEvent *event )
81 const QPointF dropPoint = mapToScene( event->pos() );
82 if ( event->mimeData()->hasFormat( QStringLiteral(
"application/x-vnd.qgis.qgis.algorithmid" ) ) )
84 QByteArray data =
event->mimeData()->data( QStringLiteral(
"application/x-vnd.qgis.qgis.algorithmid" ) );
85 QDataStream stream( &data, QIODevice::ReadOnly );
87 stream >> algorithmId;
89 QTimer::singleShot( 0,
this, [
this, dropPoint, algorithmId] {
90 emit algorithmDropped( algorithmId, dropPoint );
94 else if ( event->mimeData()->hasFormat( QStringLiteral(
"application/x-vnd.qgis.qgis.parametertypeid" ) ) )
96 QByteArray data =
event->mimeData()->data( QStringLiteral(
"application/x-vnd.qgis.qgis.parametertypeid" ) );
97 QDataStream stream( &data, QIODevice::ReadOnly );
99 stream >> paramTypeId;
101 QTimer::singleShot( 0,
this, [
this, dropPoint, paramTypeId] {
102 emit inputDropped( paramTypeId, dropPoint );
106 else if ( event->mimeData()->hasText() )
108 const QString itemId =
event->mimeData()->text();
109 QTimer::singleShot( 0,
this, [
this, dropPoint, itemId] {
110 emit inputDropped( itemId, dropPoint );
120void QgsModelGraphicsView::dragMoveEvent( QDragMoveEvent *event )
122 if ( event->mimeData()->hasFormat( QStringLiteral(
"application/x-vnd.qgis.qgis.algorithmid" ) )
123 || event->mimeData()->hasFormat( QStringLiteral(
"application/x-vnd.qgis.qgis.parametertypeid" ) )
124 || event->mimeData()->hasText() )
125 event->acceptProposedAction();
130void QgsModelGraphicsView::wheelEvent( QWheelEvent *event )
137 mTool->wheelEvent( event );
140 if ( !mTool || !event->isAccepted() )
147void QgsModelGraphicsView::wheelZoom( QWheelEvent *event )
151 double zoomFactor = settings.
value( QStringLiteral(
"qgis/zoom_factor" ), 2 ).toDouble();
152 bool reverseZoom = settings.
value( QStringLiteral(
"qgis/reverse_wheel_zoom" ),
false ).toBool();
153 bool zoomIn = reverseZoom ?
event->angleDelta().y() < 0 :
event->angleDelta().y() > 0;
156 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * std::fabs( event->angleDelta().y() );
158 if ( event->modifiers() & Qt::ControlModifier )
161 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0;
165 double scaleFactor = ( zoomIn ? 1 / zoomFactor : zoomFactor );
168 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
172 QPointF scenePoint = mapToScene( event->position().x(), event->position().y() );
176 QgsPointXY newCenter( scenePoint.x() + ( ( oldCenter.x() - scenePoint.x() ) * scaleFactor ), scenePoint.y() + ( ( oldCenter.y() - scenePoint.y() ) * scaleFactor ) );
177 centerOn( newCenter.x(), newCenter.y() );
182 scaleSafe( zoomFactor );
186 scaleSafe( 1 / zoomFactor );
190void QgsModelGraphicsView::scaleSafe(
double scale )
192 double currentScale = transform().m11();
193 scale *= currentScale;
195 setTransform( QTransform::fromScale( scale, scale ) );
198QPointF QgsModelGraphicsView::deltaForKeyEvent( QKeyEvent *event )
201 double increment = 1.0;
202 if ( event->modifiers() & Qt::ShiftModifier )
207 else if ( event->modifiers() & Qt::AltModifier )
210 double viewScale = transform().m11();
213 increment = 1 / viewScale;
219 switch ( event->key() )
237 return QPointF( deltaX, deltaY );
240void QgsModelGraphicsView::mousePressEvent( QMouseEvent *event )
248 mTool->modelPressEvent( me.get() );
249 event->setAccepted( me->isAccepted() );
252 if ( !mTool || !event->isAccepted() )
254 if ( event->button() == Qt::MiddleButton && mTool != mSpacePanTool && mTool != mSpaceZoomTool )
257 setTool( mMidMouseButtonPanTool );
262 QGraphicsView::mousePressEvent( event );
267void QgsModelGraphicsView::mouseReleaseEvent( QMouseEvent *event )
275 mTool->modelReleaseEvent( me.get() );
276 event->setAccepted( me->isAccepted() );
279 if ( !mTool || !event->isAccepted() )
280 QGraphicsView::mouseReleaseEvent( event );
283void QgsModelGraphicsView::mouseMoveEvent( QMouseEvent *event )
288 mMouseCurrentXY =
event->pos();
290 QPointF cursorPos = mapToScene( mMouseCurrentXY );
293 auto me = std::make_unique<QgsModelViewMouseEvent>(
this, event,
false );
301 if ( me->isSnapped() )
303 cursorPos = me->snappedPoint();
306 mSnapMarker->setPos( me->snappedPoint() );
307 mSnapMarker->setVisible(
true );
310 else if ( mSnapMarker )
312 mSnapMarker->setVisible(
false );
315 mTool->modelMoveEvent( me.get() );
316 event->setAccepted( me->isAccepted() );
319 if ( !mTool || !event->isAccepted() )
320 QGraphicsView::mouseMoveEvent( event );
323void QgsModelGraphicsView::mouseDoubleClickEvent( QMouseEvent *event )
331 mTool->modelDoubleClickEvent( me.get() );
332 event->setAccepted( me->isAccepted() );
335 if ( !mTool || !event->isAccepted() )
336 QGraphicsView::mouseDoubleClickEvent( event );
339void QgsModelGraphicsView::keyPressEvent( QKeyEvent *event )
346 mTool->keyPressEvent( event );
349 if ( mTool && event->isAccepted() )
352 if ( event->key() == Qt::Key_Space && !event->isAutoRepeat() && mTool != mMidMouseButtonPanTool )
354 if ( !( event->modifiers() & Qt::ControlModifier ) )
357 setTool( mSpacePanTool );
362 setTool( mSpaceZoomTool );
366 else if ( event->key() == Qt::Key_Left
367 || event->key() == Qt::Key_Right
368 || event->key() == Qt::Key_Up
369 || event->key() == Qt::Key_Down )
371 QgsModelGraphicsScene *s = modelScene();
372 const QList<QgsModelComponentGraphicItem *> itemList = s->selectedComponentItems();
373 if ( !itemList.empty() )
375 QPointF delta = deltaForKeyEvent( event );
377 itemList.at( 0 )->aboutToChange( tr(
"Move Items" ) );
378 for ( QgsModelComponentGraphicItem *item : itemList )
380 item->moveComponentBy( delta.x(), delta.y() );
382 itemList.at( 0 )->changed();
388void QgsModelGraphicsView::keyReleaseEvent( QKeyEvent *event )
395 mTool->keyReleaseEvent( event );
398 if ( !mTool || !event->isAccepted() )
399 QGraphicsView::keyReleaseEvent( event );
402void QgsModelGraphicsView::setModelScene( QgsModelGraphicsScene *scene )
406 connect( scene, &QgsModelGraphicsScene::sceneRectChanged,
this, &QgsModelGraphicsView::friendlySetSceneRect );
410 mSnapMarker =
new QgsModelViewSnapMarker();
412 scene->addItem( mSnapMarker );
415QgsModelGraphicsScene *QgsModelGraphicsView::modelScene()
const
417 return qobject_cast<QgsModelGraphicsScene *>( QgsModelGraphicsView::scene() );
441 emit toolSet( mTool );
446 if ( mTool && mTool == tool )
449 emit toolSet(
nullptr );
450 setCursor( Qt::ArrowCursor );
459void QgsModelGraphicsView::startMacroCommand(
const QString &text )
461 emit macroCommandStarted( text );
464void QgsModelGraphicsView::endMacroCommand()
466 emit macroCommandEnded();
469void QgsModelGraphicsView::beginCommand(
const QString &text )
471 emit commandBegun( text );
474void QgsModelGraphicsView::endCommand()
479void QgsModelGraphicsView::abortCommand()
481 emit commandAborted();
484void QgsModelGraphicsView::snapSelected()
486 QgsModelGraphicsScene *s = modelScene();
487 const QList<QgsModelComponentGraphicItem *> itemList = s->selectedComponentItems();
488 startMacroCommand( tr(
"Snap Items" ) );
489 if ( !itemList.empty() )
491 bool prevSetting = mSnapper.snapToGrid();
492 mSnapper.setSnapToGrid(
true );
493 for ( QgsModelComponentGraphicItem *item : itemList )
495 bool wasSnapped =
false;
496 QRectF snapped = mSnapper.snapRectWithResize( item->mapRectToScene( item->itemRect() ), transform().m11(), wasSnapped );
499 item->setItemRect( snapped );
502 mSnapper.setSnapToGrid( prevSetting );
507void QgsModelGraphicsView::friendlySetSceneRect()
509 if ( mBlockScrollbarSignals )
512 QRectF modelSceneRect = modelScene()->sceneRect();
513 QRectF viewSceneRect = sceneRect();
515 QRectF visibleRect = mapToScene( viewport()->rect() ).boundingRect();
517 viewSceneRect.setLeft( std::min( modelSceneRect.left(), visibleRect.left() ) );
518 viewSceneRect.setRight( std::max( modelSceneRect.right(), visibleRect.right() ) );
519 viewSceneRect.setTop( std::min( modelSceneRect.top(), visibleRect.top() ) );
520 viewSceneRect.setBottom( std::max( modelSceneRect.bottom(), visibleRect.bottom() ) );
522 mBlockScrollbarSignals++;
523 setSceneRect( viewSceneRect );
524 mBlockScrollbarSignals--;
527void QgsModelGraphicsView::copySelectedItems( QgsModelGraphicsView::ClipboardOperation operation )
529 copyItems( modelScene()->selectedComponentItems(), operation );
532void QgsModelGraphicsView::copyItems(
const QList<QgsModelComponentGraphicItem *> &items, QgsModelGraphicsView::ClipboardOperation operation )
539 QDomElement documentElement = doc.createElement( QStringLiteral(
"ModelComponentClipboard" ) );
540 if ( operation == ClipboardCut )
542 emit macroCommandStarted( tr(
"Cut Items" ) );
543 emit commandBegun( QString() );
546 QList<QVariant> paramComponents;
547 QList<QVariant> groupBoxComponents;
548 QList<QVariant> algComponents;
550 QList<QgsModelComponentGraphicItem *> selectedCommentParents;
551 QList<QgsProcessingModelOutput> selectedOutputs;
552 QList<QgsProcessingModelOutput> selectedOutputsComments;
553 for ( QgsModelComponentGraphicItem *item : items )
555 if (
const QgsModelCommentGraphicItem *commentItem =
dynamic_cast<QgsModelCommentGraphicItem *
>( item ) )
557 selectedCommentParents << commentItem->parentComponentItem();
558 if (
const QgsModelOutputGraphicItem *outputItem =
dynamic_cast<QgsModelOutputGraphicItem *
>( commentItem->parentComponentItem() ) )
560 selectedOutputsComments << *( static_cast<const QgsProcessingModelOutput *>( outputItem->component() ) );
563 else if (
const QgsModelOutputGraphicItem *outputItem =
dynamic_cast<QgsModelOutputGraphicItem *
>( item ) )
565 selectedOutputs << *( static_cast<const QgsProcessingModelOutput *>( outputItem->component() ) );
569 for ( QgsModelComponentGraphicItem *item : items )
571 if (
const QgsProcessingModelParameter *param =
dynamic_cast<QgsProcessingModelParameter *
>( item->component() ) )
573 QgsProcessingModelParameter component = *param;
576 if ( !selectedCommentParents.contains( item ) )
579 component.comment()->setDescription( QString() );
582 QVariantMap paramDef;
583 paramDef.insert( QStringLiteral(
"component" ), component.toVariant() );
585 paramDef.insert( QStringLiteral(
"definition" ), def->
toVariantMap() );
587 paramComponents << paramDef;
589 else if ( QgsProcessingModelGroupBox *groupBox =
dynamic_cast<QgsProcessingModelGroupBox *
>( item->component() ) )
591 groupBoxComponents << groupBox->toVariant();
593 else if (
const QgsProcessingModelChildAlgorithm *alg =
dynamic_cast<QgsProcessingModelChildAlgorithm *
>( item->component() ) )
595 QgsProcessingModelChildAlgorithm childAlg = *alg;
598 if ( !selectedCommentParents.contains( item ) )
601 childAlg.comment()->setDescription( QString() );
605 QMap<QString, QgsProcessingModelOutput> clipboardOutputs;
606 const QMap<QString, QgsProcessingModelOutput> existingOutputs = childAlg.modelOutputs();
607 for (
auto it = existingOutputs.constBegin(); it != existingOutputs.constEnd(); ++it )
610 for (
const QgsProcessingModelOutput &candidate : selectedOutputs )
612 if ( candidate.childId() == childAlg.childId() && candidate.name() == it.value().name() && candidate.childOutputName() == it.value().childOutputName() )
621 bool commentFound =
false;
622 for (
const QgsProcessingModelOutput &candidate : selectedOutputsComments )
624 if ( candidate.childId() == childAlg.childId() && candidate.name() == it.value().name() && candidate.childOutputName() == it.value().childOutputName() )
631 QgsProcessingModelOutput output = it.value();
633 output.comment()->setDescription( QString() );
635 clipboardOutputs.insert( it.key(), output );
638 childAlg.setModelOutputs( clipboardOutputs );
640 algComponents << childAlg.toVariant();
643 QVariantMap components;
644 components.insert( QStringLiteral(
"parameters" ), paramComponents );
645 components.insert( QStringLiteral(
"groupboxes" ), groupBoxComponents );
646 components.insert( QStringLiteral(
"algs" ), algComponents );
648 if ( operation == ClipboardCut )
650 emit deleteSelectedItems();
652 emit macroCommandEnded();
655 QMimeData *mimeData =
new QMimeData;
656 mimeData->setData( QStringLiteral(
"text/xml" ), doc.toByteArray() );
657 mimeData->setText( doc.toByteArray() );
658 QClipboard *clipboard = QApplication::clipboard();
659 clipboard->setMimeData( mimeData );
662void QgsModelGraphicsView::pasteItems( QgsModelGraphicsView::PasteMode mode )
668 QClipboard *clipboard = QApplication::clipboard();
669 const QMimeData *mimeData = clipboard->mimeData();
672 if ( doc.setContent( mimeData->data( QStringLiteral(
"text/xml" ) ) ) )
674 QDomElement docElem = doc.documentElement();
677 if ( res.contains( QStringLiteral(
"parameters" ) ) && res.contains( QStringLiteral(
"algs" ) ) )
682 case PasteModeCursor:
683 case PasteModeInPlace:
686 pt = mapToScene( mapFromGlobal( QCursor::pos() ) );
689 case PasteModeCenter:
692 pt = mapToScene( viewport()->rect().center() );
697 beginCommand( tr(
"Paste Items" ) );
701 QList<QgsProcessingModelGroupBox> pastedGroups;
702 for (
const QVariant &v : res.value( QStringLiteral(
"groupboxes" ) ).toList() )
704 QgsProcessingModelGroupBox box;
706 box.loadVariant( v.toMap(),
true );
710 modelScene()->model()->addGroupBox( box );
712 if ( !pastedBounds.isValid() )
713 pastedBounds = QRectF( box.position() - QPointF( box.size().width() / 2.0, box.size().height() / 2.0 ), box.size() );
715 pastedBounds = pastedBounds.united( QRectF( box.position() - QPointF( box.size().width() / 2.0, box.size().height() / 2.0 ), box.size() ) );
718 QStringList pastedParameters;
719 for (
const QVariant &v : res.value( QStringLiteral(
"parameters" ) ).toList() )
721 QVariantMap param = v.toMap();
722 QVariantMap componentDef = param.value( QStringLiteral(
"component" ) ).toMap();
723 QVariantMap paramDef = param.value( QStringLiteral(
"definition" ) ).toMap();
727 QgsProcessingModelParameter p;
728 p.loadVariant( componentDef );
731 QString name = p.parameterName();
732 QString description = paramDefinition->description();
734 while ( modelScene()->model()->parameterDefinition( name ) )
737 name = QStringLiteral(
"%1 (%2)" ).arg( p.parameterName() ).arg( next );
738 description = QStringLiteral(
"%1 (%2)" ).arg( paramDefinition->description() ).arg( next );
740 paramDefinition->setName( name );
741 paramDefinition->setDescription( description );
742 p.setParameterName( name );
744 modelScene()->model()->addModelParameter( paramDefinition.release(), p );
745 pastedParameters << p.parameterName();
747 if ( !pastedBounds.isValid() )
748 pastedBounds = QRectF( p.position() - QPointF( p.size().width() / 2.0, p.size().height() / 2.0 ), p.size() );
750 pastedBounds = pastedBounds.united( QRectF( p.position() - QPointF( p.size().width() / 2.0, p.size().height() / 2.0 ), p.size() ) );
752 if ( !p.comment()->description().isEmpty() )
753 pastedBounds = pastedBounds.united( QRectF( p.comment()->position() - QPointF( p.comment()->size().width() / 2.0, p.comment()->size().height() / 2.0 ), p.comment()->size() ) );
756 QStringList pastedAlgorithms;
757 for (
const QVariant &v : res.value( QStringLiteral(
"algs" ) ).toList() )
759 QgsProcessingModelChildAlgorithm alg;
760 alg.loadVariant( v.toMap() );
763 if ( modelScene()->model()->childAlgorithms().contains( alg.childId() ) )
765 alg.generateChildId( *modelScene()->model() );
769 pastedAlgorithms << alg.childId();
771 if ( !pastedBounds.isValid() )
772 pastedBounds = QRectF( alg.position() - QPointF( alg.size().width() / 2.0, alg.size().height() / 2.0 ), alg.size() );
774 pastedBounds = pastedBounds.united( QRectF( alg.position() - QPointF( alg.size().width() / 2.0, alg.size().height() / 2.0 ), alg.size() ) );
776 if ( !alg.comment()->description().isEmpty() )
777 pastedBounds = pastedBounds.united( QRectF( alg.comment()->position() - QPointF( alg.comment()->size().width() / 2.0, alg.comment()->size().height() / 2.0 ), alg.comment()->size() ) );
779 const QMap<QString, QgsProcessingModelChildAlgorithm> existingAlgs = modelScene()->model()->childAlgorithms();
781 const QMap<QString, QgsProcessingModelOutput> outputs = alg.modelOutputs();
782 QMap<QString, QgsProcessingModelOutput> pastedOutputs;
783 for (
auto it = outputs.constBegin(); it != outputs.constEnd(); ++it )
785 QString name = it.value().name();
791 for (
auto algIt = existingAlgs.constBegin(); algIt != existingAlgs.constEnd(); ++algIt )
793 const QMap<QString, QgsProcessingModelOutput> algOutputs = algIt->modelOutputs();
794 for (
auto outputIt = algOutputs.constBegin(); outputIt != algOutputs.constEnd(); ++outputIt )
796 if ( outputIt.value().name() == name )
808 name = QStringLiteral(
"%1 (%2)" ).arg( it.value().name() ).arg( next );
811 QgsProcessingModelOutput newOutput = it.value();
812 newOutput.setName( name );
813 newOutput.setDescription( name );
814 pastedOutputs.insert( name, newOutput );
816 pastedBounds = pastedBounds.united( QRectF( newOutput.position() - QPointF( newOutput.size().width() / 2.0, newOutput.size().height() / 2.0 ), newOutput.size() ) );
818 if ( !alg.comment()->description().isEmpty() )
819 pastedBounds = pastedBounds.united( QRectF( newOutput.comment()->position() - QPointF( newOutput.comment()->size().width() / 2.0, newOutput.comment()->size().height() / 2.0 ), newOutput.comment()->size() ) );
821 alg.setModelOutputs( pastedOutputs );
823 modelScene()->model()->addChildAlgorithm( alg );
826 QPointF offset( 0, 0 );
829 case PasteModeInPlace:
832 case PasteModeCursor:
833 case PasteModeCenter:
835 offset = pt - pastedBounds.topLeft();
840 if ( !offset.isNull() )
842 for ( QgsProcessingModelGroupBox pastedGroup : std::as_const( pastedGroups ) )
844 pastedGroup.setPosition( pastedGroup.position() + offset );
845 modelScene()->model()->addGroupBox( pastedGroup );
847 for (
const QString &pastedParam : std::as_const( pastedParameters ) )
849 modelScene()->model()->parameterComponent( pastedParam ).setPosition( modelScene()->model()->parameterComponent( pastedParam ).position() + offset );
850 modelScene()->model()->parameterComponent( pastedParam ).comment()->setPosition( modelScene()->model()->parameterComponent( pastedParam ).comment()->position() + offset );
852 for (
const QString &pastedAlg : std::as_const( pastedAlgorithms ) )
854 modelScene()->model()->childAlgorithm( pastedAlg ).setPosition( modelScene()->model()->childAlgorithm( pastedAlg ).position() + offset );
855 modelScene()->model()->childAlgorithm( pastedAlg ).comment()->setPosition( modelScene()->model()->childAlgorithm( pastedAlg ).comment()->position() + offset );
857 const QMap<QString, QgsProcessingModelOutput> outputs = modelScene()->model()->childAlgorithm( pastedAlg ).modelOutputs();
858 for (
auto it = outputs.begin(); it != outputs.end(); ++it )
860 modelScene()->model()->childAlgorithm( pastedAlg ).modelOutput( it.key() ).setPosition( modelScene()->model()->childAlgorithm( pastedAlg ).modelOutput( it.key() ).position() + offset );
861 modelScene()->model()->childAlgorithm( pastedAlg ).modelOutput( it.key() ).comment()->setPosition( modelScene()->model()->childAlgorithm( pastedAlg ).modelOutput( it.key() ).comment()->position() + offset );
870 modelScene()->rebuildRequired();
873QgsModelViewSnapMarker::QgsModelViewSnapMarker()
874 : QGraphicsRectItem( QRectF( 0, 0, 0, 0 ) )
877 QFontMetrics fm( f );
878 mSize = fm.horizontalAdvance(
'X' );
879 setPen( QPen( Qt::transparent, mSize ) );
881 setFlags( flags() | QGraphicsItem::ItemIgnoresTransformations );
882 setZValue( QgsModelGraphicsScene::ZSnapIndicator );
885void QgsModelViewSnapMarker::paint( QPainter *p,
const QStyleOptionGraphicsItem *, QWidget * )
887 QPen pen( QColor( 255, 0, 0 ) );
890 p->setBrush( Qt::NoBrush );
892 double halfSize = mSize / 2.0;
893 p->drawLine( QLineF( -halfSize, -halfSize, halfSize, halfSize ) );
894 p->drawLine( QLineF( -halfSize, halfSize, halfSize, -halfSize ) );
Manages snapping grids and preset snap lines in a layout, and handles snapping points to the nearest ...
Base class for the definition of processing parameters.
virtual QVariantMap toVariantMap() const
Saves this parameter to a QVariantMap.
static QgsProcessingParameterDefinition * parameterFromVariantMap(const QVariantMap &map)
Creates a new QgsProcessingParameterDefinition using the configuration from a supplied variant map.
A container for the context for various read/write operations on objects.
A rectangle specified with double values.
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.