QUrl QgsVirtualLayerDefinition::toUrl() const
{
  QUrl url;
  url.setPath( filePath() );

  foreach ( const QgsVirtualLayerDefinition::SourceLayer& l, sourceLayers() )
  {
    if ( l.isReferenced() )
      url.addQueryItem( "layer_ref", QString( "%1:%2" ).arg( l.reference(), l.name() ) );
    else
      url.addQueryItem( "layer", QString( "%1:%4:%2:%3" ) // the order is important, since the 4th argument may contain '%2' as well
                        .arg( l.provider(),
                              QString( QUrl::toPercentEncoding( l.name() ) ),
                              l.encoding(),
                              QString( QUrl::toPercentEncoding( l.source() ) ) ) );
  }

  if ( !query().isEmpty() )
  {
    url.addQueryItem( "query", query() );
  }

  if ( !uid().isEmpty() )
    url.addQueryItem( "uid", uid() );

  if ( geometryWkbType() == QgsWKBTypes::NoGeometry )
    url.addQueryItem( "nogeometry", "" );
  else if ( !geometryField().isEmpty() )
  {
    if ( hasDefinedGeometry() )
      url.addQueryItem( "geometry", QString( "%1:%2:%3" ).arg( geometryField() ). arg( geometryWkbType() ).arg( geometrySrid() ).toUtf8() );
    else
      url.addQueryItem( "geometry", geometryField() );
  }

  for ( int i = 0; i < fields().count(); i++ )
  {
    const QgsField& f = fields()[i];
    if ( f.type() == QVariant::Int )
      url.addQueryItem( "field", f.name() + ":int" );
    else if ( f.type() == QVariant::Double )
      url.addQueryItem( "field", f.name() + ":real" );
    else if ( f.type() == QVariant::String )
      url.addQueryItem( "field", f.name() + ":text" );
  }

  return url;
}
QUrl QgsVirtualLayerDefinition::toUrl() const
{
  QUrl url;
  if ( !filePath().isEmpty() )
    url = QUrl::fromLocalFile( filePath() );

  Q_FOREACH ( const QgsVirtualLayerDefinition::SourceLayer& l, sourceLayers() )
  {
    if ( l.isReferenced() )
      url.addQueryItem( QStringLiteral( "layer_ref" ), QStringLiteral( "%1:%2" ).arg( l.reference(), l.name() ) );
    else
      url.addEncodedQueryItem( "layer", QStringLiteral( "%1:%4:%2:%3" ) // the order is important, since the 4th argument may contain '%2' as well
                               .arg( l.provider(),
                                     QString( QUrl::toPercentEncoding( l.name() ) ),
                                     l.encoding(),
                                     QString( QUrl::toPercentEncoding( l.source() ) ) ).toUtf8() );
  }

  if ( !query().isEmpty() )
  {
    url.addQueryItem( QStringLiteral( "query" ), query() );
  }

  if ( !uid().isEmpty() )
    url.addQueryItem( QStringLiteral( "uid" ), uid() );

  if ( geometryWkbType() == QgsWkbTypes::NoGeometry )
    url.addQueryItem( QStringLiteral( "nogeometry" ), QLatin1String( "" ) );
  else if ( !geometryField().isEmpty() )
  {
    if ( hasDefinedGeometry() )
      url.addQueryItem( QStringLiteral( "geometry" ), QStringLiteral( "%1:%2:%3" ).arg( geometryField() ). arg( geometryWkbType() ).arg( geometrySrid() ).toUtf8() );
    else
      url.addQueryItem( QStringLiteral( "geometry" ), geometryField() );
  }

  Q_FOREACH ( const QgsField& f, fields() )
  {
    if ( f.type() == QVariant::Int )
      url.addQueryItem( QStringLiteral( "field" ), f.name() + ":int" );
    else if ( f.type() == QVariant::Double )
      url.addQueryItem( QStringLiteral( "field" ), f.name() + ":real" );
    else if ( f.type() == QVariant::String )
      url.addQueryItem( QStringLiteral( "field" ), f.name() + ":text" );
  }

  return url;
}