void QgsSelectedFeature::moveSelectedVertexes( QgsVector v )
{
  int nUpdates = 0;
  Q_FOREACH ( QgsVertexEntry *entry, mVertexMap )
  {
    if ( entry->isSelected() )
      nUpdates++;
  }

  if ( nUpdates == 0 )
    return;

  mVlayer->beginEditCommand( QObject::tr( "Moved vertices" ) );
  int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 );

  beginGeometryChange();

  QMultiMap<double, QgsSnappingResult> currentResultList;
  for ( int i = mVertexMap.size() - 1; i > -1 && nUpdates > 0; i-- )
  {
    QgsVertexEntry *entry = mVertexMap.value( i, nullptr );
    if ( !entry || !entry->isSelected() )
      continue;

    if ( topologicalEditing )
    {
      // snap from current vertex
      currentResultList.clear();
      mVlayer->snapWithContext( entry->pointV1(), ZERO_TOLERANCE, currentResultList, QgsSnapper::SnapToVertex );
    }

    // only last update should trigger the geometry update
    // as vertex selection gets lost on the update
    if ( --nUpdates == 0 )
      endGeometryChange();

    QgsPointV2 p = entry->point();
    p.setX( p.x() + v.x() );
    p.setY( p.y() + v.y() );
    mVlayer->moveVertex( p, mFeatureId, i );

    if ( topologicalEditing )
    {
      QMultiMap<double, QgsSnappingResult>::iterator resultIt =  currentResultList.begin();

      for ( ; resultIt != currentResultList.end(); ++resultIt )
      {
        // move all other
        if ( mFeatureId !=  resultIt.value().snappedAtGeometry )
          mVlayer->moveVertex( p, resultIt.value().snappedAtGeometry, resultIt.value().snappedVertexNr );
      }
    }
  }

  if ( nUpdates > 0 )
    endGeometryChange();

  mVlayer->endEditCommand();
}
Exemple #2
0
QList<HistoryModel::HistoryEntryMatch> HistoryModel::findEntries(const QString &prefix, bool markAsTypedIn) const
{
	QList<HistoryEntryItem*> matchedEntries;
	QList<HistoryModel::HistoryEntryMatch> allMatches;
	QList<HistoryModel::HistoryEntryMatch> currentMatches;
	QMultiMap<QDateTime, HistoryModel::HistoryEntryMatch> matchesMap;
	QHash<QUrl, QList<HistoryEntryItem*> >::const_iterator urlsIterator;

	for (urlsIterator = m_urls.constBegin(); urlsIterator != m_urls.constEnd(); ++urlsIterator)
	{
		if (urlsIterator.value().isEmpty() || matchedEntries.contains(urlsIterator.value().first()))
		{
			continue;
		}

		const QString result(Utils::matchUrl(urlsIterator.key(), prefix));

		if (!result.isEmpty())
		{
			HistoryEntryMatch match;
			match.entry = urlsIterator.value().first();
			match.match = result;

			if (markAsTypedIn)
			{
				match.isTypedIn = true;
			}

			matchesMap.insert(match.entry->data(TimeVisitedRole).toDateTime(), match);

			matchedEntries.append(match.entry);
		}
	}

	currentMatches = matchesMap.values();

	matchesMap.clear();

	for (int i = (currentMatches.count() - 1); i >= 0; --i)
	{
		allMatches.append(currentMatches.at(i));
	}

	return allMatches;
}
void QgsMapToolNodeTool::createTopologyRubberBands( QgsVectorLayer* vlayer, const QList<QgsVertexEntry*> &vertexMap, int vertex )
{
  QMultiMap<double, QgsSnappingResult> currentResultList;
  QgsGeometry *geometry = mSelectedFeature->geometry();

  // snap from current vertex
  currentResultList.clear();
  vlayer->snapWithContext( vertexMap[vertex]->point(), ZERO_TOLERANCE, currentResultList, QgsSnapper::SnapToVertex );
  QMultiMap<double, QgsSnappingResult>::iterator resultIt =  currentResultList.begin();

  for ( ; resultIt != currentResultList.end(); ++resultIt )
  {
    // move all other
    if ( mSelectedFeature->featureId() != resultIt.value().snappedAtGeometry )
    {
      if ( mTopologyMovingVertexes.contains( resultIt.value().snappedAtGeometry ) )
      {
        if ( mTopologyMovingVertexes[resultIt.value().snappedAtGeometry]->contains( resultIt.value().snappedVertexNr ) )
        {
          // skip vertex already exists in some rubberband
          continue;
        }
      }
      QgsRubberBand* trb = new QgsRubberBand( mCanvas, QGis::Line );
      mTopologyRubberBand.append( trb );
      int rbId = mTopologyRubberBand.size() - 1;
      trb->setWidth( 1 );
      trb->setColor( Qt::red );

      int tVertex = resultIt.value().snappedVertexNr;
      int tVertexBackup = -1, tVertexAfter = -1;
      int tVertexFirst = tVertex; // vertex number to check for cycling
      QgsFeature topolFeature;

      vlayer->getFeatures( QgsFeatureRequest().setFilterFid( resultIt.value().snappedAtGeometry ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( topolFeature );
      QgsGeometry* topolGeometry = topolFeature.geometry();

      while ( tVertex != -1 ) // looking for first vertex to rubberband
      {
        tVertexBackup = tVertex;
        topolGeometry->adjacentVertices( tVertex, tVertex, tVertexAfter );
        if ( tVertex == -1 || tVertex == tVertexFirst )
          break; // check if this is not first vertex of the feature or cycling error
        // if closest vertex is not from selected feature or is not selected end
        double dist;
        QgsPoint point = topolGeometry->vertexAt( tVertex );
        int at, before, after;
        geometry->closestVertex( point, at, before, after, dist );
        if ( dist > ZERO_TOLERANCE || !vertexMap[at]->isSelected() ) // problem with double precision
        {
          break; // found first vertex
        }
      }

      int movingPointIndex = 0;
      Vertexes* movingPoints = new Vertexes();
      Vertexes* addedPoints = new Vertexes();
      if ( mTopologyMovingVertexes.contains( resultIt.value().snappedAtGeometry ) )
      {
        addedPoints = mTopologyMovingVertexes[ resultIt.value().snappedAtGeometry ];
      }
      if ( tVertex == -1 ) // adding first point if needed
      {
        tVertex = tVertexBackup;
      }
      else
      {
        trb->addPoint( toMapCoordinates( vlayer, topolGeometry->vertexAt( tVertex ) ) );
        if ( tVertex == tVertexFirst ) // cycle first vertex need to be added also
        {
          movingPoints->insert( movingPointIndex );
        }
        movingPointIndex = 1;
        topolGeometry->adjacentVertices( tVertex, tVertexAfter, tVertex );
      }

      while ( tVertex != -1 )
      {
        // if closest vertex is not from selected feature or is not selected end
        double dist;
        QgsPoint point = topolGeometry->vertexAt( tVertex );
        int at, before, after;
        geometry->closestVertex( point, at, before, after, dist );
        // find first no matching vertex
        if ( dist > ZERO_TOLERANCE || !vertexMap[at]->isSelected() ) // problem with double precision
        {
          trb->addPoint( toMapCoordinates( vlayer, topolGeometry->vertexAt( tVertex ) ) );
          break; // found first vertex
        }
        else // add moving point to rubberband
        {
          if ( addedPoints->contains( tVertex ) )
            break; // just preventing to circle
          trb->addPoint( toMapCoordinates( vlayer, topolGeometry->vertexAt( tVertex ) ) );
          movingPoints->insert( movingPointIndex );
          movingPointIndex++;
          addedPoints->insert( tVertex );
        }
        topolGeometry->adjacentVertices( tVertex, tVertexAfter, tVertex );
      }
      mTopologyMovingVertexes.insert( resultIt.value().snappedAtGeometry, addedPoints );
      mTopologyRubberBandVertexes.insert( rbId, movingPoints );
    }
  }
}
Exemple #4
0
int QgsSnapper::snapMapPoint( const QgsPoint& mapCoordPoint, QList<QgsSnappingResult>& snappingResult, const QList<QgsPoint>& excludePoints )
{
  snappingResult.clear();

  QMultiMap<double, QgsSnappingResult> snappingResultList;//all snapping results
  QMultiMap<double, QgsSnappingResult> currentResultList; //snapping results of examined layer

  //start point in (output) map coordinates

  QgsPoint layerCoordPoint; //start point in layer coordinates
  QgsSnappingResult newResult;

  QList<QgsSnapper::SnapLayer>::iterator snapLayerIt;
  for ( snapLayerIt = mSnapLayers.begin(); snapLayerIt != mSnapLayers.end(); ++snapLayerIt )
  {
    if ( !snapLayerIt->mLayer->hasGeometryType() )
      continue;

    currentResultList.clear();
    //transform point from map coordinates to layer coordinates
    layerCoordPoint = mMapSettings.mapToLayerCoordinates( snapLayerIt->mLayer, mapCoordPoint );

    double tolerance = QgsTolerance::toleranceInMapUnits( snapLayerIt->mTolerance, snapLayerIt->mLayer, mMapSettings, snapLayerIt->mUnitType );
    if ( snapLayerIt->mLayer->snapWithContext( layerCoordPoint, tolerance,
         currentResultList, snapLayerIt->mSnapTo ) != 0 )
    {
      //error
    }

    //transform each result from layer crs to map crs (including distance)
    QMultiMap<double, QgsSnappingResult>::iterator currentResultIt;
    for ( currentResultIt = currentResultList.begin(); currentResultIt != currentResultList.end(); ++currentResultIt )
    {
      //for each snapping result: transform start point, snap point and other points into map coordinates to find out distance
      //store results in snapping result list
      newResult = currentResultIt.value();
      newResult.snappedVertex = mMapSettings.layerToMapCoordinates( snapLayerIt->mLayer, currentResultIt.value().snappedVertex );
      newResult.beforeVertex = mMapSettings.layerToMapCoordinates( snapLayerIt->mLayer, currentResultIt.value().beforeVertex );
      newResult.afterVertex = mMapSettings.layerToMapCoordinates( snapLayerIt->mLayer, currentResultIt.value().afterVertex );
      snappingResultList.insert( sqrt( newResult.snappedVertex.sqrDist( mapCoordPoint ) ), newResult );
    }
  }

  //excluded specific points from result
  cleanResultList( snappingResultList, excludePoints );

  //evaluate results according to snap mode
  QMultiMap<double, QgsSnappingResult>::iterator evalIt =  snappingResultList.begin();
  if ( evalIt == snappingResultList.end() )
  {
    return 0;
  }


  //Gives a priority to vertex snapping over segment snapping
  QgsSnappingResult returnResult = evalIt.value();
  for ( evalIt = snappingResultList.begin(); evalIt != snappingResultList.end(); ++evalIt )
  {
    if ( evalIt.value().snappedVertexNr != -1 )
    {
      returnResult = evalIt.value();
      snappingResultList.erase( evalIt );
      break;
    }
  }

  //We return the preferred result
  snappingResult.push_back( returnResult );

  if ( mSnapMode == QgsSnapper::SnapWithOneResult )
  {
    //return only a single  result, nothing more to do
  }
  else if ( mSnapMode == QgsSnapper::SnapWithResultsForSamePosition )
  {
    //take all snapping results within a certain tolerance because rounding differences may occur
    double tolerance = 0.000001;

    for ( evalIt = snappingResultList.begin(); evalIt != snappingResultList.end(); ++evalIt )
    {
      if ( returnResult.snappedVertex.sqrDist( evalIt.value().snappedVertex ) < tolerance*tolerance )
      {
        snappingResult.push_back( evalIt.value() );
      }
    }

  }

  else //take all results
  {
    for ( evalIt = snappingResultList.begin(); evalIt != snappingResultList.end(); ++evalIt )
    {
      snappingResult.push_back( evalIt.value() );
    }
  }

  return 0;
}
void QgsSelectedFeature::deleteSelectedVertexes()
{
  int nSelected = 0;
  foreach ( QgsVertexEntry *entry, mVertexMap )
  {
    if ( entry->isSelected() )
      nSelected++;
  }

  if ( nSelected == 0 )
    return;

  int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 );
  QMultiMap<double, QgsSnappingResult> currentResultList;

  mVlayer->beginEditCommand( QObject::tr( "Deleted vertices" ) );

  beginGeometryChange();

  int count = 0;
  for ( int i = mVertexMap.size() - 1; i > -1; i-- )
  {
    if ( mVertexMap[i]->isSelected() )
    {
      if ( mVertexMap[i]->equals() != -1 )
      {
        // to avoid try to delete some vertex twice
        mVertexMap[ mVertexMap[i]->equals()]->setSelected( false );
        nSelected--;
      }

      if ( topologicalEditing )
      {
        // snap from current vertex
        currentResultList.clear();
        mVlayer->snapWithContext( mVertexMap[i]->point(), ZERO_TOLERANCE, currentResultList, QgsSnapper::SnapToVertex );
      }

      // only last update should trigger the geometry update
      // as vertex selection gets lost on the update
      if ( --nSelected == 0 )
        endGeometryChange();

      if ( !mVlayer->deleteVertex( mFeatureId, i ) )
      {
        count = 0;
        QgsDebugMsg( QString( "Deleting vertex %1 failed - resetting" ).arg( i ) );
        break;
      }

      count++;

      if ( topologicalEditing )
      {
        QMultiMap<double, QgsSnappingResult>::iterator resultIt =  currentResultList.begin();

        for ( ; resultIt != currentResultList.end(); ++resultIt )
        {
          // move all other
          if ( mFeatureId !=  resultIt.value().snappedAtGeometry )
            mVlayer->deleteVertex( resultIt.value().snappedAtGeometry, resultIt.value().snappedVertexNr );
        }
      }
    }
  }

  if ( count > 0 )
  {
    mVlayer->endEditCommand();
  }
  else
  {
    mVlayer->destroyEditCommand();
  }
}
void ThesaurusDatabaseType::clear(){
	if (buffer) delete buffer;
	buffer=0;
	thesaurus.clear();
	fileName.clear();
}
void QgsSelectedFeature::deleteSelectedVertexes()
{
  int nSelected = 0;
  Q_FOREACH ( QgsVertexEntry *entry, mVertexMap )
  {
    if ( entry->isSelected() )
      nSelected++;
  }

  if ( nSelected == 0 )
    return;

  int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 );
  QMultiMap<double, QgsSnappingResult> currentResultList;

  mVlayer->beginEditCommand( QObject::tr( "Deleted vertices" ) );

  beginGeometryChange();

  bool success = false;
  QgsVectorLayer::EditResult res = QgsVectorLayer::Success;
  for ( int i = mVertexMap.size() - 1; i > -1 && nSelected > 0; i-- )
  {
    if ( mVertexMap.at( i )->isSelected() )
    {
      if ( topologicalEditing )
      {
        // snap from current vertex
        currentResultList.clear();
        mVlayer->snapWithContext( mVertexMap.at( i )->pointV1(), ZERO_TOLERANCE, currentResultList, QgsSnapper::SnapToVertex );
      }

      // only last update should trigger the geometry update
      // as vertex selection gets lost on the update
      if ( --nSelected == 0 )
        endGeometryChange();

      if ( res != QgsVectorLayer::EmptyGeometry )
        res = mVlayer->deleteVertexV2( mFeatureId, i );

      if ( res != QgsVectorLayer::Success && res != QgsVectorLayer::EmptyGeometry )
      {
        success = false;
        QgsDebugMsg( QString( "Deleting vertex %1 failed - resetting" ).arg( i ) );
        break;
      }

      success = true;

      if ( topologicalEditing )
      {
        QMultiMap<double, QgsSnappingResult>::iterator resultIt =  currentResultList.begin();

        for ( ; resultIt != currentResultList.end(); ++resultIt )
        {
          // move all other
          if ( mFeatureId !=  resultIt.value().snappedAtGeometry )
            mVlayer->deleteVertexV2( resultIt.value().snappedAtGeometry, resultIt.value().snappedVertexNr );
        }
      }

      if ( res == QgsVectorLayer::EmptyGeometry )
      {
        //geometry has been cleared as a result of deleting vertices (eg not enough vertices left to leave a valid geometry),
        //so nothing more to do
        QgsGeometry empty;
        geometryChanged( mFeatureId, empty );
        break;
      }
    }
  }

  if ( nSelected > 0 )
    endGeometryChange();

  if ( success )
  {
    mVlayer->endEditCommand();
  }
  else
  {
    mVlayer->destroyEditCommand();
  }
}
QList<BookmarksModel::BookmarkMatch> BookmarksModel::findBookmarks(const QString &prefix) const
{
	QList<BookmarksItem*> matchedBookmarks;
	QList<BookmarksModel::BookmarkMatch> allMatches;
	QList<BookmarksModel::BookmarkMatch> currentMatches;
	QMultiMap<QDateTime, BookmarksModel::BookmarkMatch> matchesMap;
	QHash<QString, BookmarksItem*>::const_iterator keywordsIterator;

	for (keywordsIterator = m_keywords.constBegin(); keywordsIterator != m_keywords.constEnd(); ++keywordsIterator)
	{
		if (keywordsIterator.key().startsWith(prefix, Qt::CaseInsensitive))
		{
			BookmarksModel::BookmarkMatch match;
			match.bookmark = keywordsIterator.value();
			match.match = keywordsIterator.key();

			matchesMap.insert(match.bookmark->data(TimeVisitedRole).toDateTime(), match);

			matchedBookmarks.append(match.bookmark);
		}
	}

	currentMatches = matchesMap.values();

	matchesMap.clear();

	for (int i = (currentMatches.count() - 1); i >= 0; --i)
	{
		allMatches.append(currentMatches.at(i));
	}

	QHash<QUrl, QList<BookmarksItem*> >::const_iterator urlsIterator;

	for (urlsIterator = m_urls.constBegin(); urlsIterator != m_urls.constEnd(); ++urlsIterator)
	{
		if (urlsIterator.value().isEmpty() || matchedBookmarks.contains(urlsIterator.value().first()))
		{
			continue;
		}

		const QString result = Utils::matchUrl(urlsIterator.key(), prefix);

		if (!result.isEmpty())
		{
			BookmarkMatch match;
			match.bookmark = urlsIterator.value().first();
			match.match = result;

			matchesMap.insert(match.bookmark->data(TimeVisitedRole).toDateTime(), match);

			matchedBookmarks.append(match.bookmark);
		}
	}

	currentMatches = matchesMap.values();

	matchesMap.clear();

	for (int i = (currentMatches.count() - 1); i >= 0; --i)
	{
		allMatches.append(currentMatches.at(i));
	}

	return allMatches;
}
void QgsMapRendererParallelJob::renderLayerStatic( LayerRenderJob& job )
{
  if ( job.context.renderingStopped() )
    return;

  if ( job.cached )
    return;

#ifdef QGISDEBUG
  static QSet<QString> running;
  static QMultiMap<int, QString> elapsed;

  QSettings settings;
  bool log = settings.value( "/Map/logCanvasRefreshEvent", false ).toBool();

  QTime t;
  t.start();
  QgsDebugMsg( QString( "job %1 start" ).arg( reinterpret_cast< ulong >( &job ), 0, 16 ) );
  if ( log )
  {
    QgsMessageLog::logMessage( tr( "Layer %1 job started" ).arg( job.layerId ), tr( "Rendering" ) );
    Q_ASSERT( !running.contains( job.layerId ) );
    running << job.layerId;
  }
#endif

  try
  {
    job.renderer->render();
  }
  catch ( QgsException & e )
  {
    QgsDebugMsg( "Caught unhandled QgsException: " + e.what() );
  }
  catch ( std::exception & e )
  {
    QgsDebugMsg( "Caught unhandled std::exception: " + QString::fromAscii( e.what() ) );
  }
  catch ( ... )
  {
    QgsDebugMsg( "Caught unhandled unknown exception" );
  }

#ifdef QGISDEBUG
  int tt = t.elapsed();

  QgsDebugMsg( QString( "job %1 end [%2 ms]" ).arg( reinterpret_cast< ulong >( &job ), 0, 16 ).arg( tt ) );

  if ( log )
  {
    running.remove( job.layerId );
    elapsed.insert( tt, job.layerId );

    QgsMessageLog::logMessage( tr( "Layer %1 job ended (%2 ms; still running:%3)" ).arg( job.layerId ).arg( tt ).arg( QStringList( running.values() ).join( ", " ) ), tr( "Rendering" ) );
    if ( running.isEmpty() )
    {
      QList<int> tt( elapsed.keys() );
      qSort( tt.begin(), tt.end(), qGreater<int>() );
      Q_FOREACH ( int t, tt )
      {
        QgsMessageLog::logMessage( tr( "%1 ms: %2" ).arg( t ).arg( QStringList( elapsed.values( t ) ).join( ", " ) ), tr( "Rendering" ) );
      }
      QgsMessageLog::logMessage( "---", tr( "Rendering" ) );
      elapsed.clear();
    }
Exemple #10
0
void updateScancodes()
{
#ifdef QT_MAC_USE_COCOA
    TISInputSourceRef layout = TISCopyCurrentKeyboardLayoutInputSource();
    if (!layout) {
        qWarning() << "Error retrieving current layout";
        return;
    }
    if (layout == lastLayout) {
        CFRelease(layout);
    } else {
        // keyboard layout changed
#ifndef NDEBUG
        const void *name = TISGetInputSourceProperty(layout, kTISPropertyLocalizedName);
        qDebug() << "Layout changed to: " << CFStringGetCStringPtr((CFStringRef)name, 0);
#endif
        lastLayout = layout;
        scancodes.clear();

        CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(layout,
                                                kTISPropertyUnicodeKeyLayoutData));
        const UCKeyboardLayout *ucData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : 0;

        if (!ucData) {
            qWarning() << "Error retrieving current layout character data";
            return;
        }

        for (int i = 0; i < 128; ++i) {
            UInt32 tmpState = 0;
            UniChar str[4];
            UniCharCount actualLength = 0;
            OSStatus err = UCKeyTranslate(ucData, i, kUCKeyActionDown, 0, LMGetKbdType(),
                                          kUCKeyTranslateNoDeadKeysMask, &tmpState, 4, &actualLength, str);
            if (err != noErr) {
                qWarning() << "Error translating unicode key" << err;
            } else {
                if (str[0] && str[0] != kFunctionKeyCharCode) {
                    scancodes.insert(str[0], i);
                }
            }
        }
    }
#else
    KeyboardLayoutRef layout;
    if (KLGetCurrentKeyboardLayout(&layout) != noErr) {
        qWarning() << "Error retrieving current layout";
    }
    if (layout != lastLayout) {
#ifndef NDEBUG
        void *name;
        KLGetKeyboardLayoutProperty(layout, kKLName, const_cast<const void **>(&name));
        qDebug() << "Layout changed to: " << CFStringGetCStringPtr((CFStringRef) name, 0);
#endif
        lastLayout = layout;
        scancodes.clear();
        void *kchr;
        if (KLGetKeyboardLayoutProperty(layout, kKLKCHRData, const_cast<const void **>(&kchr)) != noErr) {
            qWarning() << "Couldn't load active keyboard layout";
        } else {
            for (int i = 0; i < 128; i++) {
                UInt32 tmpState = 0;
                UInt32 chr = KeyTranslate(kchr, i, &tmpState);
                if (chr && chr != kFunctionKeyCharCode) {
                    scancodes.insert(chr, i);
                }
            }
        }
    }
#endif
}