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 QgsMapToolShowHideLabels::showHideLabel( QgsVectorLayer* vlayer,
    int fid,
    bool hide )
{

  // verify attribute table has proper field setup
  bool showSuccess;
  int showCol;
  int show;

  if ( !dataDefinedShowHide( vlayer, fid, show, showSuccess, showCol ) )
  {
    return false;
  }

  // check if attribute value is already the same
  QgsFeature f;
  if ( !vlayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ).setFlags( QgsFeatureRequest::NoGeometry ) ).nextFeature( f ) )
  {
    return false;
  }

  int colVal = hide ? 0 : 1;
  QVariant fQVal = f.attributes()[showCol];
  bool convToInt;
  int fVal = fQVal.toInt( &convToInt );

  if ( !convToInt || fVal == colVal )
  {
    return false;
  }

  // different attribute value, edit table
  QString labelText = currentLabelText( 24 );
  QString editTxt = hide ? tr( "Hid label" ) : tr( "Showed label" );
  vlayer->beginEditCommand( editTxt + QString( " '%1'" ).arg( labelText ) );
  if ( !vlayer->changeAttributeValue( fid, showCol, colVal, true ) )
  {
    QgsDebugMsg( "Failed write to attribute table" );
    vlayer->endEditCommand();
    return false;
  }
  vlayer->endEditCommand();
  return true;
}
示例#3
0
void QgsMapToolRotateLabel::canvasReleaseEvent( QgsMapMouseEvent* e )
{
  Q_UNUSED( e );

  if ( !mLabelRubberBand ) //no rubber band created (most likely because the current label cannot be rotated )
  {
    return;
  }

  deleteRubberBands();
  delete mRotationItem;
  mRotationItem = nullptr;
  delete mRotationPreviewBox;
  mRotationPreviewBox = nullptr;

  QgsVectorLayer* vlayer = mCurrentLabel.layer;
  if ( !vlayer )
  {
    return;
  }

  int rotationCol;
  if ( !labelIsRotatable( vlayer, mCurrentLabel.settings, rotationCol ) )
  {
    return;
  }

  double rotation = mCtrlPressed ? roundTo15Degrees( mCurrentRotation ) : mCurrentRotation;
  if ( rotation == mStartRotation ) //mouse button pressed / released, but no rotation
  {
    return;
  }

  vlayer->beginEditCommand( tr( "Rotated label" ) + QString( " '%1'" ).arg( currentLabelText( 24 ) ) );
  vlayer->changeAttributeValue( mCurrentLabel.pos.featureId, rotationCol, rotation );
  vlayer->endEditCommand();
  vlayer->triggerRepaint();
}
示例#4
0
void QgsMapToolMoveLabel::canvasReleaseEvent( QgsMapMouseEvent* e )
{
  if ( !mLabelRubberBand )
  {
    return;
  }

  deleteRubberBands();

  QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( mCurrentLabelPos.layerID );
  if ( !layer )
  {
    return;
  }

  QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>( layer );
  if ( !vlayer )
  {
    return;
  }

  if ( !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 ( !dataDefinedPosition( vlayer, mCurrentLabelPos.featureId, 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( mCurrentLabelPos.featureId, xCol, xPosNew );
  vlayer->changeAttributeValue( mCurrentLabelPos.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
  int rCol;
  if ( !mCurrentLabelPos.isDiagram
       && !mCurrentLabelPos.isPinned
       && !preserveRotation()
       && layerIsRotatable( vlayer, rCol ) )
  {
    double defRot;
    bool rSuccess;
    if ( dataDefinedRotation( vlayer, mCurrentLabelPos.featureId, defRot, rSuccess ) )
    {
      double labelRot = mCurrentLabelPos.rotation * 180 / M_PI;
      vlayer->changeAttributeValue( mCurrentLabelPos.featureId, rCol, labelRot );
    }
  }
  vlayer->endEditCommand();

  if ( mCanvas )
    mCanvas->refresh();
}
void QgsMapToolChangeLabelProperties::canvasReleaseEvent( QMouseEvent *e )
{
  Q_UNUSED( e );
  QgsVectorLayer* vlayer = currentLayer();
  if ( mLabelRubberBand && mCanvas && vlayer )
  {
    QString labeltext = QString(); // NULL QString signifies no expression
    bool settingsOk;
    QgsPalLayerSettings& labelSettings = currentLabelSettings( &settingsOk );
    if ( settingsOk && labelSettings.isExpression )
    {
      labeltext = mCurrentLabelPos.labelText;
    }

    QgsLabelPropertyDialog d( mCurrentLabelPos.layerID, mCurrentLabelPos.featureId, mCurrentLabelPos.labelFont, labeltext, 0 );
    if ( d.exec() == QDialog::Accepted )
    {
      const QgsAttributeMap& changes = d.changedProperties();
      if ( changes.size() > 0 )
      {
        vlayer->beginEditCommand( tr( "Changed properties for label" ) + QString( " '%1'" ).arg( currentLabelText( 24 ) ) );

        QgsAttributeMap::const_iterator changeIt = changes.constBegin();
        for ( ; changeIt != changes.constEnd(); ++changeIt )
        {
          vlayer->changeAttributeValue( mCurrentLabelPos.featureId, changeIt.key(), changeIt.value() );
        }

        vlayer->endEditCommand();
        mCanvas->refresh();
      }
    }
    deleteRubberBands();
  }
}
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;
}
示例#7
0
void QgsMapToolPinLabels::pinUnpinLabels( const QgsRectangle& ext, QMouseEvent * e )
{

  bool doUnpin = e->modifiers() & Qt::ShiftModifier ? true : false;
  bool toggleUnpinOrPin = e->modifiers() & Qt::ControlModifier ? true : false;

  // get list of all drawn labels from all layers within, or touching, chosen extent
  bool labelChanged = false;

  const QgsLabelingResults* labelingResults = mCanvas->labelingResults();
  if ( !labelingResults )
  {
    QgsDebugMsg( QString( "No labeling engine" ) );
    return;
  }

  QList<QgsLabelPosition> labelPosList = labelingResults->labelsWithinRect( ext );

  QList<QgsLabelPosition>::const_iterator it;
  for ( it = labelPosList.constBegin() ; it != labelPosList.constEnd(); ++it )
  {
    mCurrentLabelPos = *it;

#ifdef QGISDEBUG
    QString labellyr = currentLayer()->name();
    QString labeltxt = currentLabelText();
#endif
    QgsDebugMsg( QString( "Layer: %0" ).arg( labellyr ) );
    QgsDebugMsg( QString( "Label: %0" ).arg( labeltxt ) );

    QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( mCurrentLabelPos.layerID );
    if ( !layer )
    {
      QgsDebugMsg( QString( "Failed to get label layer" ) );
      continue;
    }
    QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>( layer );
    if ( !vlayer )
    {
      QgsDebugMsg( QString( "Failed to cast label layer to vector layer" ) );
      continue;
    }
    if ( !vlayer->isEditable() )
    {
      QgsDebugMsg( QString( "Vector layer not editable, skipping label" ) );
      continue;
    }

    QString labelStringID = QString( "%0|%1" ).arg( mCurrentLabelPos.layerID, QString::number( mCurrentLabelPos.featureId ) );

    // unpin label
    if ( mCurrentLabelPos.isPinned && ( doUnpin  || toggleUnpinOrPin ) )
    {
      // unpin previously pinned label (set attribute table fields to NULL)
      if ( pinUnpinLabel( vlayer, mCurrentLabelPos, false ) )
      {
        labelChanged = true;
      }
      else
      {
        QgsDebugMsg( QString( "Unpin failed for layer, label: %0, %1" ).arg( labellyr, labeltxt ) );
      }
    }

    // pin label
    if ( !mCurrentLabelPos.isPinned && ( !doUnpin || toggleUnpinOrPin ) )
    {
      // pin label's location, and optionally rotation, to attribute table
      if ( pinUnpinLabel( vlayer, mCurrentLabelPos, true ) )
      {
        labelChanged = true;
      }
      else
      {
        QgsDebugMsg( QString( "Pin failed for layer, label: %0, %1" ).arg( labellyr, labeltxt ) );
      }
    }
  }

  if ( labelChanged )
  {
    mCanvas->refresh();

    if ( !mShowPinned )
    {
      // toggle it on (pin-unpin tool doesn't work well without it)
      QgisApp::instance()->actionShowPinnedLabels()->setChecked( true );
    }
  }
}
示例#8
0
bool QgsMapToolLabel::rotationPoint( QgsPoint& pos, bool ignoreUpsideDown )
{
    QVector<QgsPoint> cornerPoints = mCurrentLabelPos.cornerPoints;
    if ( cornerPoints.size() < 4 )
    {
        return false;
    }

    if ( mCurrentLabelPos.upsideDown && !ignoreUpsideDown )
    {
        pos = mCurrentLabelPos.cornerPoints.at( 2 );
    }
    else
    {
        pos = mCurrentLabelPos.cornerPoints.at( 0 );
    }

    //alignment always center/center and rotation 0 for diagrams
    if ( mCurrentLabelPos.isDiagram )
    {
        pos.setX( pos.x() + mCurrentLabelPos.labelRect.width() / 2.0 );
        pos.setY( pos.y() + mCurrentLabelPos.labelRect.height() / 2.0 );
        return true;
    }

    //adapt pos depending on data defined alignment
    QString haliString, valiString;
    currentAlignment( haliString, valiString );

    if ( !mCurrentLabelPos.isPinned )
    {
        haliString = "Center";
        valiString = "Half";
    }

    QFont labelFont = labelFontCurrentFeature();
    QFontMetricsF labelFontMetrics( labelFont );

    //label text?
    QString labelText = currentLabelText();

    bool labelSettingsOk;
    QgsPalLayerSettings& labelSettings = currentLabelSettings( &labelSettingsOk );
    if ( !labelSettingsOk )
    {
        return false;
    }

    double labelSizeX, labelSizeY;
    labelSettings.calculateLabelSize( &labelFontMetrics, labelText, labelSizeX, labelSizeY );

    double xdiff = 0;
    double ydiff = 0;

    if ( haliString.compare( "Center", Qt::CaseInsensitive ) == 0 )
    {
        xdiff = labelSizeX / 2.0;
    }
    else if ( haliString.compare( "Right", Qt::CaseInsensitive ) == 0 )
    {
        xdiff = labelSizeX;
    }

    if ( valiString.compare( "Top", Qt::CaseInsensitive ) == 0 || valiString.compare( "Cap", Qt::CaseInsensitive ) == 0 )
    {
        ydiff = labelSizeY;
    }
    else
    {
        double descentRatio = 1 / labelFontMetrics.ascent() / labelFontMetrics.height();
        if ( valiString.compare( "Base", Qt::CaseInsensitive ) == 0 )
        {
            ydiff = labelSizeY * descentRatio;
        }
        else if ( valiString.compare( "Half", Qt::CaseInsensitive ) == 0 )
        {
            ydiff = labelSizeY * descentRatio;
            ydiff = labelSizeY * 0.5 * ( 1 - descentRatio );
        }
    }

    double angle = mCurrentLabelPos.rotation;
    double xd = xdiff * cos( angle ) - ydiff * sin( angle );
    double yd = xdiff * sin( angle ) + ydiff * cos( angle );
    if ( mCurrentLabelPos.upsideDown && !ignoreUpsideDown )
    {
        pos.setX( pos.x() - xd );
        pos.setY( pos.y() - yd );
    }
    else
    {
        pos.setX( pos.x() + xd );
        pos.setY( pos.y() + yd );
    }
    return true;
}
void QgsMapToolChangeLabelProperties::applyChanges( const QgsAttributeMap& changes )
{
  QgsVectorLayer* vlayer = mCurrentLabel.layer;
  if ( !vlayer )
    return;

  if ( !changes.isEmpty() )
  {
    vlayer->beginEditCommand( tr( "Changed properties for label" ) + QStringLiteral( " '%1'" ).arg( currentLabelText( 24 ) ) );

    QgsAttributeMap::const_iterator changeIt = changes.constBegin();
    for ( ; changeIt != changes.constEnd(); ++changeIt )
    {
      vlayer->changeAttributeValue( mCurrentLabel.pos.featureId, changeIt.key(), changeIt.value() );
    }

    vlayer->endEditCommand();
    vlayer->triggerRepaint();
  }
}