bool QgsMapToolPinLabels::pinUnpinCurrentDiagram( bool pin ) { // skip diagrams if ( ! mCurrentLabel.pos.isDiagram ) return false; // verify attribute table has x, y fields mapped int xCol, yCol; double xPosOrig, yPosOrig; bool xSuccess, ySuccess; if ( !currentLabelDataDefinedPosition( xPosOrig, xSuccess, yPosOrig, ySuccess, xCol, yCol ) ) return false; // edit attribute table QgsVectorLayer *vlayer = mCurrentLabel.layer; int fid = mCurrentLabel.pos.featureId; bool writeFailed = false; QString labelText = currentLabelText( 24 ); if ( pin ) { QgsPointXY referencePoint = mCurrentLabel.pos.labelRect.center(); double labelX = referencePoint.x(); double labelY = referencePoint.y(); // transform back to layer crs QgsPointXY transformedPoint = mCanvas->mapSettings().mapToLayerCoordinates( vlayer, referencePoint ); labelX = transformedPoint.x(); labelY = transformedPoint.y(); vlayer->beginEditCommand( tr( "Pinned diagram" ) + QStringLiteral( " '%1'" ).arg( labelText ) ); writeFailed = !vlayer->changeAttributeValue( fid, xCol, labelX ); if ( !vlayer->changeAttributeValue( fid, yCol, labelY ) ) writeFailed = true; vlayer->endEditCommand(); } else { vlayer->beginEditCommand( tr( "Unpinned diagram" ) + QStringLiteral( " '%1'" ).arg( labelText ) ); writeFailed = !vlayer->changeAttributeValue( fid, xCol, QVariant( QString() ) ); if ( !vlayer->changeAttributeValue( fid, yCol, QVariant( QString() ) ) ) writeFailed = true; vlayer->endEditCommand(); } return !writeFailed; }
bool QgsMapToolLabel::isPinned() { bool rc = false; if ( ! mCurrentLabel.pos.isDiagram ) { rc = mCurrentLabel.pos.isPinned; } else { // for diagrams, the isPinned attribute is not set. So we check directly if // there's data defined. int xCol, yCol; double x, y; bool xSuccess, ySuccess; if ( currentLabelDataDefinedPosition( x, xSuccess, y, ySuccess, xCol, yCol ) && xSuccess && ySuccess ) rc = true; } return rc; }
bool QgsMapToolLabel::currentLabelDataDefinedRotation( double &rotation, bool &rotationSuccess, int &rCol, bool ignoreXY ) const { QgsVectorLayer *vlayer = mCurrentLabel.layer; QgsFeatureId featureId = mCurrentLabel.pos.featureId; rotationSuccess = false; if ( !vlayer ) { return false; } if ( !labelIsRotatable( vlayer, mCurrentLabel.settings, rCol ) ) { return false; } QgsFeature f; if ( !vlayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setFlags( QgsFeatureRequest::NoGeometry ) ).nextFeature( f ) ) { return false; } //test, if data defined x- and y- values are not null. Otherwise, the position is determined by PAL and the rotation cannot be fixed if ( !ignoreXY ) { int xCol, yCol; double x, y; bool xSuccess, ySuccess; if ( !currentLabelDataDefinedPosition( x, xSuccess, y, ySuccess, xCol, yCol ) || !xSuccess || !ySuccess ) { return false; } } rotation = f.attribute( rCol ).toDouble( &rotationSuccess ); return true; }
void QgsMapToolMoveLabel::canvasReleaseEvent( QgsMapMouseEvent* e ) { if ( !mLabelRubberBand ) { return; } deleteRubberBands(); QgsVectorLayer* vlayer = mCurrentLabel.layer; if ( !vlayer || !vlayer->isEditable() ) { return; } QgsPoint releaseCoords = toMapCoordinates( e->pos() ); double xdiff = releaseCoords.x() - mStartPointMapCoords.x(); double ydiff = releaseCoords.y() - mStartPointMapCoords.y(); int xCol, yCol; double xPosOrig, yPosOrig; bool xSuccess, ySuccess; if ( !currentLabelDataDefinedPosition( xPosOrig, xSuccess, yPosOrig, ySuccess, xCol, yCol ) ) { return; } double xPosNew, yPosNew; if ( !xSuccess || !ySuccess ) { xPosNew = releaseCoords.x() - mClickOffsetX; yPosNew = releaseCoords.y() - mClickOffsetY; } else { //transform to map crs first, because xdiff,ydiff are in map coordinates const QgsMapSettings& ms = mCanvas->mapSettings(); if ( ms.hasCrsTransformEnabled() ) { QgsPoint transformedPoint = ms.layerToMapCoordinates( vlayer, QgsPoint( xPosOrig, yPosOrig ) ); xPosOrig = transformedPoint.x(); yPosOrig = transformedPoint.y(); } xPosNew = xPosOrig + xdiff; yPosNew = yPosOrig + ydiff; } //transform back to layer crs if ( mCanvas ) { const QgsMapSettings& s = mCanvas->mapSettings(); if ( s.hasCrsTransformEnabled() ) { QgsPoint transformedPoint = s.mapToLayerCoordinates( vlayer, QgsPoint( xPosNew, yPosNew ) ); xPosNew = transformedPoint.x(); yPosNew = transformedPoint.y(); } } vlayer->beginEditCommand( tr( "Moved label" ) + QString( " '%1'" ).arg( currentLabelText( 24 ) ) ); vlayer->changeAttributeValue( mCurrentLabel.pos.featureId, xCol, xPosNew ); vlayer->changeAttributeValue( mCurrentLabel.pos.featureId, yCol, yPosNew ); // set rotation to that of label, if data-defined and no rotation set yet // honor whether to preserve preexisting data on pin // must come after setting x and y positions if ( !mCurrentLabel.pos.isDiagram && !mCurrentLabel.pos.isPinned && !currentLabelPreserveRotation() ) { double defRot; bool rSuccess; int rCol; if ( currentLabelDataDefinedRotation( defRot, rSuccess, rCol ) ) { double labelRot = mCurrentLabel.pos.rotation * 180 / M_PI; vlayer->changeAttributeValue( mCurrentLabel.pos.featureId, rCol, labelRot ); } } vlayer->endEditCommand(); if ( mCanvas ) mCanvas->refresh(); }
bool QgsMapToolPinLabels::pinUnpinCurrentLabel( bool pin ) { QgsVectorLayer *vlayer = mCurrentLabel.layer; const QgsLabelPosition &labelpos = mCurrentLabel.pos; // skip diagrams if ( labelpos.isDiagram ) { QgsDebugMsg( QStringLiteral( "Label is diagram, skipping" ) ); return false; } // verify attribute table has x, y fields mapped int xCol, yCol; double xPosOrig, yPosOrig; bool xSuccess, ySuccess; if ( !currentLabelDataDefinedPosition( xPosOrig, xSuccess, yPosOrig, ySuccess, xCol, yCol ) ) { QgsDebugMsg( QStringLiteral( "Label X or Y column not mapped, skipping" ) ); return false; } // rotation field is optional, but will be used if available, unless data exists int rCol; bool rSuccess = false; double defRot; bool hasRCol = currentLabelDataDefinedRotation( defRot, rSuccess, rCol, true ); // get whether to preserve predefined rotation data during label pin/unpin operations bool preserveRot = currentLabelPreserveRotation(); // edit attribute table int fid = labelpos.featureId; bool writeFailed = false; QString labelText = currentLabelText( 24 ); if ( pin ) { // QgsPointXY labelpoint = labelpos.cornerPoints.at( 0 ); QgsPointXY referencePoint; if ( !currentLabelRotationPoint( referencePoint, !preserveRot, false ) ) { referencePoint.setX( labelpos.labelRect.xMinimum() ); referencePoint.setY( labelpos.labelRect.yMinimum() ); } double labelX = referencePoint.x(); double labelY = referencePoint.y(); double labelR = labelpos.rotation * 180 / M_PI; // transform back to layer crs QgsPointXY transformedPoint = mCanvas->mapSettings().mapToLayerCoordinates( vlayer, referencePoint ); labelX = transformedPoint.x(); labelY = transformedPoint.y(); vlayer->beginEditCommand( tr( "Pinned label" ) + QStringLiteral( " '%1'" ).arg( labelText ) ); writeFailed = !vlayer->changeAttributeValue( fid, xCol, labelX ); if ( !vlayer->changeAttributeValue( fid, yCol, labelY ) ) writeFailed = true; if ( hasRCol && !preserveRot ) { if ( !vlayer->changeAttributeValue( fid, rCol, labelR ) ) writeFailed = true; } vlayer->endEditCommand(); } else { vlayer->beginEditCommand( tr( "Unpinned label" ) + QStringLiteral( " '%1'" ).arg( labelText ) ); writeFailed = !vlayer->changeAttributeValue( fid, xCol, QVariant( QString() ) ); if ( !vlayer->changeAttributeValue( fid, yCol, QVariant( QString() ) ) ) writeFailed = true; if ( hasRCol && !preserveRot ) { if ( !vlayer->changeAttributeValue( fid, rCol, QVariant( QString() ) ) ) writeFailed = true; } vlayer->endEditCommand(); } if ( writeFailed ) { QgsDebugMsg( QStringLiteral( "Write to attribute table failed" ) ); #if 0 QgsDebugMsg( QStringLiteral( "Undoing and removing failed command from layer's undo stack" ) ); int lastCmdIndx = vlayer->undoStack()->count(); const QgsUndoCommand *lastCmd = qobject_cast<const QgsUndoCommand *>( vlayer->undoStack()->command( lastCmdIndx ) ); if ( lastCmd ) { vlayer->undoEditCommand( lastCmd ); delete vlayer->undoStack()->command( lastCmdIndx ); } #endif return false; } return true; }